Programiranje

Java Nasvet 60: Shranjevanje bitnih datotek v Javi

Ta namig dopolnjuje Java Tip 43, ki je prikazal postopek nalaganja bitnih datotek v Java programih. Ta mesec spremljam vadnico o shranjevanju slik v 24-bitne bitne datoteke in odrezek kode, ki ga lahko uporabite za zapisovanje bitne datoteke iz slikovnega predmeta.

Zmožnost ustvarjanja bitne datoteke odpre številna vrata, če delate v okolju Microsoft Windows. Na primer pri zadnjem projektu sem moral vmesnik Java in Microsoft Access. Program Java je uporabniku omogočil risanje zemljevida na zaslon. Zemljevid je bil nato natisnjen v poročilu Microsoft Access. Ker Java ne podpira OLE, je bila moja edina rešitev ustvariti bitno sliko na zemljevidu in poročilu Microsoftovega dostopa povedati, kje naj ga vzamem. Če ste kdaj morali napisati aplikacijo za pošiljanje slike v odložišče, vam bo ta namig morda koristil - še posebej, če te podatke posredujete drugi aplikaciji Windows.

Oblika bitne slike

Format bitne slike podpira 4-bitno RLE (kodiranje dolžine poteka) ter 8-bitno in 24-bitno kodiranje. Ker imamo opravka samo s 24-bitno obliko, si oglejmo strukturo datoteke.

Bitna slika je razdeljena na tri odseke. Spodaj sem vam jih postavil.

Oddelek 1: Glava datoteke bitne slike

Ta glava vsebuje informacije o velikosti vrste in postavitvi bitne datoteke. Struktura je naslednja (povzeta iz definicije strukture jezika C):

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

Tu je opis elementov kode iz zgornjega seznama:

  • bfType: Označuje vrsto datoteke in je vedno nastavljena na BM.
  • bfSize: Določa velikost celotne datoteke v bajtih.
  • bfReserved1: Rezervirano - mora biti nastavljeno na 0.
  • bfReserved2: Rezervirano - mora biti nastavljeno na 0.
  • bfOffBits: Določi odmik bajta od BitmapFileHeader na začetek slike.

Tu ste videli, da je namen glave bitne slike identifikacija bitne datoteke. Vsak program, ki bere bitne datoteke, uporablja bitmap glavo za preverjanje veljavnosti datotek.

Oddelek 2: Glava informacij o bitni sliki

Naslednja glava, imenovana glava informacij, vsebuje vse lastnosti same slike.

Tukaj je opisano, kako določite podatke o dimenziji in barvnem formatu bitne slike (DIB), neodvisne od naprave Windows 3.0 (ali novejše):

typedef struct tagBITMAPINFOHEADER {DWORD biSize; LONG biWidir; DOLGA biHeight; BESEDA biPlanes; BESEDA biBitCount; DWORD biCompression; DWORD biSizeImage; LONG biXPelsPerMeter; LONG biYPelsPerMeter; DWORD biClrUsed; DWORD biClrImportant; } BITMAPINFOHEADER; 

Vsak element zgornjega seznama kod je opisan spodaj:

  • biSize: Določa število bajtov, ki jih zahteva BITMAPINFOHEADER struktura.
  • biWidth: Določa širino bitne slike v slikovnih pikah.
  • biHeight: Določa višino bitne slike v slikovnih pikah.
  • biPlanes: Določa število ravnin za ciljno napravo. Ta član mora biti nastavljen na 1.
  • biBitCount: Določa število bitov na slikovno piko. Ta vrednost mora biti 1, 4, 8 ali 24.
  • biCompression: Določi vrsto stiskanja za stisnjeno bitno sliko. V 24-bitni obliki je spremenljivka nastavljena na 0.
  • biSizeImage: določa velikost slike v bajtih. Velja, da tega člana nastavite na 0, če je bitna slika v BI_RGB format.
  • biXPelsPerMeter: določa vodoravno ločljivost ciljne naprave v bitni sliki v slikovnih pikah na meter. Aplikacija lahko s to vrednostjo izbere bitno sliko iz skupine virov, ki se najbolje ujema z značilnostmi trenutne naprave.
  • biYPelsPerMeter: določa navpično ločljivost ciljne naprave v bitni sliki v metrih na meter.
  • biClrUsed: Podaja število barvnih indeksov v barvni tabeli, ki jo dejansko uporablja bitna slika. Če biBitCount je nastavljeno na 24, biClrUsed določa velikost referenčne tabele barv, ki se uporablja za optimizacijo delovanja barvnih palet sistema Windows.
  • biClrImportant: Podaja število barvnih indeksov, ki se štejejo za pomembne za prikaz bitne slike. Če je ta vrednost 0, so pomembne vse barve.

