1.1 Úvod
Vykreslování bitmap jednou z nejčastějších operací v oblasti grafického výstupu.
Jedním ze známých problémů při kreslení těchto obrázků je pak zajištění
"průhlednosti", tzn. částečné zachování původního pozadí. V
následujícím čtyřdílném seriálu si ukážeme jak tento problém řešit pomocí
rastrových operací a související metody BitBlt (StretchBlt). Krok za
krokem si rozebereme celý postup kreslení bitmap na typickém příkladu a ukážeme si
jaké možnosti nám zmíněná metoda dává
1.2 Vykreslení bitmapy
Nejjednodušší způsob použití obrázku v aplikaci je použití standardní bitmapy,
která je uložena ve zdrojích aplikace.Takovou bitmapu lze pak velice jednoduše nahrát
použitím metody LoadBitmap a vykreslit na obrazovku metodou BitBlt (v
původní velikosti). Další možností je použití metody StretchBlt, která
umožňuje změnu výsledné velikosti bitmapy. Naším prvním příkladem tedy bude
ukázka vykreslení bitmapy.
Prvním krokem je vložení bitmapy do zdrojů aplikace. Tato akce je
jednoduchá a lze ji provést například volbou Insert->Resource z hlavního
menu. Ve vyvolaném dialogu zvolíme typ zdroje Bitmap a ukončíme tlačítkem New.
Pomocí jednoduchých prostředků Visual C++ lze nyní bitmapu editovat.

V záhlaví předchozího obrázku je patrné symbolické jméno
(definované pomocí příkazu preprocesoru - #define) IDB_FROG,
které používáme pro identifikaci bitmapy. Toto jméno je reprezentováno číselnou
konstantou jejíž hodnotu můžeme v případě potřeby nalézt v hlavičkovém souboru resource.h.
Z obrázku je dále patrné pozadí, které je vyplněno červenou barvou. Tato barva
bude později prohlášena za "průhlednou".
Dalším krokem je nahrání vytvořené bitmapy ze zdrojů. Pro
tento úkol využijeme třídy CBitmap z knihovny MFC a její metodu LoadBitmap.
Pokud se bitmapu ze zdrojů aplikace nepodaří nahrát, vrátí tato metoda hodnotu FALSE.
Následujcí zdrojový kód ukazuje použití této třídy a metody.
CBitmap oBitmap;
if (!oBitmap.LoadBitmap(IDB_FROG))
return; |
Nyní nezbývá, než bitmapu vykreslit. Je možná trochu
překvapující, že třída CBitmap nemá metodu Draw, ale později
nám bude jasné proč. Také algoritmus kreslení bitmapy není tak triviální, jak
bychom čekali. Podívejme se opět nejdříve na ukázku zdrojového kódu.
CDC oMemDC;
if (!oMemDC.CreateCompatibleDC(pDC))
return;
BITMAP bmp;
oBitmap.GetBitmap(&bmp);
CBitmap* pOldBitmap = oMemDC.SelectObject(&oBitmap);
pDC->BitBlt(0, 0, bmp.bmWidth, bmp.bmHeight, &oMemDC, 0, 0, SRCCOPY);
oMemDC.SelectObject(pOldBitmap); |
Jak je z ukázky vidět, bitmapu nelze vytisknout přímo. Je nutné
vytvořit dočasný paměťový kontext zařízení (oMemDC), do kterého bitmapu
vložíme a odkud ji metodou BitBlt přemístíme do skutečného (cílového)
kontextu zařízení pDC.

Tento princip jednoduše využívá toho, že bitmapa může ve Windows
představovat pseudo vstupně/výstupní zařízení. Jak také vidíme z předchozího
obrázku, kontext vlastně představuje vstupní bod k tomuto zařízení a metody BitBlt
a StrecthBlt umožňují provádět rastrové operace (přesuny bitových map)
mezi těmito kontexty. Pozorný čtenář si jistě povšimne, že operace lze provádět
oběma směry, můžeme například snímat obsah obrazovky (videopaměti).
Nyní se můžeme vrátit k našemu příkladu. Prvním krokem je
vytvoření paměťového kontextu zařízení oMemDC, který je kompatibilní s
obrazovým kontextem pDC. K tomuto účelu použijeme metodu CreateCompatibleDC.
Pro zjištění velikosti vykreslované bitmapy použijeme metody GetObject,
která inicializuje předanou strukturu BITMAP. V dalším kroku vybereme
bitmapu, voláním metody SelectObject do paměťového kontextu a vytiskneme ji
pomocí BitBlt. (tato metoda používá rastrovou operaci SRCCOPY).
Návratovou hodnotou metody SelectObject je původní objekt (původní bitmapa)
v kontextu, který musíme po ukončení tisku vrátit. Hlavička metody BitBlt
je následující.
BOOL BitBlt( int x, int y, int nWidth, int nHeight, CDC* pSrcDC,
int xSrc, int ySrc, DWORD dwRop ); |
|
|
x
|
Logická x-ová souřadnice levého horního rohu cílového obdélníku. |
y |
Logická y-ová souřadnice levého horního rohu cílového obdélníku. |
nWidth |
Šířka cílového obdélníku (v bodech). |
nHeight |
Výška cílového obdélníku (v bodech). |
pSrcDC |
Ukazatel na zdrojový kontext zařízení. Pokud je použita rastrová
operace, která nezahrnuje zdroj musí být nastaveno na NULL. |
xSrc |
Logická x-ová souřadnice levého horního rohu ve zdrojové bitmapě,
odkud začne kopírování. |
ySrc |
Logická y-ová souřadnice levého horního rohu ve zdrojové bitmapě,
odkud začne kopírování. |
dwRop |
Typ provedené rastrové operace. Tato operace definuje kombinaci barev ve
výsledné operaci. Tato operace může zahrnovat aktuální štětec, zdrojovou bitmapu
nebo cílovou bitmapu. |
Pokud bychom při vykreslování bitmapy chtěli měnit její velikost,
použijeme metodu StretchBlt. Tato metoda se od předcházející liší pouze
dvěma parametry.
BOOL StretchBlt( int x, int y, int nWidth, int nHeight, CDC* pSrcDC,
int xSrc, int ySrc, int nSrcWidth, int nSrcHeight, DWORD dwRop ); |
|
|
nSrcWidth |
Šířka zdrojového obdélníku (v bodech). |
nSrcWidth |
Výška zdrojového obdélníku (v bodech). |
Výsledek našeho příkladu je znázorněn na následujícím
obrázku.

Pokud bychom chtěli při tisku bitmapy měnit její velikost můžeme
použít metodu BitBlt. Podívejme se na ukázku volání této metody.
pDC->StretchBlt(0, 0, bmp.bmWidth * 2, bmp.bmHeight, &oMemDC, 0, 0,
bmp.bmWidth, bmp.bmHeight, SRCCOPY); |
Výsledek by pak je následující.

Příště rastrové operace... |