Programavimas

„Java“ patarimas 60: bitų žemėlapių failų išsaugojimas „Java“

Šis patarimas papildo „Java Tip 43“, kuris parodė bitų žemėlapių failų įkėlimo į „Java“ programas procesą. Šį mėnesį aš vadovaujuosi mokymo programa, kaip išsaugoti vaizdus 24 bitų bitmap failuose, ir kodo fragmentą, kurį galite naudoti norėdami parašyti bitmap failą iš vaizdo objekto.

Galimybė sukurti bitų žemėlapio failą atveria daug durų, jei dirbate „Microsoft Windows“ aplinkoje. Pavyzdžiui, vykdydamas savo paskutinį projektą turėjau susieti „Java“ su „Microsoft Access“. „Java“ programa leido vartotojui piešti žemėlapį ekrane. Žemėlapis buvo atspausdintas „Microsoft Access“ ataskaitoje. Kadangi „Java“ nepalaiko OLE, mano vienintelis sprendimas buvo sukurti žemėlapio bitmap failą ir pasakyti „Microsoft Access“ ataskaitai, kur jį pasiimti. Jei kada nors teko rašyti programą, kad galėtumėte siųsti vaizdą į mainų sritį, šis patarimas gali būti jums naudingas - ypač jei ši informacija perduodama kitai „Windows“ programai.

„Bitmap“ failo formatas

Bitų žemėlapio failo formatas palaiko 4 bitų RLE (veikimo trukmės kodavimą), taip pat 8 ir 24 bitų kodavimą. Kadangi mes susiduriame tik su 24 bitų formatu, pažvelkime į failo struktūrą.

Taškų žemėlapio failas yra padalintas į tris dalis. Aš juos išdėstiau jums žemiau.

1 skyrius: Bitmap failo antraštė

Šioje antraštėje yra informacijos apie bitų žemėlapio failo tipo dydį ir išdėstymą. Struktūra yra tokia (paimta iš C kalbos struktūros apibrėžimo):

typedef struct tagBITMAPFILEHEADER {UINT bfType; DWORD bfSize; UINT bfReserved1; UINT bfReserved2; DWORD bfOffBits; } BITMAPFILEHEADER; 

Štai kodo elementų aprašymas iš anksčiau pateikto sąrašo:

  • „bfType“: Nurodo failo tipą ir visada yra nustatytas kaip BM.
  • bfSize: Nurodo viso failo dydį baitais.
  • bfReserved1: Rezervuota - turi būti nustatyta į 0.
  • bfReserved2: Rezervuota - turi būti nustatyta į 0.
  • „bfOffBits“: Nurodo baito poslinkį iš „BitmapFileHeader“ iki vaizdo pradžios.

Čia matėte, kad bitmap antraštės tikslas yra identifikuoti bitmap failą. Kiekviena programa, skaitanti taškinių žemėlapių failus, failų patvirtinimui naudoja bitmap antraštę.

2 skyrius: Bitmap informacijos antraštė

Kita antraštė, vadinama informacijos antraštė, yra visos paties vaizdo savybės.

Štai kaip nurodote informaciją apie „Windows 3.0“ (ar naujesnės) nuo įrenginio nepriklausomos bitų schemos (DIB) matmenis ir spalvų formatą:

typedef struct tagBITMAPINFOHEADER {DWORD biSize; ILGAS biWidth; ILGAS biAukštis; ŽODIS biPlanes; ŽODIS biBitCount; „DWORD biCompression“; „DWORD biSizeImage“; LONG biXPelsPerMeter; LONG biYPelsPerMeter; DWORD biClrUsed; DWORD biClrSvarbu; } BITMAPINFOHEADER; 

