Programovanie

Tip Java 60: Ukladanie bitmapových súborov v prostredí Java

Tento tip dopĺňa doplnok Java Tip 43, ktorý demonštroval proces načítania bitmapových súborov v aplikáciách Java. Tento mesiac pokračujem v návode, ako ukladať obrázky do 24-bitových bitmapových súborov, a kódu, ktorý môžete použiť na zápis bitmapového súboru z obrazového objektu.

Schopnosť vytvoriť bitmapový súbor otvára mnoho dverí, ak pracujete v prostredí Microsoft Windows. Napríklad pri mojom poslednom projekte som musel prepojiť Javu s programom Microsoft Access. Program Java umožňoval používateľovi nakresliť mapu na obrazovku. Mapa bola potom vytlačená v správe programu Microsoft Access. Pretože Java nepodporuje OLE, mojím jediným riešením bolo vytvoriť bitmapový súbor mapy a povedať správe programu Microsoft Access, kde ju vyzdvihnúť. Ak ste niekedy museli napísať aplikáciu na odoslanie obrázka do schránky, tento tip vám môže byť užitočný - najmä ak sa tieto informácie odovzdávajú inej aplikácii pre Windows.

Formát bitmapového súboru

Formát bitmapového súboru podporuje 4-bitové RLE (kódovanie dĺžky behu), ako aj 8-bitové a 24-bitové kódovanie. Pretože máme do činenia iba s 24-bitovým formátom, poďme sa pozrieť na štruktúru súboru.

Bitmapový súbor je rozdelený do troch častí. Rozložil som ich pre vás nižšie.

Oddiel 1: Hlavička bitmapového súboru

Táto hlavička obsahuje informácie o veľkosti typu a rozložení bitmapového súboru. Štruktúra je nasledovná (prevzaté z definície štruktúry jazyka C):

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

Tu je popis prvkov kódu z vyššie uvedeného zoznamu:

  • bfType: Označuje typ súboru a je vždy nastavený na BM.
  • bfSize: Určuje veľkosť celého súboru v bajtoch.
  • bfReserved1: Rezervované - musí byť nastavené na 0.
  • bfReserved2: Rezervované - musí byť nastavené na 0.
  • bfOffBits: Určuje odsadenie bajtov od BitmapFileHeader na začiatok obrázka.

Tu ste videli, že účelom hlavičky bitovej mapy je identifikovať bitmapový súbor. Každý program, ktorý číta bitové mapy, používa na overenie súborov hlavičku bitovej mapy.

Oddiel 2: Hlavička bitmapových informácií

Ďalšia hlavička s názvom informačná hlavička, obsahuje všetky vlastnosti samotného obrázka.

Tu je postup, ako zadáte informácie o dimenzii a farebnom formáte bitmapy nezávislej na zariadení so systémom Windows 3.0 (alebo vyššej) (DIB):

typedef struct tagBITMAPINFOHEADER {DWORD biSize; DLHÁ ŠÍRKA; DLHÁ biHeight; SLOVNÉ dvojplošníky; WORD biBitCount; DWORD biCompression; DWORD biSizeImage; DLHÝ biXPelsPerMeter; DLHÝ biYPelsPerMeter; DWORD biClrUsed; DWORD biClrDôležité; } BITMAPINFOHEADER; 

Každý prvok vyššie uvedeného zoznamu kódov je popísaný nižšie:

  • biSize: Určuje počet bajtov požadovaný parametrom BITMAPINFOHEADER štruktúra.
  • biWidth: Určuje šírku bitmapy v pixeloch.
  • biHeight: Určuje výšku bitmapy v pixeloch.
  • dvojplošníky: Určuje počet lietadiel pre cieľové zariadenie. Tento člen musí byť nastavený na 1.
  • biBitCount: Určuje počet bitov na pixel. Táto hodnota musí byť 1, 4, 8 alebo 24.
  • biCompression: Určuje typ kompresie pre komprimovanú bitovú mapu. V 24-bitovom formáte je premenná nastavená na 0.
  • biSizeImage: Určuje veľkosť obrázka v bajtoch. Je platné nastaviť tohto člena na 0, ak je bitmapa v BI_RGB formát.
  • biXPelsPerMeter: Určuje horizontálne rozlíšenie cieľového zariadenia pre bitmapu v pixeloch na meter. Aplikácia môže pomocou tejto hodnoty vybrať bitmapu zo skupiny prostriedkov, ktorá najlepšie zodpovedá charakteristikám aktuálneho zariadenia.
  • biYPelsPerMeter: Určuje vertikálne rozlíšenie cieľového zariadenia pre bitmapu v pixeloch na meter.
  • biClrUsed: Určuje počet indexov farieb v tabuľke farieb skutočne použitých bitmapou. Ak biBitCount je nastavený na 24, biClrUsed určuje veľkosť tabuľky referenčných farieb použitých na optimalizáciu výkonu farebných paliet systému Windows.
  • biClrImportant: Určuje počet farebných indexov považovaných za dôležité pre zobrazenie bitmapy. Ak je táto hodnota 0, sú dôležité všetky farby.

Teraz sú definované všetky informácie potrebné na vytvorenie obrázka.

Oddiel 3: Obrázok

V 24-bitovom formáte je každý pixel v obraze predstavovaný sériou troch bajtov RGB uložených ako BRG. Každý riadok skenovania je vyplnený rovnomernou hranicou 4 bajtov. Aby sa proces ešte viac skomplikoval, obrázok sa ukladá zdola nahor, čo znamená, že prvý riadok skenovania je posledný riadok skenovania v obraze. Nasledujúci obrázok zobrazuje obe hlavičky (BITMAPHEADER) a (BITMAPINFOHEADER) a časť obrázka. Každá časť je ohraničená zvislou čiarou:

 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 * 

Teraz, ku kódu

Teraz, keď vieme všetko o štruktúre 24-bitového bitmapového súboru, tu je to, na čo ste čakali: kód na zápis bitmapového súboru z obrazového objektu.

