Ohjelmointi

Java Tip 60: Bittikarttatiedostojen tallentaminen Java-tiedostoon

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än BitmapFileHeader 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.