Kiekvienas aukščiau nurodyto kodų sąrašo elementas aprašytas toliau:

  • biSize: Nurodo, kokio baitų reikalauja BITMAPINFOHEADER struktūra.
  • biWidth: Nurodo taškų plotį pikseliais.
  • biAukštis: Nurodo taškų aukščio taškais.
  • lėktuvai: Nurodo tikslinio įrenginio plokštumų skaičių. Šis narys turi būti nustatytas į 1.
  • „biBitCount“: Nurodo bitų skaičių pikselyje. Ši vertė turi būti 1, 4, 8 arba 24.
  • bi kompresija: Nurodo suglaudinto bitų žemėlapio glaudinimo tipą. 24 bitų formatu kintamasis nustatomas į 0.
  • „biSizeImage“: nurodo vaizdo dydį baitais. Galima nustatyti šį narį į 0, jei bitų schema yra BI_RGB formatas.
  • „biXPelsPerMeter“: nurodo taškinio įrenginio horizontaliąją skiriamąją gebą, skiriamą bitų žemėlapiui. Programa gali naudoti šią vertę norėdama pasirinkti bitų žemėlapį iš išteklių grupės, kuri geriausiai atitinka dabartinio įrenginio charakteristikas.
  • „biYPelsPerMeter“: nurodo tikslinio įtaiso, skirto bitų žemėlapiui, vertikaliąją skiriamąją gebą pikseliais metre.
  • „biClrUsed“: nurodo spalvų indeksų skaičių spalvų lentelėje, kurią faktiškai naudoja bitmap. Jei „biBitCount“ yra nustatytas į 24, biClrUsed nurodo atskaitos spalvų lentelės, naudojamos optimizuoti „Windows“ spalvų paletės našumą, dydį.
  • „biClrImportant“: nurodo spalvų indeksų, kurie laikomi svarbiais rodant bitų žemėlapį, skaičių. Jei ši vertė yra 0, visos spalvos yra svarbios.

Dabar apibrėžta visa informacija, reikalinga vaizdui sukurti.

3 skyrius: Vaizdas

24 bitų formatu kiekvieną vaizdo pikselį vaizduoja trijų RGB baitų serija, saugoma kaip BRG. Kiekviena nuskaitymo linija paminkštinta iki net 4 baitų ribos. Norėdami šiek tiek apsunkinti procesą, vaizdas saugomas iš apačios į viršų, o tai reiškia, kad pirmoji nuskaitymo eilutė yra paskutinė paveikslėlio nuskaitymo linija. Šiame paveikslėlyje parodytos abi antraštės (BITMAPHEADER) ir (BITMAPINFOHEADER) ir atvaizdo dalis. Kiekvieną skyrių riboja vertikali juosta:

 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 * 

Dabar - prie kodo

Dabar, kai mes viską žinome apie 24 bitų bitmap failo struktūrą, štai ko jūs laukėte: kodas, skirtas parašyti bitmap failą iš vaizdo objekto.