import java.awt. *; import java.io. *; import java.awt.image. *; verejná trieda BMPFile rozširuje komponent {// --- súkromné ​​konštanty súkromné ​​konečné statické int BITMAPFILEHEADER_SIZE = 14; súkromná konečná statická int BITMAPINFOHEADER_SIZE = 40; // --- Deklarácia súkromnej premennej // --- Hlavička bitmapového súboru súkromný bajt bitmapFileHeader [] = nový bajt [14]; private byte bfType [] = {'B', 'M'}; private int bfSize = 0; private int bfReserved1 = 0; private int bfReserved2 = 0; private int bfOffBits = BITMAPFILEHEADER_SIZE + BITMAPINFOHEADER_SIZE; // --- Bitmapová informačná hlavička súkromný bajt bitmapInfoHeader [] = nový bajt [40]; private int biSize = BITMAPINFOHEADER_SIZE; private int biWidth = 0; private 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; // --- Bitmapové surové dáta súkromné ​​int bitmapa []; // --- Sekcia súborov private FileOutputStream fo; // --- Predvolený konštruktor public BMPFile () {} public void saveBitmap (String parFilename, Image parImage, int parWidth, int parHeight) {try {fo = new FileOutputStream (parFilename); save (parImage, parWidth, parHeight); fo.close (); } catch (Výnimka saveEx) {saveEx.printStackTrace (); }} / * * SaveMethod je hlavná metóda procesu. Táto metóda * zavolá metódu convertImage na prevod obrázka pamäte na * bajtové pole; metóda writeBitmapFileHeader vytvorí a zapíše * hlavičku bitmapového súboru; writeBitmapInfoHeader vytvorí záhlavie s informáciami *; a writeBitmap zapíše obrázok. * * / private void save (Image parImage, int parWidth, int parHeight) {try {convertImage (parImage, parWidth, parHeight); writeBitmapFileHeader (); writeBitmapInfoHeader (); writeBitmap (); } catch (Výnimka saveEx) {saveEx.printStackTrace (); }} / * * convertImage prevádza obraz z pamäte do bitmapového formátu (BRG). * Tiež počíta niektoré informácie pre hlavičku bitmapovej informácie. * * / private boolean convertImage (Image parImage, int parWidth, int parHeight) {int pad; bitmap = new int [parWidth * parHeight]; PixelGrabber pg = nový PixelGrabber (parImage, 0, 0, parWidth, parHeight, bitmap, 0, parWidth); try {pg.grabPixels (); } catch (InterruptedException e) {e.printStackTrace (); návrat (nepravda); } pad = (4 - ((parWidth * 3)% 4)) * parHeight; biSizeImage = ((parWidth * parHeight) * 3) + podložka; bfSize = biSizeImage + BITMAPFILEHEADER_SIZE + BITMAPINFOHEADER_SIZE; biWidth = parWidth; biHeight = parHeight; návrat (pravda); } / * * writeBitmap prevádza obraz vrátený z nástroja na zachytávanie pixelov na * požadovaný formát. Pamätajte: riadky skenovania sú invertované v * bitmapovom súbore! * * Každý riadok skenovania musí byť vyplnený rovnomernou hranicou 4 bajtov. * / private void writeBitmap () {int veľkosť; hodnota int; int j; int i; int riadokPočtu; int riadokIndex; int lastRowIndex; int podložka; int padCount; byte rgb [] = nový bajt [3]; size = (biWidth * biHeight) - 1; podložka = 4 - ((biWidth * 3)% 4); if (pad == 4) // <==== Pad na opravu chýb = 0; // <==== Oprava chyby rowCount = 1; padCount = 0; rowIndex = veľkosť - biWidth; lastRowIndex = rowIndex; skúsiť {for (j = 0; j> 8) & 0xFF); rgb [2] = (bajt) ((hodnota >> 16) & 0xFF); fo.write (rgb); if (rowCount == biWidth) {padCount + = pad; pre (i = 1; i> 8) & 0x00FF); návrat (retValue); } / * * * intToDWord prevádza int na dvojslovo, kde je návratová hodnota * uložená v 4-bajtovom poli. * * / private byte [] intToDWord (int parValue) {byte 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); návrat (retValue); }} 

Záver

To je všetko. Som si istý, že táto trieda bude veľmi užitočná, pretože od verzie JDK 1.1.6 Java nepodporuje ukladanie obrázkov v žiadnom z populárnych formátov. JDK 1.2 ponúkne podporu pre vytváranie obrázkov JPEG, nepodporuje však bitmapy. Táto trieda teda stále vyplní medzeru v JDK 1.2.

Ak sa s touto triedou hráte a hľadáte spôsoby, ako ju vylepšiť, dajte mi vedieť! Môj e-mail sa zobrazí nižšie spolu s mojím životopisom.

Jean-Pierre Dubé je nezávislý konzultant v odbore Java. Založil spoločnosť Infocom, ktorá bola zaregistrovaná v roku 1988. Od tej doby vyvinula spoločnosť Infocom niekoľko vlastných aplikácií od výroby, správy dokumentov a rozsiahlej správy elektrických vedení. Má rozsiahle skúsenosti s programovaním v jazykoch C, Visual Basic a naposledy v prostredí Java, ktoré je teraz primárnym jazykom používaným v jeho spoločnosti. Jedným z nedávnych projektov spoločnosti Infocom je API diagramu, ktoré by malo byť čoskoro dostupné ako beta verzia.

Tento príbeh, „Java Tip 60: Ukladanie bitmapových súborov v jazyku Java“, bol pôvodne publikovaný spoločnosťou JavaWorld.

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