I'm trying to convert a pixel array to a HBITMAP
as instructed in this post: How to convert an Array of pixels to HBITMAP.
Basically, the array is converted to a HBITMAP
and then verified by copied to the clipboard. However, when accessing the bit value from the BITMAP
construct by its bmBits
member, it returns NULL
.
I might have something missing here. If a HBITMAP
is created successfully, why we still get a NULL
pointer to its bit values?
uint8 width = 160;
uint8 height = 120;
uint8* pixels = new uint8[160 * 120 * 4];
for (int i = 0; i < 160 * 120 * 4; i++){
pixels[i] = (i % 4 == 1) * 255; // testing pixels
}
BITMAPINFOHEADER bmih;
bmih.biSize = sizeof(BITMAPINFOHEADER);
bmih.biWidth = width;
bmih.biHeight = -1 * height;
bmih.biPlanes = 1;
bmih.biBitCount = 32;
bmih.biCompression = BI_RGB;
bmih.biSizeImage = 0;
bmih.biXPelsPerMeter = 10;
bmih.biYPelsPerMeter = 10;
bmih.biClrUsed = 0;
bmih.biClrImportant = 0;
BITMAPINFO dbmi;
ZeroMemory(&dbmi, sizeof(dbmi));
dbmi.bmiHeader = bmih;
dbmi.bmiColors->rgbBlue = 0;
dbmi.bmiColors->rgbGreen = 0;
dbmi.bmiColors->rgbRed = 0;
dbmi.bmiColors->rgbReserved = 0;
HDC hdc = ::GetDC(NULL);
HBITMAP hbmp = CreateDIBitmap(hdc, &bmih, CBM_INIT, pixels, &dbmi, DIB_RGB_COLORS);
if (hbmp == NULL) {
::MessageBox(NULL, L"Could not load the desired image", L"Error", MB_OK);
return NULL;
}
::ReleaseDC(NULL, hdc);
// a little test if everything is OK
OpenClipboard(NULL);
EmptyClipboard();
SetClipboardData(CF_BITMAP, hbmp); // I can verify the image by pasting
CloseClipboard();
// verify the bitmap
BITMAP bitmap;
::GetObject(hbmp, sizeof(BITMAP), &bitmap);
uint8* lpbits = (uint8*)bitmap.bmBits;
assert(lpbits != NULL); // Why this assertion failed??
// cleanup
// DeleteObject(hbmp);
The answer is in the GetObject()
documentation:
If
hgdiobj
is a handle to a bitmap created by callingCreateDIBSection
, and the specified buffer is large enough, theGetObject
function returns aDIBSECTION
structure. In addition, thebmBits
member of theBITMAP
structure contained within theDIBSECTION
will contain a pointer to the bitmap's bit values.If hgdiobj is a handle to a bitmap created by any other means,
GetObject
returns only the width, height, and color format information of the bitmap. You can obtain the bitmap's bit values by calling theGetDIBits()
orGetBitmapBits()
function.
This means that bmBits
is populated only when querying a DIB bitmap for a DIBSECTION
structure, which contains a BITMAP
amongst other things.
You are querying a DDB bitmap for a BITMAP
structure, so bmBits
does not get populated, and you have to retrieve the pixel bits separately.