Texturování 5
Obsah
Rastrové soubory a OpenGLPopis formátu rastrového souboru BMP
Použití formátu BMP
Struktura BMP souboru
Hlavička souboru BMP (datová struktura BITMAPFILEHEADER)
Informace o obraze (datová struktura BITMAPINFOHEADER)
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í glTexParameteri(), 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 BITMAPFILEHEADER), informační hlavičku (strukturu BITMAPINFOHEADER), 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
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í:
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:
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í:
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:
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):
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 BITMAPINFOHEADERnastavena 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:
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):
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.
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.