Hlavní navigace

Grafická knihovna OpenGL (26): formáty rastrových souborů

30. 12. 2003
Doba čtení: 12 minut

Sdílet

V tomto dílu seriálu o grafické knihovně OpenGL si popíšeme některé formáty rastrových souborů, které lze použít pro ukládání a zpětné načítání textur. Vzhledem k omezenému rozsahu jednotlivých dílů si podrobně popíšeme pouze jednodušší formáty, jejichž implementace v programech je bezproblémová a nevyžaduje ke své činnosti žádné další podpůrné knihovny.

Texturování 5

Obsah

Rastrové soubory a OpenGL
Popis formátu rastrového souboru BMP
Použití formátu BMP
Struktura BMP souboru
Hlavička souboru BMP (datová struktura BITMAPFILEHEA­DER)
Informace o obraze (datová struktura BITMAPINFOHEA­DER)
Barevná paleta (datová struktura RGBQUAD)
Obrazová data (datová struktura BITS)
TrueColor soubory BMP
Komprimace v BMP souborech
Pokračování
Demonstrační příklad
 

Rastrové soubory a OpenGL

Jak již víme z předchozích dílů, je před vykreslením textury nejdříve nutné tuto texturu vytvořit v operační paměti počítače a následně specifikovat její parametry (rozměry apod.) pomocí funkcí glTexParamete­ri(), glTexParameterf() a posléze glTexImage2D().

Vytvoření textury v paměti počítače však není žádným způsobem ze strany OpenGL podporováno, protože OpenGL je knihovna určená pro tvorbu a vykreslování trojrozměrných scén, nikoli pro načítání a ukládání dat. Proto si musíme vhodné funkce pro načtení textur vytvořit sami. Nejjednodušší je samozřejmě použití již hotových knihoven (libpng, libjpeg), ale někdy není vhodné se spoléhat na dostupnost těchto knihoven (běžný uživatel například nemá znalosti ani práva tyto knihovny měnit, knihovny jsou závislé na dalších knihovnách apod.).

Proto může být výhodné vytvořit několik jednoduchých funkcí pro načtení rastrových dat textury z některého vhodného formátu. Dnes si popíšeme rastrový formát BMP, v příštím dílu formát TGA. Oba zvolené formáty mají možnost ukládání rastrových dat v barevném režimu TrueColor, což je z hlediska texturování jistě výhodné. Navíc je možné ve formátu TGA ukládat i alfa-složku, tj. průhlednost či neprůhlednost každého pixelu.

V dalším textu si popíšeme rastrový formát BMP, který sice zdaleka není ideální, ale jeho načítání je poměrně jednoduché a přímočaré, což se nám hodí pro demonstrační příklady. V dalším textu se omezíme pouze na formát Microsoftu. Existuje sice i podobný formát z dílny IBM, který se liší ve struktuře hlavičky, ale není příliš rozšířený.

Formát BMP zcela jistě nepatří mezi formáty úsporné. Zaprvé je použita docela velká hlavička, ve které je spousta zbytečných (rezervovaných) položek. Zadruhé se při ukládání barevné palety zbytečně pracuje se čtyřmi bajty místo tří (opět se jedná o rezervovanou položku, kterou podle normy nelze použít ani na alfa-kanál). Zatřetí je sice povolena komprimace rastrových dat (ovšem jenom jich, palety se to netýká), ale zvolená metoda je pro běžné obrázky neefektivní a mnohdy vede spíše k nárustu velikosti souboru! Komprimovat jde také pouze paletové obrázky, u TrueColor není komprimace povolena.

Obrazové řádky se ve formátu BMP ukládají zespodu nahoru, což jde proti všem zavedeným konvencím používaným v počítačové grafice (tento způsob ukládání může zpomalovat vykreslování, vyrovnávací paměti jsou z toho také nadšené apod.). Důvod, proč tomu tak je, spočívá v určité nekonzistenci WinAPI, které převzalo některé funkce ze systému OS/2, jenž měl (konzistentně) nastaven růst vertikálních souřadnic také zdola nahoru. Většina funkcí WinAPI však používá přirozenější opačnou orientaci vertikálních souřadnic, takže ve výsledku jde o pěkný zmatek.

