Tämä vinkki täydentää Java Tip 43 -ohjelmaa, joka osoitti bittikarttatiedostojen lataamisen Java-sovelluksiin. Tässä kuussa seuraan opetusohjelmaa kuvien tallentamisesta 24-bittisiin bittikarttatiedostoihin ja koodinpätkää, jonka avulla voit kirjoittaa bittikarttatiedoston kuvaobjektista.
Kyky luoda bittikarttatiedosto avaa monia ovia, jos työskentelet Microsoft Windows -ympäristössä. Esimerkiksi viimeisessä projektissani minun piti liittää Java Java-käyttöjärjestelmään Microsoft Accessin kanssa. Java-ohjelman avulla käyttäjä voi piirtää kartan ruudulle. Kartta painettiin sitten Microsoft Access -raportissa. Koska Java ei tue OLE: tä, ainoa ratkaisuni oli luoda kartan bittikartatiedosto ja kertoa Microsoft Access -raportille, mistä se noudetaan. Jos olet joskus joutunut kirjoittamaan sovelluksen kuvan lähettämiseksi leikepöydälle, tästä vinkistä voi olla hyötyä sinulle - varsinkin jos nämä tiedot välitetään toiselle Windows-sovellukselle.
Bittikarttatiedoston muoto
Bittikarttatiedostomuoto tukee 4-bittistä RLE: tä (ajonpituuden koodausta) sekä 8- ja 24-bittistä koodausta. Koska kyseessä on vain 24-bittinen muoto, katsotaanpa tiedoston rakenne.
Bittikarttatiedosto on jaettu kolmeen osaan. Olen asettanut ne sinulle alla.
Osa 1: Bittikarttatiedoston otsikko
Tämä otsikko sisältää tietoja bittikarttatiedoston tyypin koosta ja asettelusta. Rakenne on seuraava (otettu C-kielen rakenteen määritelmästä):
typedef struct tagBITMAPFILEHEADER {UINT bfType; DWORD bfSize; UINT bfReserved1; UINT bfReserved2; DWORD bfOffBits; } BITMAPFILEHEADER;
Tässä on kuvaus yllä olevien luettelo-koodielementeistä:
bfType
: Ilmaisee tiedoston tyypin ja asetetaan aina BM: ksi.bfKoko
: Määrittää koko tiedoston koon tavuina.bfVarattu 1
: Varattu - täytyy olla 0.bfVarattu 2
: Varattu - täytyy olla 0.bfOffBits
: Määrittää tavun siirtymänBitmapFileHeader
kuvan alkuun.
Täällä olet nähnyt, että bittikartan otsikon tarkoituksena on tunnistaa bittikarttatiedosto. Jokainen ohjelma, joka lukee bittikarttatiedostoja, käyttää bittikartan otsikkoa tiedostojen vahvistamiseen.
Osa 2: Bittikartan tietotunniste
Seuraava otsikko, nimeltään tietotunniste, sisältää kaikki kuvan ominaisuudet.
Näin määrität tiedot Windows 3.0 (tai uudempi) -laitteesta riippumattoman bittikartan (DIB) ulottuvuudesta ja värimuodosta:
typedef struct tagBITMAPINFOHEADER {DWORD biSize; PITKÄ bi-leveys; PITKÄ biKorkeus; WORD biKoneet; SANA biBitCount; DWORD bi-pakkaus; DWORD biSizeImage; PITKÄ biXPelsPerMeter; PITKÄ biYPelsPerMeter; DWORD biClrUsed; DWORD biClrTärkeää; } BITMAPINFOHEADER;
Jokainen yllä olevan koodiluettelon osa on kuvattu alla:
biKoko
: MäärittääBITMAPINFOHEADER
rakenne.biWidth
: Määrittää bittikartan leveyden pikseleinä.biKorkeus
: Määrittää bittikartan korkeuden pikseleinä.biKoneet
: Määrittää kohdelaitteen tasojen määrän. Tämän jäsenen on oltava 1.biBitCount
: Määrittää bittien määrän pikseliä kohti. Tämän arvon on oltava 1, 4, 8 tai 24.bi-pakkaus
: Määrittää pakatun bittikartan pakkaustyypin. 24-bittisessä muodossa muuttuja asetetaan arvoon 0.- biSizeImage: Määrittää kuvan tavuina. On kelvollista asettaa tämä jäsen 0: ksi, jos bittikartta on
BI_RGB
muoto. - biXPelsPerMeter: Määrittää bittikartan kohdelaitteen horisontaalisen resoluution pikseleinä metriä kohti. Sovellus voi käyttää tätä arvoa valitakseen bittikartan resurssiryhmästä, joka parhaiten vastaa nykyisen laitteen ominaisuuksia.
- biYPelsPerMeter: Määrittää bittikartan kohdelaitteen pystysuuntaisen resoluution pikseleinä metriä kohti.
- biClrUsed: Määrittää bittikartan tosiasiallisesti käyttämien väritaulukoiden väriindeksien määrän. Jos
biBitCount
on asetettu arvoon 24,biClrUsed
määrittää vertailuväritaulukon koon, jota käytetään optimoimaan Windowsin väripalettien suorituskyky. - biClrTärkeää: Määrittää bittikartan näyttämisen kannalta tärkeinä pidettyjen väriindeksien määrän. Jos tämä arvo on 0, kaikki värit ovat tärkeitä.
Nyt kaikki kuvan luomiseen tarvittavat tiedot on määritelty.
Osa 3: Kuva
24-bittisessä muodossa jokaista kuvan pikseliä edustaa kolmen tavun RGB-sarja, joka on tallennettu BRG: ksi. Jokainen skannausviiva on pehmustettu tasaiselle 4 tavun rajalle. Prosessin hieman monimutkaisemmaksi kuva tallennetaan alhaalta ylös, mikä tarkoittaa, että ensimmäinen skannausrivi on kuvan viimeinen skannausrivi. Seuraava kuva esittää molemmat otsikot (BITMAPHEADER
) ja (BITMAPINFOHEADER
) ja osa kuvasta. Jokainen osa on rajattu pystypalkilla:
0000000000 4D42 B536 0002 0000 0000 0036 0000 | 0028 0000000020 0000 0107 0000 00E0 0000 0001 0018 0000 0000000040 0000 B500 0002 0EC4 0000 0EC4 0000 0000 0000000060 0000 0000 0000 | FFFF FFFF FFFF FFFF FFFF 0000000100 FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF *
Nyt koodiin
Nyt kun tiedämme kaiken 24-bittisen bittikarttatiedoston rakenteesta, tässä on mitä olet odottanut: koodi kirjoittaa bittikarttatiedosto kuvaobjektista.
tuo java.awt. *; tuo java.io. *; tuo java.awt.image. *; julkinen luokka BMPFile laajentaa komponenttia {// --- yksityiset vakiot yksityinen lopullinen staattinen int BITMAPFILEHEADER_SIZE = 14; yksityinen lopullinen staattinen int BITMAPINFOHEADER_SIZE = 40; // --- yksityisen muuttujan ilmoitus // --- bittikarttatiedoston otsikko yksityinen tavu bitmapFileHeader [] = uusi tavu [14]; yksityinen tavu bfType [] = {'B', 'M'}; yksityinen int bfSize = 0; yksityinen int bfReserved1 = 0; yksityinen int bfReserved2 = 0; yksityinen int bfOffBits = BITMAPFILEHEADER_SIZE + BITMAPINFOHEADER_SIZE; // --- bittikartan tiedototsikon yksityinen tavu bittikarttaInfoHeader [] = uusi tavu [40]; yksityinen int biSize = BITMAPINFOHEADER_SIZE; yksityinen int biWidth = 0; yksityinen int biKorkeus = 0; yksityiset int-tasot = 1; yksityinen int biBitCount = 24; yksityinen int biokompressio = 0; yksityinen int biSizeImage = 0x030000; yksityinen int biXPelsPerMeter = 0x0; yksityinen int biYPelsPerMeter = 0x0; yksityinen int biClrUsed = 0; yksityinen int biClrTärkeää = 0; // --- Bitmap raw data private int bitmap []; // --- Tiedosto-osio yksityinen FileOutputStream fo; // --- Oletusrakentaja public BMPFile () {} public void saveBitmap (String parFilename, Image parImage, int parWidth, int parHeight) {try {fo = new FileOutputStream (parFilename); save (parImage, parWidth, parHeight); fo. sulje (); } catch (Exception saveEx) {saveEx.printStackTrace (); }} / * * SaveMethod on prosessin päämenetelmä. Tämä menetelmä * kutsuu convertImage-menetelmää muuntamaan muistikuvan * tavua olevaksi taulukoksi; method writeBitmapFileHeader luo ja kirjoittaa * bittikarttatiedoston otsikon; writeBitmapInfoHeader luo * tietootsikon; ja writeBitmap kirjoittaa kuvan. * * / private void save (Kuvan parImage, int parWidth, int parHeight) {kokeile {convertImage (parImage, parWidth, parHeight); writeBitmapFileHeader (); writeBitmapInfoHeader (); writeBitmap (); } catch (Exception saveEx) {saveEx.printStackTrace (); }} / * * convertImage muuntaa muistikuvan bittikarttamuodoksi (BRG). * Se laskee myös joitain tietoja bittikartan tietotunnisteelle. * * / private boolean convertImage (Kuvan parImage, int parWidth, int parHeight) {int pad; bittikartta = uusi int [parWidth * parHeight]; PixelGrabber pg = uusi PixelGrabber (parImage, 0, 0, parWidth, parHeight, bitmap, 0, parWidth); kokeile {pg.grabPixels (); } catch (InterruptedException e) {e.printStackTrace (); paluu (väärä); } pad = (4 - ((parWidth * 3)% 4)) * parHeight; biSizeImage = ((parWidth * parHeight) * 3) + pad; bfSize = biSizeImage + BITMAPFILEHEADER_SIZE + BITMAPINFOHEADER_SIZE; biWidth = parWidth; biHeight = parHeight; paluu (tosi); } / * * writeBitmap muuntaa pikselihahmosta palautetun kuvan * tarvittavaan muotoon. Muista: skannausviivat käännetään * bittikarttatiedostona! * * Jokainen skannausviiva on täytettävä tasaiselle 4 tavun rajalle. * / private void writeBitmap () {int koko; int-arvo; int j; int i; int rowCount; int riviIndex; int lastRowIndex; int pad; int padCount; tavu rgb [] = uusi tavu [3]; koko = (biWidth * biHeight) - 1; tyyny = 4 - ((biWidth * 3)% 4); if (pad == 4) // <==== Vikakorjauslaji = 0; // <==== VirheenkorjausriviLuku = 1; padCount = 0; rowIndex = koko - biWidth; lastRowIndex = rowIndex; kokeile {for (j = 0; j> 8) & 0xFF); rgb [2] = (tavu) ((arvo >> 16) & 0xFF); fo.write (rgb); jos (rowCount == biWidth) {padCount + = pad; (i = 1; i> 8) & 0x00FF); tuotto (retValue); } / * * * intToDWord muuntaa int-sanan kaksoissanaksi, jossa return * -arvo tallennetaan 4-tavuiseen matriisiin. * * / yksityinen tavu [] intToDWord (int parValue) {tavu retValue [] = uusi tavu [4]; retValue [0] = (tavu) (parValue & 0x00FF); retValue [1] = (tavu) ((parValue >> 8) & 0x000000FF); retValue [2] = (tavu) ((parValue >> 16) & 0x000000FF); retValue [3] = (tavu) ((parValue >> 24) & 0x000000FF); tuotto (retValue); }}
Johtopäätös
Siinä kaikki siinä on. Olen varma, että tämä luokka on sinulle erittäin hyödyllinen, koska JDK 1.1.6: sta lähtien Java ei tue kuvien tallentamista missään suositussa muodossa. JDK 1.2 tarjoaa tukea JPEG-kuvien luomiseen, mutta ei tukea bittikartoille. Joten tämä luokka täyttää silti aukon JDK 1.2: ssa.
Jos pelaat tämän luokan kanssa ja löydät tapoja parantaa sitä, ilmoita siitä minulle! Sähköpostini näkyy alla, yhdessä elämäni kanssa.
Jean-Pierre Dubé on riippumaton Java-konsultti. Hän perusti vuonna 1988 rekisteröidyn Infocomin. Sittemmin Infocom on kehittänyt useita räätälöityjä sovelluksia valmistuksesta, asiakirjojen hallinnasta ja laajamittaisesta sähköjohdon hallinnasta. Hänellä on laaja ohjelmointikokemus C: ssä, Visual Basicissa ja viimeksi Java-kielessä, joka on nyt hänen yrityksensä ensisijainen kieli. Yksi Infocomin viimeaikaisista projekteista on kaavio-sovellusliittymä, jonka pitäisi tulla saataville beta-julkaisuna pian.Tämän tarinan "Java Tip 60: Bittikarttatiedostojen tallentaminen Java-tiedostoon" julkaisi alun perin JavaWorld.