importuoti java.awt. *; importuoti java.io. *; importuoti java.awt.image. *; viešoji klasė „BMPFile“ išplečia komponentą {// --- privačios konstantos privati ​​galutinė statinė int BITMAPFILEHEADER_SIZE = 14; privati ​​galutinė statinė int BITMAPINFOHEADER_SIZE = 40; // --- privataus kintamojo deklaracija // --- bitmap failo antraštė privatus baitas bitmapFileHeader [] = naujas baitas [14]; privatus baitas bfType [] = {'B', 'M'}; privatus int bfSize = 0; privatus int bfReserved1 = 0; privatus int bfReserved2 = 0; privatus int bfOffBits = BITMAPFILEHEADER_SIZE + BITMAPINFOHEADER_SIZE; // --- Bitmap informacijos antraštės privatus baitas bitmapInfoHeader [] = naujas baitas [40]; privatus int biSize = BITMAPINFOHEADER_SIZE; privatus int biWidth = 0; privatus int biHeight = 0; privatūs int biPlanes = 1; privatus int biBitCount = 24; private int biCompression = 0; privatus int biSizeImage = 0x030000; privatus int biXPelsPerMeter = 0x0; privatus int biYPelsPerMeter = 0x0; privatus int biClrUsed = 0; privatus int biClrSvarbu = 0; // --- Bitmap raw data private int bitmap []; // --- Failų skyrius privatus FileOutputStream fo; // --- numatytasis konstruktoriaus viešasis BMPFile () {} public void saveBitmap (String parFilename, Image parImage, int parWidth, int parHeight) {try {fo = new FileOutputStream (parFilename); išsaugoti (parImage, parWidth, parHeight); fo.uždaryti (); } gaudyti (Išimtis saveEx) {saveEx.printStackTrace (); }} / * * „SaveMethod“ yra pagrindinis proceso metodas. Šis metodas * iškvies „convertImage“ metodą, kad paverstų atminties vaizdą į * baitų masyvą; metodas writeBitmapFileHeader sukuria ir rašo * bitmap failo antraštę; writeBitmapInfoHeader sukuria * informacijos antraštę; ir „writeBitmap“ rašo vaizdą. * * / private void save (Image parImage, int parWidth, int parHeight) {bandykite {convertImage (parImage, parWidth, parHeight); writeBitmapFileHeader (); writeBitmapInfoHeader (); writeBitmap (); } gaudyti (Išimtis saveEx) {saveEx.printStackTrace (); }} / * * convertImage konvertuoja atminties vaizdą į bitmap formatą (BRG). * Tai taip pat apskaičiuoja tam tikrą informaciją apie žemėlapio informacijos antraštę. * * / privatus boolean convertImage (Vaizdo parImage, int parWidth, int parHeight) {int pad; bitmap = new int [parWidth * parHeight]; „PixelGrabber“ pg = naujas „PixelGrabber“ (parImage, 0, 0, parWidth, parHeight, bitmap, 0, parWidth); pabandykite {pg.grabPixels (); } gaudyti (InterruptedException e) {e.printStackTrace (); grįžti (klaidinga); } pad = (4 - ((parWidth * 3)% 4)) * parHeight; biSizeImage = ((parWidth * parHeight) * 3) + padas; bfSize = biSizeImage + BITMAPFILEHEADER_SIZE + BITMAPINFOHEADER_SIZE; biWidth = parWidth; biHeight = parHeight; grįžti (tiesa); } / * * writeBitmap konvertuoja iš pikselių grobiko grąžintą vaizdą į * reikiamą formatą. Atminkite: nuskaitymo linijos yra apverstos * bitų žemėlapio faile! * * Kiekviena nuskaitymo linija turi būti paminkštinta iki net 4 baitų ribos. * / private void writeBitmap () {int dydis; int vertė; int j; int i; int rowCount; int rowIndex; int lastRowIndex; int padas; int padCount; baitas rgb [] = naujas baitas [3]; dydis = (biWidth * biHeight) - 1; pad = 4 - ((biWidth * 3)% 4); if (pad == 4) // <==== Klaidų taisymo bloknotas = 0; // <==== Klaidų taisymo eilutėCount = 1; padCount = 0; rowIndex = dydis - biWidth; lastRowIndex = rowIndex; pabandykite {for (j = 0; j> 8) & 0xFF); rgb [2] = (baitas) ((reikšmė >> 16) ir 0xFF); fo.write (rgb); if (rowCount == biWidth) {padCount + = pad; už (i = 1; i> 8) ir 0x00FF); grąža (retValue); } / * * * intToDWord paverčia int į dvigubą žodį, kur grąžos * reikšmė saugoma 4 baitų masyve. * * / privatus baitas [] intToDWord (int parValue) {baitas retValue [] = naujas baitas [4]; retValue [0] = (baitas) (parValue & 0x00FF); retValue [1] = (baitas) ((parValue >> 8) & 0x000000FF); retValue [2] = (baitas) ((parValue >> 16) & 0x000000FF); retValue [3] = (baitas) ((parValue >> 24) & 0x000000FF); grąža (retValue); }} 

Išvada

Tai viskas. Esu įsitikinęs, kad ši klasė jums bus labai naudinga, nes nuo JDK 1.1.6 „Java“ nepalaiko vaizdų išsaugojimo populiariausiais formatais. JDK 1.2 pasiūlys palaikymą kuriant JPEG vaizdus, ​​bet nepalaikys bitų žemėlapių. Taigi ši klasė vis tiek užpildys JDK 1.2 spragą.

Jei žaidžiate su šia klase ir rasite būdų ją pagerinti, praneškite man! Žemiau rodomas mano el. Paštas kartu su biografija.

Jean-Pierre Dubé yra nepriklausomas „Java“ konsultantas. Jis įkūrė „Infocom“, įregistruotą 1988 m. Nuo tada „Infocom“ sukūrė keletą pritaikytų programų, pradedant gamyba, dokumentų valdymu ir didelio masto elektros energijos tiekimo linijų valdymu. Jis turi didelę programavimo patirtį C, „Visual Basic“ ir pastaruoju metu „Java“, kuri dabar yra pagrindinė jo įmonės kalba. Vienas iš naujausių „Infocom“ projektų yra diagramos API, kuri netrukus turėtų būti prieinama kaip beta versija.

Šią istoriją „Java Tip 60: bitmap failų išsaugojimas„ Java ““ iš pradžių paskelbė „JavaWorld“.