-
Dynamic Bitmap Display
Code:
BITMAP CustomBMP;
HBITMAP hCustomBMP;
BITMAPINFO CustomBMPInfo;
BYTE BitmapData[16];
RGBQUAD* Palette;
Code:
case WM_CREATE:
{
Palette = malloc(16);
Palette[0].rgbRed = 0;
Palette[0].rgbGreen = 0;
Palette[0].rgbBlue = 0;
Palette[1].rgbRed = 255;
Palette[1].rgbGreen = 0;
Palette[1].rgbBlue = 0;
Palette[2].rgbRed = 0;
Palette[2].rgbGreen = 255;
Palette[2].rgbBlue = 0;
Palette[3].rgbRed = 0;
Palette[3].rgbGreen = 0;
Palette[3].rgbBlue = 255;
Palette[4].rgbRed = 255;
Palette[4].rgbGreen = 255;
Palette[4].rgbBlue = 0;
Palette[5].rgbRed = 255;
Palette[5].rgbGreen = 0;
Palette[5].rgbBlue = 255;
Palette[6].rgbRed = 0;
Palette[6].rgbGreen = 255;
Palette[6].rgbBlue = 255;
Palette[7].rgbRed = 128;
Palette[7].rgbGreen = 0;
Palette[7].rgbBlue = 0;
Palette[8].rgbRed = 0;
Palette[8].rgbGreen = 128;
Palette[8].rgbBlue = 0;
Palette[9].rgbRed = 0;
Palette[9].rgbGreen = 0;
Palette[9].rgbBlue = 128;
Palette[10].rgbRed = 128;
Palette[10].rgbGreen = 128;
Palette[10].rgbBlue = 0;
Palette[11].rgbRed = 128;
Palette[11].rgbGreen = 0;
Palette[11].rgbBlue = 128;
Palette[12].rgbRed = 0;
Palette[12].rgbGreen = 128;
Palette[12].rgbBlue = 128;
Palette[13].rgbRed = 128;
Palette[13].rgbGreen = 128;
Palette[13].rgbBlue = 128;
Palette[14].rgbRed = 255;
Palette[14].rgbGreen = 255;
Palette[14].rgbBlue = 255;
Palette[15].rgbRed = 0;
Palette[15].rgbGreen = 0;
Palette[15].rgbBlue = 0;
BitmapData[0] = 0x01;
BitmapData[1] = 0x23;
BitmapData[2] = 0x45;
BitmapData[3] = 0x67;
BitmapData[4] = 0x89;
BitmapData[5] = 0xAB;
BitmapData[6] = 0xCD;
BitmapData[7] = 0xEF;
BitmapData[8] = 0x01;
BitmapData[9] = 0x23;
BitmapData[10] = 0x45;
BitmapData[11] = 0x67;
BitmapData[12] = 0x89;
BitmapData[13] = 0xAB;
BitmapData[14] = 0xCD;
BitmapData[15] = 0xEF;
CustomBMPInfo.bmiHeader.biSize = 40;
CustomBMPInfo.bmiHeader.biWidth = 16;
CustomBMPInfo.bmiHeader.biHeight = 2;
CustomBMPInfo.bmiHeader.biPlanes = 1;
CustomBMPInfo.bmiHeader.biBitCount = 4;
CustomBMPInfo.bmiHeader.biCompression = 0;
CustomBMPInfo.bmiHeader.biSizeImage = 0;
CustomBMPInfo.bmiHeader.biXPelsPerMeter = 0;
CustomBMPInfo.bmiHeader.biYPelsPerMeter = 0;
CustomBMPInfo.bmiHeader.biClrUsed = 16;
CustomBMPInfo.bmiHeader.biClrImportant = 0;
CustomBMPInfo.bmiColors = Palette;
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
hCustomBMP = CreateCompatibleBitmap(hdc,
CustomBMPInfo.bmiHeader.biWidth,
CustomBMPInfo.bmiHeader.biHeight);
GetObject(hCustomBMP, sizeof(CustomBMP), &CustomBMP);
SetDIBits(hdc, hCustomBMP, 0, CustomBMP.bmHeight, BitmapData, &CustomBMPInfo, DIB_RGB_COLORS);
HDC hdcMem = CreateCompatibleDC(hdc);
HBITMAP hbmOld = SelectObject(hdcMem, hCustomBMP);
BitBlt(hdc, 0, 0, CustomBMP.bmWidth, CustomBMP.bmHeight, hdcMem, 0, 0, SRCCOPY);
SelectObject(hdcMem, hbmOld);
DeleteDC(hdcMem);
DeleteObject(hCustomBMP);
EndPaint(hwnd, &ps);
}
break;
case WM_CLOSE:
{
free(Palette);
DestroyWindow(hwnd);
}
break;
I'm having problems trying to understand the SetDIBits, with a paletted bitmap, rather than a raw bitmap. I attached an image of the output, zoomed in by 800%, as well as an image of the output I was aiming for. Any ideas what I'm doing wrong?
-
Code:
Palette = malloc(sizeof(RGBQUAD) * 16);
-
Ahh. Thank you. That doesn't seem to be my problem, though. The output is the same.
-
Your params are wrong.
ie CustomBMPInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
Have a look here...
http://cboard.cprogramming.com/showt...ght=bmp+header
-
Code:
CustomBMPInfo.bmiColors = Palette;
This should not compile. The BITMAPINFO structure has the following definition:
Code:
typedef struct tagBITMAPINFO {
BITMAPINFOHEADER bmiHeader;
RGBQUAD bmiColors[1];
} BITMAPINFO, *PBITMAPINFO;
The bmiColors member is an array, and therefore can not be assigned to. BITMAPINFO consists of an BITMAPINFOHEADER followed by a variable sized array of palette entries. It is not a BITMAPINFOHEADER followed by a pointer to an array of palette entries, which your code attempts to create. Because the array may be of various sizes, it is defined with the placeholder size of 1, and the programmer is expected to allocate appropriate memory. This pattern is not uncommon in the Windows API.
I have modified your code to demonstrate:
Code:
#include <windows.h>
#include <stdio.h>
#if defined(_MSC_VER)
#pragma comment(lib, "gdi32.lib")
#endif
int main(void)
{
BITMAP CustomBMP;
HBITMAP hCustomBMP;
BYTE BitmapData[16];
BITMAPINFO* CustomBMPInfo;
RGBQUAD* Palette;
/* Allocate space for a BITMAPINFO structure followed by an array of RGBQUADs */
CustomBMPInfo = (BITMAPINFO*) malloc(sizeof(BITMAPINFO) + (sizeof(RGBQUAD) * 16));
/* TODO: check malloc. */
/* Convenience variable. We could use CustomBMPInfo->bmiColors directly. */
Palette = CustomBMPInfo->bmiColors;
Palette[0].rgbRed = 0;
Palette[0].rgbGreen = 0;
Palette[0].rgbBlue = 0;
Palette[1].rgbRed = 255;
Palette[1].rgbGreen = 0;
Palette[1].rgbBlue = 0;
Palette[2].rgbRed = 0;
Palette[2].rgbGreen = 255;
Palette[2].rgbBlue = 0;
Palette[3].rgbRed = 0;
Palette[3].rgbGreen = 0;
Palette[3].rgbBlue = 255;
Palette[4].rgbRed = 255;
Palette[4].rgbGreen = 255;
Palette[4].rgbBlue = 0;
Palette[5].rgbRed = 255;
Palette[5].rgbGreen = 0;
Palette[5].rgbBlue = 255;
Palette[6].rgbRed = 0;
Palette[6].rgbGreen = 255;
Palette[6].rgbBlue = 255;
Palette[7].rgbRed = 128;
Palette[7].rgbGreen = 0;
Palette[7].rgbBlue = 0;
Palette[8].rgbRed = 0;
Palette[8].rgbGreen = 128;
Palette[8].rgbBlue = 0;
Palette[9].rgbRed = 0;
Palette[9].rgbGreen = 0;
Palette[9].rgbBlue = 128;
Palette[10].rgbRed = 128;
Palette[10].rgbGreen = 128;
Palette[10].rgbBlue = 0;
Palette[11].rgbRed = 128;
Palette[11].rgbGreen = 0;
Palette[11].rgbBlue = 128;
Palette[12].rgbRed = 0;
Palette[12].rgbGreen = 128;
Palette[12].rgbBlue = 128;
Palette[13].rgbRed = 128;
Palette[13].rgbGreen = 128;
Palette[13].rgbBlue = 128;
Palette[14].rgbRed = 255;
Palette[14].rgbGreen = 255;
Palette[14].rgbBlue = 255;
Palette[15].rgbRed = 0;
Palette[15].rgbGreen = 0;
Palette[15].rgbBlue = 0;
BitmapData[0] = 0x01;
BitmapData[1] = 0x23;
BitmapData[2] = 0x45;
BitmapData[3] = 0x67;
BitmapData[4] = 0x89;
BitmapData[5] = 0xAB;
BitmapData[6] = 0xCD;
BitmapData[7] = 0xEF;
BitmapData[8] = 0x01;
BitmapData[9] = 0x23;
BitmapData[10] = 0x45;
BitmapData[11] = 0x67;
BitmapData[12] = 0x89;
BitmapData[13] = 0xAB;
BitmapData[14] = 0xCD;
BitmapData[15] = 0xEF;
CustomBMPInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
CustomBMPInfo->bmiHeader.biWidth = 16;
CustomBMPInfo->bmiHeader.biHeight = 2;
CustomBMPInfo->bmiHeader.biPlanes = 1;
CustomBMPInfo->bmiHeader.biBitCount = 4;
CustomBMPInfo->bmiHeader.biCompression = BI_RGB;
CustomBMPInfo->bmiHeader.biSizeImage = 0;
CustomBMPInfo->bmiHeader.biXPelsPerMeter = 0;
CustomBMPInfo->bmiHeader.biYPelsPerMeter = 0;
CustomBMPInfo->bmiHeader.biClrUsed = 16;
CustomBMPInfo->bmiHeader.biClrImportant = 0;
HDC hdc = GetDC(NULL);
hCustomBMP = CreateCompatibleBitmap(hdc,
CustomBMPInfo->bmiHeader.biWidth,
CustomBMPInfo->bmiHeader.biHeight);
GetObject(hCustomBMP, sizeof(CustomBMP), &CustomBMP);
SetDIBits(hdc, hCustomBMP, 0, CustomBMP.bmHeight, BitmapData, CustomBMPInfo, DIB_RGB_COLORS);
HDC hdcMem = CreateCompatibleDC(hdc);
HBITMAP hbmOld = (HBITMAP) SelectObject(hdcMem, hCustomBMP);
BitBlt(hdc, 0, 0, CustomBMP.bmWidth, CustomBMP.bmHeight, hdcMem, 0, 0, SRCCOPY);
SelectObject(hdcMem, hbmOld);
DeleteDC(hdcMem);
DeleteObject(hCustomBMP);
ReleaseDC(NULL, hdc);
getchar();
return 0;
}
-
I've never seen anyone use that technique for allocation. Although, it does make sense. Thanks a lot. I wish MSDN would be a little clearer on how to use that structure.