Popis formátu rastrového souboru BMP

Bitmapové soubory jsou v operačních systémech Microsoft Windows uloženy v takzvaném Device Independent Bitmap (DIB) formátu. V podstatě jde o klasickou bitovou mapu nezávislou na zařízení použitém pro získání nebo naopak zobrazení obrazové informace. Termín Device Independent znamená, že bitmapy určují barvy jednotlivých pixelů ve formě, která je nezávislá na metodě používané pro zobrazování barev.

Formát DIB byl zaveden spolu s Microsoft Windows verze 2.0. V současných systémech (v podstatě od Microsoft Windows verze 3.0) se používá vylepšená verze označená jako BMP (BitMaP). Rastrové soubory uložené v této verzi by měly mít vždy koncovku .bmp.

Použití formátu BMP

Formát BMP umožňuje ukládání rastrových dat v těchto formátech:

  • 1 bit na pixel – dvoubarevné obrázky (používá se barevná paleta)
  • 4 bity na pixel – 16barevné obrázky (taktéž se používá barevná paleta)
  • 8 bitů na pixel – 256barevné obrázky (opět se používá barevná paleta)
  • 24 bitů na pixel – TrueColor obrázky (16 milionů barev, barevná paleta se nepoužívá, protože každý pixel je reprezentován přímo svou barvou).

Každý soubor typu BMP obsahuje hlavičku BMP souboru (strukturu BITMAPFILEHEA­DER), informační hlavičku (strukturu BITMAPINFOHEA­DER), tabulku barev – paletu (pole struktur RGBQUAD[]) a pole bitů, které obsahují vlastní obrazová data (BITS). Názvy struktur v závorkách odpovídají strukturám používaným v operačních systémech Microsoft Windows ve WindowsAPI (WinAPI). Celková struktura souboru BMP je následující:

Struktura BMP souboru

Tabulka č. 518
Název Význam
BITMAPFILEHEADER Datová struktura, která obsahuje základní informace o BMP souboru. Velikost této struktury je vždy 14 bytů.
BITMAPINFOHEADER Datová struktura, která obsahuje informace o uloženém obraze. Velikost této struktury je vždy 40 bytů.
RGBQUAD[0] První položka barevné palety (jedná se o RGB složky).
RGBQUAD[1] Druhá položka barevné palety, pokud je paleta použita.
  … následují případné další položky barevné palety …
RGBQUAD[n] Poslední položka barevné palety.
BITS Vlastní obrazová data. Formát těchto dat závisí na použité komprimační metodě a na počtu barev.

Hlavička souboru BMP (datová struktura BITMAPFILEHEADER)

Hlavička souboru BMP (tj. datová struktura BITMAPFILEHEADER) obsahuje údaje o typu, velikosti a celkové organizaci tohoto souboru. Velikost struktury je 14 bytů a její organizace je následující:

Tabulka č. 519
Název Délka Význam
bfType 2 byty Identifikátor formátu BMP. Aktuální verze formátu BMP zde obsahuje ASCII kód znaků „BM“.
bfSize 4 byty Celková velikost souboru s obrazovými údaji.
bfReserved1 2 byty Tento údaj je rezervovaný pro pozdější použití. V současné verzi formátu BMP zde musí být uložena nulová hodnota.
bfReserved2 2 byty I tento údaj je rezervovaný pro pozdější použití. V současné verzi formátu BMP zde musí být uložena nulová hodnota.
bfOffBits 4 byty Posun struktury BITMAPFILEHEADER od začátku vlastních obrazových dat.

Informace o obraze (datová struktura BITMAPINFOHEADER)

Struktura BITMAPINFOHEADER obsahuje základní informace o obraze. Mezi tyto informace patří rozměry, typ komprimace a barevný formát rastrových dat. Velikost struktury je vždy rovna 40 bytům a má následující organizaci:

Tabulka č. 520
Název Délka Význam
biSize 4 byty Tato položka udává celkovou velikost datové struktury BITMAPINFOHEADER.
biWidth 4 byty Tato položka udává šířku obrazu v pixelech.
biHeight 4 byty Tato položka udává výšku obrazu v pixelech.
biPlanes 2 byty V této položce je zadaný počet bitových rovin pro výstupní zařízení. V BMP je zde vždy hodnota 1.
biBitCount 2 byty V této položce je zadaný počet bitů na pixel. Podle počtu barev zde mohou být hodnoty 1, 4, 8 nebo 24 (to odpovídá postupně 2, 16, 256ti barvám popř. TrueColor režimu).
biCompression 4 byty Udává typ komprimační metody obrazových dat. Musí být nastavené na jednu z hodnot:
0 (BI_RGB),
1 (BI_RLE8) nebo
2 (BI_RLE4).
biSizeImage 4 byty Tato položka udává velikost obrazu v bytech. Pokud je bitmapa nekomprimovaná, může zde být nulová hodnota.
biXPelsPerMeter 4 byty Udává horizontální rozlišení výstupního zařízení v pixelech na metr. Tato hodnota může být použitá např. pro výběr obrazu ze skupiny obrazů, který nejlépe odpovídá rozlišení daného výstupního zařízení. Většina programů nemá potřebné informace o výstupním zařízení, a proto do této položky vkládá hodnotu 0.
biYPelsPerMeter 4 byty

Udává vertikální rozlišení výstupního zařízení v pixelech na metr. Opět, jako u předchozí položky, zde většina programů zapisuje hodnotu 0.

biClrUsed 4 byty

Udává počet barev, které jsou použity v dané bitmapě. Jestliže je tato hodnota nastavena na nulu (což dělá většina programů), znamená to, že bitmapa používá maximální počet barev. Tento počet lze jednoduše zjistit z položky biBitCount.

biClrImportant 4 byty

Udává počet barev, které jsou důležité pro vykreslení bitmapy. Pokud je tato hodnota nulová, jsou všechny barvy důležité. Tento údaj je používán při zobrazování na zařízeních, která mají omezený počet současně zobrazitelných barev (např. starší grafické karty se 16 resp. 256 barevnými režimy). Ovladač displeje může upravit systémovou paletu tak, aby zobrazil daný obrázek co nejvěrněji. Také je vhodné upravit paletu tak, aby byly barvy seřazené podle důležitosti.

Barevná paleta (datová struktura RGBQUAD)

Barevná paleta (tabulka barev) je definovaná jako pole struktur typu RGBQUAD. Toto pole obsahuje tolik položek, kolik je barev v uložené bitmapě. Není tedy nutné definovat pro obrázek uložený v 256 barvách všech 256 barev, ale pouze tolik, kolik jich je použito. Ve 24bitovém formátu se barevná paleta nepoužívá, protože každý pixel je zde reprezentovaný přímo svou RGB hodnotou. Jak již bylo napsáno výše, je vhodné barvy v paletě uspořádat tak, aby jejich pořadí odpovídalo důležitosti (tak pravil Microsoft, osobně nevím, proč by to nezvládla samotná aplikace např. z histogramu).

Struktura RGBQUAD je následující:

Tabulka č. 521
Název Délka Význam
rgbBlue 1 byte Specifikuje intenzitu červené barevné složky.
rgbGreen 1 byte Specifikuje intenzitu zelené barevné složky.
rgbRed 1 byte Specifikuje intenzitu modré barevné složky.
rgbReserved 1 byte Tato položka je rezervovaná a musí být nastavena na hodnotu 0.

Obrazová data (datová struktura BITS)

Obrazová data jsou v souboru uložena bezprostředně za paletou, v případě 24 bitového formátu ihned za informační hlavičkou. Data reprezentují po sobě jdoucí obrazové řádky (scanline). Každý obrazový řádek sestává z hodnot reprezentujících jednotlivé pixely v řádku v pořadí zleva doprava. Počet bytů reprezentujících obrazový řádek je závislý na šířce obrázku a na barevném formátu. Obrazový řádek je vždy zarovnaný na 4 byty (32 bitů), v případě nutnosti se doplňuje na 4 byty nulami.

