OpenGL Imaging Subset (5)

30. 3. 2004
Doba čtení: 8 minut

Sdílet

Tento díl seriálu o OpenGL Imaging Subsetu přímo navazuje na díl předchozí, v němž jsme si popsali, které barvové palety je možné při zpracování rastrových obrazů použít. V dnešním dílu si popíšeme způsob nastavení parametrů, které ovlivňují naplnění barvové palety. Dále budou popsány operace pro zjištění těchto parametrů, změnu barvové palety, načtení barvové palety přímo z framebufferu a změnu části barvové palety.

Obsah

Parametry ovlivňující naplnění barvové palety
Zjištění parametrů ovlivňujících naplnění barvové palety
Vytvoření barvové palety z hodnot přečtených z framebufferu
Změna části barvové palety
Změna části barvové palety z hodnot přečtených z framebufferu
Pokračování
Seznam funkcí zmíněných v této části
Nové funkce popsané v této části
Demonstrační příklady
Zkomprimovaná verze článku

Parametry ovlivňující naplnění barvové palety

Při zápisu dat do barvové palety pomocí minule popsané funkce glColorTable() se mohou s barvami provádět dvě jednoduché operace: vynásobení vstupujících barvových hodnot konstantou (scale) a přičtení konstanty (bias). Tyto operace se na barvové složky aplikují ihned po sobě, tj. napřed se provede vynásobení konstantou scale, následně součet s konstantou bias. Konstanty scale a bias, kterými se budou jednotlivé barvové složky pixelů (barvová paleta je zadaná pomocí pixmapy) násobit, resp. s nimi sčítat, se zadávají pomocí funkcí:

void glColorTableParameteriv(
    GLenum        target,
    GLenum        pname,
    const GLint   *params
);

void glColorTableParameterfv(
    GLenum        target,
    GLenum        pname,
    Const GLfloat *params
);

kde:

  • V argumentu target se předává jméno barvové palety. Tento argument může nabývat stejných hodnot jako odpovídající argument funkce glColorTable(), tj. GL_COLOR_TABLE,GL_POS­T_CONVOLUTION_CO­LOR_TABLE, nebo GL_POST_COLOR_MAT­RIX_COLOR_TAB­LE.
  • Argument pname označuje, která ze dvou konstant se nastavuje: GL_COLOR_TABLE_SCA­LE pro nastavení konstanty scale, nebo GL_COLOR_TABLE_BI­AS pro nastavení konstanty bias.
  • Argument params obsahuje ukazatel na pole čtyř hodnot, kde na každou složku R, G, B a A připadá jedna hodnota. Pro každou barvovou složku (i pro alfa hodnotu) je možné nastavit jiné hodnoty konstant scale a bias. Pokud jsou hodnoty reprezentované typem GLfloat, jsou přímo zapsány do odpovídajících konstant, pokud se jedná o hodnoty typu GLint, provede se nejdříve jejich převod na typ GLfloat. Způsob převodu je stejný jako u funkce glDrawPixels().

Zjištění parametrů ovlivňujících naplnění barvové palety

Aktuálně nastavené hodnoty všech konstant scale a bias lze zjistit pomocí následujících dvou funkcí:

void glGetColorTableParameterfv(
    GLenum  target,
    GLenum  pname,
    GLfloat *params
);

void glGetColorTableParameteriv(
    GLenum  target,
    GLenum  pname,
    GLint   *params
);

Význam jednotlivých argumentů funkcí glGetColorTable­Parameterfv() a glGetColorTable­Parameteriv():

  • V argumentu target musí být zadáno jméno barvové palety, jejíž konstanty bias nebo scale potřebujeme zjistit. Podobně jako u funkce glColorTable(), i zde se jedná o jednu z hodnotGL_CO­LOR_TABLE, GL_POST_CONVO­LUTION_COLOR_TAB­LE a GL_POST_COLOR_MAT­RIX_COLOR_TAB­LE.
  • Argumentem pname, který může obsahovat hodnotu GL_COLOR_TABLE_SCA­LE nebo GL_COLOR_TABLE_BI­AS, je specifikováno, zda se mají vrátit multiplikativní konstanty scale, nebo aditivní konstanty bias.
  • Poslední argument pname obsahuje ukazatel na oblast paměti, do které se hodnoty konstant zaznamenají. Alokovaná paměť musí mít volné místo pro čtyři položky, protože se pro každou barvovou složku R, G, B a A ukládá jedna hodnota.

Vytvoření barvové palety z hodnot přečtených z framebufferu

Barvová paleta nemusí být specifikována pouze pomocí vhodné pixmapy přenášené z operační paměti počítače, jak tomu bylo u funkce glColorTable(). Vhodnou pixmapu je také možné přečíst přímo z framebufferu. K tomuto účelu se používá funkce:

void glCopyColorTable(
    GLenum  target,
    GLenum  internalFormat,
    GLint   x,
    GLint   y,
    GLsizei width
);

Barvy jsou získány stejným způsobem (tj. prochází stejnou částí grafického vykreslovacího řetězce) jako při zadání pixmapy pomocí funkce glColorTable(), pouze se liší zdroj dat, kterým je nyní místo operační paměti framebuffer. Význam jednotlivých argumentů funkce glCopyColorTa­ble():

  • Parametr target obsahuje jméno barvové palety, jejíž položky se mají z framebufferu přečíst. Povolené hodnoty tohoto argumentu jsouGL_COLOR_TAB­LE, GL_POST_CONVO­LUTION_COLOR_TAB­LE nebo GL_POST_COLOR_MAT­RIX_COLOR_TAB­LE.
  • Význam argumentu internalFormat je stejný jako u funkce glColorTable(). V tomto argumentu je uložen interní formát dat barvové palety, tj. formát, do kterého se (nezávisle na vstupním rastrovém obrázku) barvová paleta uloží. Mezi povolené hodnoty, které je možné v tomto argumentu zadat, patří: GL_RGBA, GL_RGB, GL_RED,GL_GRE­EN, GL_BLUE, GL_ALPHA atd. Nejpoužívanější jsou hodnoty GL_RGBA a GL_RGB, pomocí kterých lze vytvořit barvovou paletu s výběrem libovolné barvy z celého barevného spektra.
  • Hodnoty argumentů x a y specifikují levý dolní roh pixmapy ve framebufferu, která se bude číst. Souřadnice levého rohu jsou zadány přímo v pixelech, neprovádí se s nimi tedy žádná transformace (na rozdíl od souřadnic vrcholů vykreslovaných plošek).
  • V argumentu width je uložena šířka pixmapy, která odpovídá počtu přečtených barev. Podobně jako u funkce glColorTable(), i u této funkce se nemusí zadávat výška pixmapy, neboť je vždy rovna jednomu řádku pixelů.

Změna části barvové palety

V některých případech může být žádoucí změnit pouze část barvové palety. Z hlediska rychlosti zpracování je, oproti opakovanému čtení a zápisu celé palety, mnohdy výhodnější upravit pouze některé barvové položky. Pro tento účel je možné použít funkci glColorSubTable() s následující hlavičkou:

void glColorSubTable(
    GLenum  target,
    GLsizei start,
    GLsizei count,
    GLenum  format,
    GLenum  type,
    void    *data
);

Význam jednotlivých argumentů funkce glColorSubTable():

  • Argument target musí obsahovat jednu z následujících hodnot: GL_COLOR_TABLE, GL_POST_CONVO­LUTION_COLOR_TAB­LE aGL_POST_COLOR_MAT­RIX_COLOR_TAB­LE pro přímou modifikaci barvové palety.
  • Argument start obsahuje index první barvové složky, která se má v barvové paletě změnit. Celkový počet položek je zjištěn v okamžiku vytváření barvové palety pomocí funkce glColorTable() nebo glCopyColorTa­ble().
  • Argument count obsahuje počet položek barvové palety, které se mají změnit. Součet start+count by neměl překročit celkový počet položek (indexů) v barvové paletě. V případě, že k překročení dojde, je generována chyba.
  • V argumentu format je zadán formát dat, které jsou funkci glColorSubTable() předávány. Význam jednotlivých hodnot je stejný jako u funkce glDrawPixels(), povolené hodnoty tohoto argumentu jsou: GL_RGBA, GL_RGB, GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA a rozšířené formáty jakoGL_BGR_EXT, GL_BGRA_EXT apod.
  • Argument type má, podobně jako argument předchozí, stejný význam jako u funkce glDrawPixels() – lze pomocí něj specifikovat, jaký formát budou mít jednotlivé barvové složky předávaných pixelů. Povolené hodnoty jsou GL_UNSIGNED_BYTE, GL_BYTE, GL_UNSIGNED_SHOR­T,GL_SHORT, GL_UNSIGNED_INT, GL_INT a GL_FLOAT. Všimněte si, že není povolen typ GL_BITMAP, který by při práci s barvovou paletou nedával smysl.
  • V argumentu data je předán ukazatel na rastrová data přenášeného obrázku. Při přenosu se provádí datové konverze a případné rozpakování barvových hodnot pixelů podobně jako při vykreslování rastrových bitmap (funkce glBitmap) a pixmapy (funkce glDrawPixels).

Změna části barvové palety z hodnot přečtených z framebufferu

Existuje ještě jedna funkce, pomocí které je možné nastavit část barvové palety. Tato funkce však nečte potřebná data z operační paměti počítače, ale přímo z framebufferu. Jedná se tedy o sloučení vlastností funkcí glCopyColorTa­ble() a glColorSubTable(), čemuž také odpovídá název funkce: glCopyColorSub­Table(). Tato funkce má hlavičku:

void glCopyColorSubTable(
    GLenum  target,
    GLsizei start,
    GLint   x,
    GLint   y,
    GLsizei width
);

Význam jednotlivých argumentů funkce glCopyColorSub­Table() je velmi podobný oběma předešlým funkcím. Za zmínku stojí pouze fakt, že počet položek, které mají být v barvové paletě změněny, není zadán v argumentu count, ale v argumentu width. Počet měněných položek tedy odpovídá šířce pixmapy přečtené z framebufferu. Vzhledem k tomu, že se hodnoty čtou přímo z framebufferu, není zapotřebí definovat formát dat.

Pokračování

V dalším pokračování tohoto seriálu se budeme zabývat velmi zajímavou tematikou – tvorbou a použitím konvolučních filtrů pomocí Imaging Subsetu. Konvoluční filtry lze použít pro aplikaci mnoha grafických efektů, například rozmazání obrázku, zvýraznění hran nebo zobrazení obrázku jako vystouplého či naopak jakoby vytesaného reliéfu.

Seznam funkcí zmíněných v této části

glColorTable()
glDrawPixels()
glBitmap()
 

Nové funkce popsané v této části

glColorTablePa­rameteriv()
glColorTablePa­rameterfv()
glGetColorTable­Parameterfv()
glGetColorTable­Parameteriv()
glCopyColorTable()
glColorSubTable()
glCopyColorSub­Table()
 

Demonstrační příklady

Po překladu a spuštění prvního demonstračního příkladu se zobrazí obrázek Leny. Zobrazení se provádí pomocí nám již známé funkce glDrawPixels(), ale s modifikací barvové palety, která se provádí pomocí příkazu glColorTable(). Tento příkaz je vyvolán ve funkciprepare­ColorTable().

Pomocí klávesy P lze použití barvové palety, tj. přemapování barvových složek jednotlivých pixelů, povolit či zakázat. V demonstračním programu se tak děje s využitím příkazů glEnable(GL_CO­LOR_TABLE) a glDisable(GL_CO­LOR_TABLE).

Barevná paleta je nastavena tak, aby prováděla gama korekci, přičemž gama křivka má exponent větší než jedna. To znamená, že se zvyšuje kontrast světlých barev a současně se obrázek jako celek jeví poněkud tmavší.

Rozdíl mezi obrázkem bez aplikované gama korekce a s aplikovanou gama korekcí je vidět na prvním a druhém obrázku.

Zdrojový kód prvního demonstračního příkladu je dostupný zde, HTML verze se zvýrazněním syntaxe zde.

Screenshot prvního demonstračního příkladu s vypnutou gama korekcí
Obrázek 1: Screenshot prvního demonstračního příkladu s vypnutou gama korekcí

Screenshot prvního demonstračního příkladu se zapnutou gama korekcí
Obrázek 2: Screenshot prvního demonstračního příkladu se zapnutou gama korekcí

Druhý demonstrační příklad je prakticky totožný s příkladem prvním. Jediný rozdíl spočívá v tom, že se při výpočtu gama křivky používá exponent menší než jedna. Výsledek je přesně opačný než u prvního příkladu: zvyšuje se kontrast tmavých barev a obrázek se současně jeví poněkud světlejší.

Aplikace gama křivek pomocí palet je samozřejmě pouze jednou z možností, pro které lze barvové palety využít. Mnohem zajímavější je použití palet pro tvorbu jednoduchých animací.

Pro spuštění demonstračních příkladů je nutné mít stažený i původní obrázek Leny, který pro jistotu opět přikládám i do zkomprimované verze článku, i když je totožný s obrázkem z předchozí části.

Zdrojový kód druhého demonstračního příkladu je dostupný zde, HTML verze se zvýrazněním syntaxe zde.

ict ve školství 24

Screenshot druhého demonstračního příkladu
Obrázek 3: Screenshot druhého demonstračního příkladu

Zkomprimovaná verze článku

Zkomprimovaná verze tohoto článku spolu s demonstračními příklady a obrázky je umístěna zde.

Autor článku

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