|
|
|
Drawing to a Bitmap
Starting with the earliest versions of Windows and continued with the Win32 API, the device context
used for manipulating graphics in the GDI library has been a mainstay of Windows graphics programming.
I have found the need to do more than just render graphics on a monitor or printer. Every once in a while
I need to render graphics right onto a bitmap image. Recently, I found a need to do this when I was
working with some code that needed to render TrueType fonts onto a screen painted through calls to the
FastGraph library.
The basic concept is that the GDI calls work on a memory based device context that has a bitmap
selected into it. Any subsequent calls drawing to that device context will result in drawing directly onto
the selected bitmap.
char *string = "My Text";
HDC dc = GetDC(GetDesktopWindow());
HFONT ttfont = CreateFont(-10*GetDeviceCaps(dc, LOGPIXELSY)/72, 0, 0, 0, FW_NORMAL, 0, 0, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS | CLIP_LH_ANGLES, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, "Arial");
HDC memdc = CreateCompatibleDC(dc);
HBITMAP hbmp, hbmpOld;
SIZE textsize;
RECT textrect = {0};
COLORREF transparent = 0; // black is transparent for FastGraph in this instance
HBRUSH transbrush = CreateSolidBrush(transparent);
BITMAPINFO bmi = {0};
COLORREF *dibuf;
SelectObject(memdc, ttfont);
GetTextExtentPoint32(memdc, string, strlen(string), &textsize);
textrect.right = textsize.cx;
textrect.bottom = textsize.cy;
hbmp = CreateCompatibleBitmap(dc, textsize.cx, textsize.cy);
hbmpOld = SelectObject(memdc, hbmp);
FillRect(memdc, &textrect, transbrush);
SetBkColor(memdc, transparent);
SetTextColor(memdc, textcolor);
DrawText(memdc, string, -1, &textrect, DT_SINGLELINE);
SelectObject(memdc, hbmpOld);
bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
bmi.bmiHeader.biWidth = textsize.cx;
bmi.bmiHeader.biHeight = -textsize.cy;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biSizeImage = textsize.cx * 4 * textsize.cy;
dibuf = (COLORREF *)malloc(bmi.bmiHeader.biSizeImage);
if (GetDIBits(memdc, hbmp, 0, textsize.cy, dibuf, &bmi, DIB_RGB_COLORS))
{
// copy pixels over to FastGraph buffers
}
free(dibuf);
DeleteObject(transbrush);
DeleteObject(hbmp);
DeleteDC(memdc);
ReleaseDC(dc);
The call to GetDIBits using 32 bits per pixel makes the copying process simpler when dealing with true color
displays. It is important that the device context used to create the compatible bitmap is NOT the one created in
memory. That is why dc is used instead of memdc in the call to CreateCompatibleBitmap
above.
|