Obrazové řádky se v bitmapě ukládají zdola nahoru, což je odlišné od většiny ostatních obrazových formátů. To znamená, že první byte v poli BITS reprezentuje pixel (resp. pixely) v levém dolním rohu bitmapy. Poslední byte potom reprezentuje pixely v pravém horním rohu.

Položka struktury BITMAPINFOHEADER biBitCount určuje počet bitů, které jsou potřeba pro reprezentaci každého pixelu. Tato položka současně určuje maximální počet barev v bitmapě. Význam jednotlivých hodnot:

1 – Bitmapa je monochromatická, přičemž barevná paleta obsahuje dvě položky. Každý bit pole bitmapy reprezentuje jeden pixel. Jestliže není bit nastavený (je nulový), pixel bude zobrazený barvou první položky barevné palety. Jestliže je bit nastavený (je jedničkový), pixel bude zobrazený barvou druhé položky barevné palety.

4 – Bitmapa má maximálně 16 barev, přičemž barevná paleta obsahuje maximálně 16 položek. Každý pixel bitmapy je reprezentován čtyřmi bity. To znamená, že v jednom byte je uložen index do tabulky barev pro dva pixely. Pokud například první byte v bitmapě má hodnotu 0×2a, byte reprezentuje dva pixely. První pixel bude mít barvu třetí položky barevné palety (hodnota horních čtyřech bitů je 2), druhý pixel bude mít barvu jedenácté položky barevné palety (hodnota spodních čtyřech bitů je 10).

8 – Bitmapa má maximálně 256 barev, přičemž barevná paleta obsahuje maximálně 256 položek. Každý pixel bitmapy je reprezentovaný jedním bytem, který udává index do tabulky barev, podobně jako v předchozích případech.

24 – Bitmapa je v TrueColor režimu, tzn. obsahuje maximálně 224 barev (16 777 216 barev). Barevná paleta není uložena, protože je pixel reprezentován přímo svými RGB hodnotami. Každý pixel je uložen ve třech bytech, kde každý byte reprezentuje intenzity červené, zelené a modré barevné složky.

TrueColor soubory BMP

TrueColor soubory BMP jsou vždy ukládány bez komprimace, proto musí být položka biCompression struktury BITMAPINFOHEADER nastavená na hodnotu BI_RGB. Položka biBitCount musí být nastavená na hodnotu 24.

Vlastní obrazová data jsou ukládána postupně po řádcích zdola nahoru. Každý obrazový řádek obsahuje trojici hodnot RGB pro jednotlivé pixely v řádku.

Je potřeba upozornit, že některé programy ukládají barevné složky jednotlivých pixelů v opačném pořadí (tedy GBR), což může způsobit problémy při konverzi obrázků.

Komprimace v BMP souborech

Operační systémy Windows od verze 3.0 podporují jednoduchou RLE (Run Length Encoding) komprimaci bitových map. RLE komprimace lze využít pouze u bitmap s čtyřmi resp. osmi bity na pixel. U jednobitových a TrueColor bitmap jsou obrázky vždy uloženy v nekomprimované podobě.

Jestliže je položka biCompression struktury BITMAPINFOHEADER nastavena na hodnotu BI_RLE8, je bitmapa komprimovaná RLE metodou pro 256barevné bitmapy.

Informace jsou v bitmapě organizovány do skupiny po dvou bytech. První byte určuje počet po sobě jdoucích pixelů, které budou mít index barvy určený v druhém bytu. První byte ve skupině může být nastavený na nulu, což znamená tzv. únik: např. konec řádku, konec bitmapy nebo delta. Typ úniku je zapsán v druhém bytu skupiny. Význam jednotlivých únikových hodnot:

Tabulka č. 522
hodnota druhého byte ve skupině význam úniku
0×00 indikuje konec řádku
0×01 indikuje konec bitmapy
0×02 delta – dva byty následující za touto hodnotou obsahují bezznaménkové (unsigned char) hodnoty, které znamenají horizontální a vertikální posunutí následujících pixelů od aktuální pozice
0×03–0×ff druhý byte určuje počet bytů, které následují. Tyto byty přímo určují pixely v nezkomprimovaném tvaru – co byte, to pixel.

