int21h

Formát BMP

Windows BitMaP

Myslím, že většina lidí co tenhle článek čtou už aspoň jednoduchý BMP přečetla, ale nezapomínejme na méně pokročilé programátory a na lamy co chcou machrovat psaním článků jako já. Formát byl navržen firmou Micro$oft a musím říct, že tohle je jedna z mála věcí co se jim povedla. (I když co jde na tak jednoduchým formátu zkazit, že?). Hold v jednoduchosti je síla.


BMP formáty jsou ve skutečnosti dva.
Jeden na Windows a druhý na OS/2. V tomto článku budu popisovat oba, protože tam je pár odlišností.

Dost podobný formát se jmenuje DIB, ale v tom je pár odlišností:
o DIB obrázky vůbec nepodporují kompresi (ale záznam v hlavičce tam stejně asi je kvůli kompatibilitě)
o První dva znaky nemusí být jen BM, ale i různé další:
oo BA - Bitmap array
oo CI - Color icon
oo IC - Icon
oo CP - Color Pointer (myš)
oo PT - Pointer (myš)

Tyto skupiny se od sebe liší asi jenom ve velikosti a počtu barev

A teď nějaké praktické informace

Možné počty barev jsou:
o 2 (bitové)
o 16
o 256
o 16M (TrueColor)
o 4MLD (HiColor)

Grayscale je to samé jako 256. (Nevím proč neredukovali paletu)
Maximální možné rozlišení je 65536x65536
(Potom ale nevím, proč je v hlavičce na každý rozměr 32 bitů)

RLE komprese

Obrázky BMP podporují kompresi RLE. To je sice super, ale stejně to nikdo nepoužívá,
protože číst z takového souboru data je už poněkud těžší a kdo by se s tím chtěl štvát kvůli těm pár KB. (Někdy je komprimovaný obrázek dokonce větší než ten samý nekomprimovaný:)
Většina programů komprimované obrázky neumí zpracovat.

RLE komprese 8bitových obrázků

30. offset hlavičky = 1
Každá položka začína takzvaným Run-bytem. Podle toho se rozhoduje co dál.
Pokud je Run-byte větší než nula, tak se následující byte nakreslí Run-byte krát. (Encoded mode)
Pokud je Run-byte nula tak pokud je následující byte:
0 - Konec řádku
1 - Konec obrazových dat
2 - Takzvaná delta. Následující 2 byty jsou posuntí x a y pozice.
p=3 až 255 - Absolute mode:
Následujících p bytů jsou barvy v nezakódovaném tvaru. Pokud je p liché, tak je řada doplněná nulou na sudej počet.
Ale o tomhle už byly napsané KB textu. Více můžete vidět v příkladu

RLE komprese 4bitových obrázků

30. offset hlavičky = 2
Stejně jako u 8bRLE je tu Run-byte.
Pokud je Run-byte větší než nula, tak se následující nibbles nakreslí Run-byte krát.(Encoded mode)
Například 05c3 se rozkóduje c3c3c
Všimněte si, že pokud je Run-byte lichý tak poslední barva je první nibble.
Dál je to stejný jako u 8bRLE až na Absolute mode
Absolute mode

Hlavička

Toto je hlavička, kterou můžete najít snad všude. Já ji jenom překládám a popisuju.
Offset Velikost Popis
---------------------------
0      2        ID - BM=Windows bitmap
2      4        Velikost BMP souboru
6      4        První rezervované data
10     4        Offset na kterém začínají obrazová data
14     4        Velikost hlavičky (vždycky stejná)
18     4        Šířka obrázku v pixelech
22     4        Výška obrázku v pixelech
26     2        Počet bitových rovin
28     2        Bits per pixel (2^bpp=počet barev)
30     4        Komprese 0=žádná,1=RLE 8-bit/Pixel,2=RLE 4-bit/Pixel
34     4        Velikost obrazových dat (WIDTH*HEIGHT/BPP)
38     4        Horizontální rozlišení
42     4        Vertikální rozlišení (rastry)
46     4        Kolik je použito barev. Ale vždycky je tam 0
50     4        Důležité barvy (Pokud je to 0 tak je barev 256 (prý))  

Paleta

Hned po hlavičce následuje paleta barev. Její délka je (2^bpp)*4
Krát 4 je tam proto, že každá barva je vyjádřena čtyřmi byty ve formě
B,G,R,Reserved.

V OS/2 typu je paleta uložena ve formě R,G,B Tedy tři byty. Tím se dost zmenší velikost.


Každou složku v paletě je nutné před nastavením do palety vydělit 4!
Protože data v paletě jsou 8bitové a položky v DAC registrech jenom 6bitové. Proto x div 4 (x shr 2);

struktura WIN:
Offset Velikost Popis
---------------------
0      1        Modrá
1      1        Zelená
2      1        Červená
3      1        Rezervováno (je to k ničemu a zvětší to paletu. O 256b)  

struktura OS/2:
Nikdy jsem to neviděl, ale četl jsem, že je to stejné, ale bez rezervovaného kanálu.

Data

Data jsou uložena od levého spodního do pravého horního bodu,
takže pokud to chcete vykreslit odshora dolů, tak se to musí přepočítat.

2 barvy:
Jeden byte vyjadřuje 8 pixelů. Bit na barvu
16 barev:
Jeden byte vyjadřuje 2 pixely. Nibble na barvu

Šířka každého řádku je vždy zarovnána na takový počet bytů, aby jejich počet byl dělitelný 4 beze zbytku
Což znamená if ((x*bpp and 3)<>0) then zarovnani:=3-(x*bpp and 3) bytů.

256 barev:
Jeden byte vyjadřuje právě jednu barvu
65536 barev:
Každý WORD vyjadřuje hodnotu RGB barvy
16777216 barev(TrueColor):
Paleta chybí, každá barva je v datech reprezentována 3 byty BGR
4294967296 barev(HiColor):
Každé 4byty znamenají 0BGR

Příklad

Připravil jsem malý příklad na čtení Micro$oftích BMP obrázků pro TurboPascal.
Podporuje 2,16,256,16M(Jenom emulace) barev. Dále zvládá kompresi RLE pro 8 a 4bitové obrázky.

Použité procedury PutPixel(x,y,c) a SetColor(i,r,g,b) by měly být
v každé dobré unitě pro mód $13. Vím že tyhle jsou dost pomalé a taky tam není žádný buffer,
ale o rychlost mi zrovna nešlo. Má to být spíš názorné a přehledné.

]bmpview.pas[
2006-11-30 | BOby
Reklamy: