Bittérkép műveletek

A bittérképekkel alapvetően négy fajta műveletet lehet végezni: egy adott eszközön már létrehozott képet a bittérképbe lehet menteni, a keletkezett bittérképet a memóriában vagy a merevlemezen lehet tárolni képet illetve onnan visszatölteni, a bittérképekről információkat lehet gyűjteni, valamint a bittérképet tetszőleges eszközön meg lehet jeleníttetni.

Egy adott eszközön már létrehozott kép bittérképbe mentéséhez, vagy az elmentett kép kirajzolásához az alkalmazásnak először egy ún. kompatibilis eszközkörnyezetet kell létrehoznia a forrásként illetve majdan célként szolgáló eszközkontextus alapján a CreateCompatibleDC() függvény segítségével. A kompatibilis eszközkörnyezet a mintaként szolgáló eszközkontextussal minden jellemzőjében (színmélység, felbontás, stb.) teljesen egyezik, kivéve, hogy nem valódi eszközhöz kötődik, hanem a rajta keresztül történő rajzolóműveletek eredménye kizárólag a memóriába, mégpedig egy bittérképben jelenik meg. Ahhoz, hogy egy kompatibilis eszközkörnyezetbe rajzolni lehessen, az alkalmazásnak először létre kell hoznia és ki kell választania bele egy, a rajzoló-műveletek eredményét tároló bittérképet. E objektum létrehozására az alkalmazásnak a CreateCompatibleBitmap(), kiválasztására pedig a már megismert SelectObject() függvény segítségével nyílik módja. A bittérkép kiválasztása után a kompatibilis eszközkörnyezet készen áll a kép információk tárolására és visszaadására.

Természetesen bittérképek nem csak már létező eszközkörnyezetek alapján, hanem tetszőleges paraméterekkel is létrehozhatók a CreateBitmap() illetve a CreateBitmapIndirect() függvényekkel, mely hívásokban a kép kiterjedése mellett színábrázolására vonatkozó információk, sőt, (bináris) tartalma is megadásra kerülhet. Ugyancsak itt érdemes megemlíteni a már korábban létrehozott bittérképek betöltéséhez használható LoadBitmap() illetve LoadImage() függvényeket is.

Eszközkörnyezetek közötti képátvitelre számos függvényt bocsát a GDI a programozók rendelkezésére. Bár ezek a függvények segítségével bármely két eszközkörnyezet között lehetővé válik képi információk átvitele, tipikusan általában egy valódi és egy kompatibilis eszközkontextus között zajlik ez a művelet. A leggyakrabban használt képátviteli függvény a BitBlt(), amely téglalap alakú területek színinformációinak bit-blokk műveletek keretén belüli átvitelét végzi. A függvény paramétereiként a keletkező képinformációkat tároló cél-eszközkontextust, illetve azon belül a befoglaló téglalapkoordinátáit (bal felső sarkát és kiterjedését) kell megadni, amelyeket a forrás-eszközkörnyezet azonosítója, majd a forrás-információkat szolgáltató téglalap bal felső sarkának koordinátái követik (a forrástéglalap kiterjedése megegyezik a céltéglalapéval). A paraméterek listáját az ún. raszter-operiációs kód (Raster OPeration - ROP) zárja. Ez utóbbi paraméter azt határozza meg, hogy a céleszközkörnyezetben a céltéglalapban létrejövő kép a forrás- illetve cél-pixelek milyen kombinációjaként kerül létrehozásra. A ROP valójában egy diszkrét bitmezőkre bontható szám, amely a kép előállításához használandó operandusokat (forrás és célpixel színei, inverzei, fekete, fehér, stb.) illetve az azok között végrehajtandó műveletet (bináris XOR, AND, OR, stb.) kódolja. Amennyiben a cél- és a forrás-eszközkörnyezet színformátuma nem egyezik, úgy a művelet elvégzése előtt a forrásképet a célkörnyezet formátumára hozza a GDI, majd így végzi el rajtuk a meghatározott műveletet.

A ROP műveletek leggyakrabban használt kombinációit takaró konstansokat és jelentéseiket az alábbi táblázat tartalmazza:
 

ROP kód Jelentés
BLACKNESS A céltéglalapot a fizikai paletta 0. elemének megfelelő színnel (ez általában a fekete) tölti ki.
DSTINVERT Invertálja a céltéglalap színeit.
SRCAND A forrás- és a céltéglalap színeit a logikai AND művelet segítségével kombinálva állítja elő a céltéglalap tartalmát
SRCCOPY A forrástéglalap tartalmát a céltéglalapba másolja (felülírja)
SRCINVERT A forrás- és a céltéglalap színeit a logikai XOR művelet segítségével kombinálja
SRCPAINT A forrás- és a céltéglalap színeit a logikai OR művelet segítségével kombinálja
WHITENESS A céltéglalapot a fizikai paletta 1. elemének megfelelő színnel (ez általában a fehér) tölti ki.

Az alábbi ábrákon az egyes ROP műveletek hatása közti különbség jól megfigyelhető:
 
 

Amint az paramétereinek listájából következik, a BitBlt() függvény nem alkalmas torzítási műveletek elvégzésére, hiszen a forrás- és céltéglalap kiterjedései megegyeznek. Amennyiben az alkalmazás a forrástól eltérő horizontális és/vagy vertikális kiterjedésű célképet szeretne kapni, úgy a StretchBlt() függvényt kell használnia, amely a céltéglalap kiterjedésének a forrásétól független megadását is lehetővé teszi. Amennyiben a cél és a forrás-téglalap kiterjedéséinek előjele eltér, úgy a GDI a megfelelő tengelyek mentén tükrözést alkalmaz a célkép előállítása során.

Bizonyos esetekben szükség lehet arra, hogy ne téglalap alakú területen, hanem egy adott kép vagy képek csak bizonyos pontjainak bevonásával végezzen az alkalmazás műveletet. Ilyen esetekben használható effektíven a MaskBlt() függvény, ami a BitBlt() funkcionalitását bővíti ki úgy, hogy egy harmadik, monokróm bitmap (a maszk) bevonásával teszi lehetővé az alkalmazás számára, hogy meghatározza mely pixelpozíciókban milyen műveletet kíván végezni a forrás- és cél-operandusok (pixelek) között. Ugyanis az eljárás utolsó paramétereként átadott, a MAKEROP4() függvény segítségével előállítható műveleti-páros kombináció két eleme közül mindig a maszk-bitmap adott pozícióban elhelyezkedő pixelének be- illetve kikapcsolt állapotától függ, hogy az első v. a második művelet hajtódik -e végre a forrás- és a célképpont között.

Az itt látható ábra pl. úgy került létrehozásra, hogy a téglalapokat tartalmazó kép monokrómra konvertált változata (fehér alapon három fekete téglalap) maszkként lett megadva a második (macskás) képet, mint forrást és az (SRCCOPY, NOTSRCCOPY) műveleti párost alkalmazó MaskBlt() hívásban. Így a célképben a maszk fekete pixeljeinek helyén a forráskép eredeti, meg a maszk fehér pixeljei helyén a forráskép invertált változata jelent meg.

Amennyiben egy bittérképnek csak bizonyos színű pixeleit nem kívánjuk a célképre kirajzoltatni, úgy érdemes inkább a TransparentBlt() függvény használatához folyamodni, amely a torzítás mellett lehetőséget nyújt ennek egyszerű megvalósítására is. A függvénynek már megszokott, a cél- és forrás-eszközkontextust azonosító, valamint a forrás- és céltéglalapot meghatározó paramétereken túl csak azt az RGB komponenseivel meghatározott színt kell átadni, amely színeket tartalmazó pixeleket ki kívánjuk zárni a rajzolási műveletből, azaz amelyek helyén meg kívánjuk hagyni a célkép képpontjainak színét. Pl. az itt látható ábrán a második (macskás) képre került az első, téglalapokat tartalmazó kép rámásolásra úgy, hogy a kék tisztán színű (RGB: 0,0,255) pixelek kerültek a műveletből kizárásra, azaz, az ezekből álló középső téglalap helyén továbbra is megmaradt az eredeti kép tartalma.
 

A StrectBlt()-hez hasonlóan ugyancsak torzításra nyújt lehetőséget a PlgBlt() függvény melynek segítségével azonban téglalap helyett parallelogram alakba torzíthatjuk át az eredetileg téglalap alakú forrásképet. A függvény a forrás- és céleszközkontextuson, a forrástéglalapon és a ROP műveleti kódon kívül a parallolgrammát három sarokpontjának koordinátáival egyértelműen meghatározó (a negyediket automatikusan számítja) tömböt várja, valamint a MaskBlt()-hez hasonlóan opcionálisan maszk-bitkép is átadható neki.

Azt, hogy az egyes torzítások során a GDI milyen algoritmus szerint járjon el a "felesleges" pixelek/pixelsorok eltávolításakor az ún. nyújtási mód (strecth mode) határozza meg. E beállítás lekérdezésére a GetStretchBltMode(), míg megváltoztatására a SetStretchBltMode() függvény segítségével nyílik lehetőség. Az alábbi táblázat az alkalmazható beállításokat tartalmazza:
 

Nyújtási mód Jelentés
BLACKONWHITE Logikai ÉS műveletet végez a meghagyott és az eliminált pixelek színei között. Monokróm bitképek esetén ez gyakorlatilag a fekete pixeleket "részesíti előnyben" a fehérekkel szemben.
COLORONCOLOR A kiszűrt pixelek színinformációt figyelmen kívül hagyja. (gyakorlatilag nem törekszik az elveszett színinformáció megőrzésére, ami éles határvonalak kialakulását eredményezheti)
HALFTONE A létrehozott célképben a pixelek színeit úgy alakítja ki, hogy adott területen belül azok átlaga megegyezzen a forrásképben eredetileg meglévővel. (gyakorlatilag elmossa az éles kontúrokat)
WHITEONBLACK Logikai VAGY műveletet végez a meghagyott és az eliminált pixelek színei között. Monokróm bitképek esetén ez gyakorlatilag a fehér pixeleket "részesíti előnyben" a feketékkel szemben.

Az alapértelmezett nyújtási mód a BLACKONWHITE. A legszebb eredményt a HALFTONE mód generálja, azonban alkalmazása rendkívüli mértékben megnöveli a feldolgozási időt, így a gyakorlatban inkább a közepesen jó eredményt nyújtó COLORONCOLOR módot szokás legtöbbször alkalmazni.

Természetesen az bittérképek akár pixelenként is manipulálhatók a GetPixel() / SetPixel() függvénypáros segítségével. A bittérképhez tartozó paletta bejegyzései a GetDIBColorTable() / SetDIBColorTable() páros segítségével kérdezhetők le illetve módosíthatók. A bittérkép bináris tartalma szintén elérhető a GetDIBits() / SetDIBits() függvénypároson keresztül, melyek segítségével akár a teljes bittérkép, akár csak egyes részeit reprezentáló színinformációk közvetlenül hozzáférhetővé válnak.

(folytatjuk)