Ukázka 256barevné bitmapy (všechny hodnoty jsou zapsané v hexadecimálním tvaru):

Tabulka č. 523
Komprimovaná data Nekomprimovaná data
05 10 10 10 10 10 10
03 aa aa aa aa
00 03 12 34 56 12 34 56
02 bb bb bb
00 02 0a 14 posun o 10 pixelů vpravo a 20 pixelů dolů
02 cc cc cc
00 00 konec řádku
01 dd dd
00 01 konec bitmapy

Jestliže je položka biCompression struktury BITMAPINFOHEA­DERnastavena na hodnotu BI_RLE4, je bitmapa komprimovaná RLE metodou pro 16barevné bitmapy.

Informace jsou v bitmapě organizovány do skupiny dvou bytů. První byte určuje počet po sobě jdoucích pixelů, které budou mít index barvy určený v druhém bytu. Druhý byte obsahuje dva indexy barev, uložené v nejvyšších resp. nejnižších čtyřech bitech daného bytu (masky pro získání těchto čtyřech bitů jsou 0×0f a 0×f0). První pixel ve skupině je zobrazený barvou s indexem získaným maskou 0×f0, druhý pixel barvou s indexem získaným maskou 0×0f. Třetí pixel má barvu stejnou jako první pixel atd. Barvy jsou postupně přiřazeny všem pixelům ve skupině.

První byte ve skupině může být nastaven na nulu, což znamená tzv. únik: např. konec řádku, konec bitmapy nebo delta. Typ úniku je zapsán v druhém bytu skupiny. Význam jednotlivých únikových hodnot:

Tabulka č. 524
hodnota druhého byte ve skupině význam úniku
0×00 indikuje konec řádku
0×01 indikuje konec bitmapy
0×02 delta – dva byty následující za touto hodnotou obsahují bezznaménkové (unsigned char) hodnoty, které znamenají horizontální a vertikální posunutí následujících pixelů od aktuální pozice
0×03–0×ff druhý byte určuje počet indexů barev, které následují v nezkomprimovaném tvaru.

Ukázka 16barevné bitmapy (všechny hodnoty jsou zapsané v hexadecimálním tvaru):

Tabulka č. 525
Komprimovaná data Nekomprimovaná data
05 01 0 1 0 1 0
03 12 1 2 1
00 06 12 34 56 1 2 3 4 5 6
04 ab a b a b
00 02 0a 14 posun o 10 pixelů vpravo a 20 pixelů dolů
02 cc c c
00 00 konec řádku
09 ef e f e f e f e f e
00 01 konec bitmapy

Pokračování

V dalším pokračování si popíšeme formát souboru TGA, který je poněkud flexibilnější a jednodušší než formát BMP.

Demonstrační příklad

Dnes si ukážeme pouze jeden demonstrační příklad. V tomto příkladu se nejprve načtou textury ze souborů typu BMP a posléze se vykreslí trojrozměrná scéna s tělesy pokrytými texturami. Pro spuštění tohoto příkladu jsou zapotřebí soubory ground.bmp, treasure.bmp, wall1.bmp awall2.bmp, které jsou spolu se zdrojovým kódem zabaleny do zip souboru opengl26.zip. Pro prohlížení je k dispozici i samostatný zdrojový soubor popř. tentýž soubor s obarvenou syntaxí.

Ovládání demonstračního programu je možné buď myší (pohybem vlevo a vpravo se provádí otáčení ve scéně, tlačítka slouží k chůzi vpřed a vzad), nebo klávesnicí (šipky pro pohyb a otáčení, CTRL+šipky pro úkroky). BTW: v zobrazeném bludišti je na dvou místech ukryt „poklad“ – viz také screenshot.

root_podpora

Screenshot z demonstračního příkladu
Obrázek 1: Screenshot z demonstračního příkladu

Pro majitele pomalejšího připojení k internetu je zde k dispozici celý článek i s přílohami zabalený do jednoho zip souboru.

Byl pro vás článek přínosný?

Autor článku

Vystudoval VUT FIT a v současné době pracuje na projektech vytvářených v jazycích Python a Go.