Zdaj so definirane vse informacije, potrebne za ustvarjanje slike.

Oddelek 3: Slika

V 24-bitni obliki je vsaka slikovna pika na sliki predstavljena v seriji treh bajtov RGB, shranjenih kot BRG. Vsaka črta optičnega branja je obložena s celo 4-bajtno mejo. Da bi postopek še bolj zakomplicirali, se slika shrani od spodaj navzgor, kar pomeni, da je prva vrstica optičnega branja zadnja črta skeniranja na sliki. Naslednja slika prikazuje obe glavi (BITMAPHEADER) in (BITMAPINFOHEADER) in del slike. Vsak odsek je razmejen z navpično vrstico:

 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 * 

Zdaj pa k kodi

Zdaj, ko vemo vse o strukturi 24-bitne bitne slike, je to, kar ste čakali: koda za zapisovanje bitne datoteke iz slikovnega predmeta.

uvoz java.awt. *; uvoz java.io. *; uvoz java.awt.image. *; javni razred BMPFile razširi komponento {// --- Zasebne konstante private final static int BITMAPFILEHEADER_SIZE = 14; zasebni končni statični int BITMAPINFOHEADER_SIZE = 40; // --- Deklaracija zasebne spremenljivke // --- Glava datoteke bitne slike zasebni bajt bitmapFileHeader [] = nov bajt [14]; zasebni bajt bfType [] = {'B', 'M'}; zasebno int bfSize = 0; zasebno int bfReserved1 = 0; zasebno int bfReserved2 = 0; private int bfOffBits = BITMAPFILEHEADER_SIZE + BITMAPINFOHEADER_SIZE; // --- Zaglavje informacij o bitni sliki zasebni bajt bitmapInfoHeader [] = nov bajt [40]; private int biSize = BITMAPINFOHEADER_SIZE; private int biWidth = 0; zasebno int biHeight = 0; private int biPlanes = 1; private int biBitCount = 24; private int biCompression = 0; private int biSizeImage = 0x030000; private int biXPelsPerMeter = 0x0; private int biYPelsPerMeter = 0x0; private int biClrUsed = 0; private int biClrImportant = 0; // --- Bitmap surovi podatki private int bitmapa []; // --- razdelek datoteke private FileOutputStream fo; // --- Privzeti konstruktor public BMPFile () {} public void saveBitmap (String parFilename, Image parImage, int parWidth, int parHeight) {try {fo = new FileOutputStream (parFilename); shrani (parImage, parWidth, parHeight); fo.close (); } catch (Izjema saveEx) {saveEx.printStackTrace (); }} / * * SaveMethod je glavna metoda postopka. Ta metoda * bo poklicala metodo convertImage za pretvorbo pomnilniške slike v * bajtno matriko; metoda writeBitmapFileHeader ustvari in zapiše * glavo bitmap datoteke; writeBitmapInfoHeader ustvari * informacijsko glavo; in writeBitmap zapiše sliko. * * / private void save (Image parImage, int parWidth, int parHeight) {try {convertImage (parImage, parWidth, parHeight); writeBitmapFileHeader (); writeBitmapInfoHeader (); writeBitmap (); } catch (Izjema saveEx) {saveEx.printStackTrace (); }} / * * convertImage pretvori sliko pomnilnika v bitno bitno obliko (BRG). * Izračuna tudi nekaj informacij za glavo informacij o bitni sliki. * * / private boolean convertImage (Image parImage, int parWidth, int parHeight) {int pad; bitna slika = nov int [parWidth * parHeight]; PixelGrabber pg = nov PixelGrabber (parImage, 0, 0, parWidth, parHeight, bitmap, 0, parWidth); poskusite {pg.grabPixels (); } catch (InterruptedException e) {e.printStackTrace (); vrnitev (napačno); } pad = (4 - ((parWidth * 3)% 4)) * parHeight; biSizeImage = ((parWidth * parHeight) * 3) + pad; bfSize = biSizeImage + BITMAPFILEHEADER_SIZE + BITMAPINFOHEADER_SIZE; biWidth = parWidth; biHeight = parHeight; vrnitev (true); } / * * writeBitmap pretvori sliko, vrnjeno iz zajemnika slikovnih pik, v * zahtevano obliko. Ne pozabite: vrstice za optično branje so obrnjene v * bitno sliko! * * Vsaka črta optičnega branja mora biti oblazinjena do enakomerne 4-bajtne meje. * / private void writeBitmap () {int velikost; vrednost int; int j; int i; int rowCount; int rowIndex; int lastRowIndex; int blazinica; int padCount; bajt rgb [] = nov bajt [3]; velikost = (biWidth * biHeight) - 1; blazinica = 4 - ((biWidth * 3)% 4); if (pad == 4) // <==== Pad za odpravljanje napak = 0; // <==== Popravek napak rowCount = 1; padCount = 0; rowIndex = velikost - biWidth; lastRowIndex = rowIndex; poskusite {for (j = 0; j> 8) & 0xFF); rgb [2] = (bajt) ((vrednost >> 16) & 0xFF); fo.write (rgb); if (rowCount == biWidth) {padCount + = pad; za (i = 1; i> 8) & 0x00FF); vrnitev (retValue); } / * * * intToDWord pretvori int v dvojno besedo, kjer je vrnjena vrednost * shranjena v 4-bajtni matriki. * * / zasebni bajt [] intToDWord (int parValue) {bajt retValue [] = nov bajt [4]; retValue [0] = (bajt) (parValue & 0x00FF); retValue [1] = (bajt) ((parValue >> 8) & 0x000000FF); retValue [2] = (bajt) ((parValue >> 16) & 0x000000FF); retValue [3] = (bajt) ((parValue >> 24) & 0x000000FF); vrnitev (retValue); }} 

Zaključek

To je vse. Prepričan sem, da se vam bo ta razred zdel zelo koristen, saj od JDK 1.1.6 Java ne podpira shranjevanja slik v nobeni priljubljeni obliki. JDK 1.2 bo ponujal podporo za ustvarjanje slik JPEG, ne pa tudi podporo za bitne slike. Torej bo ta razred še vedno zapolnil vrzel v JDK 1.2.

Če se poigrate s tem razredom in poiščete načine za njegovo izboljšanje, mi sporočite! Spodaj se prikaže moja e-pošta, skupaj z mojo biografijo.

Jean-Pierre Dubé je neodvisni svetovalec za Javo. Ustanovil je Infocom, registriran leta 1988. Od takrat je Infocom razvil več aplikacij po meri, od proizvodnje, upravljanja dokumentov in obsežnega upravljanja električnih vodov. Ima bogate programske izkušnje na C, Visual Basic in nazadnje na Javi, ki je zdaj glavni jezik, ki ga uporablja njegovo podjetje. Eden zadnjih Infocomovih projektov je API za diagrame, ki naj bi bil kmalu na voljo kot beta izdaja.

To zgodbo, "Java Nasvet 60: Shranjevanje bitnih datotek v Javi", je prvotno objavil JavaWorld.

$config[zx-auto] not found$config[zx-overlay] not found