将位数组转换为 HBITMAP 后 bmBits 的 NULL 指针

NULL pointer for bmBits after converting a bit array to HBITMAP

我正在尝试按照 post 中的说明将像素数组转换为 HBITMAPHow to convert an Array of pixels to HBITMAP

基本上,数组被转换为HBITMAP,然后通过复制到剪贴板进行验证。但是,当通过其 bmBits 成员从 BITMAP 构造访问位值时,它 returns NULL.

我这里可能遗漏了什么。如果一个 HBITMAP 创建成功,为什么我们仍然得到一个 NULL 指向它的位值的指针?

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);

答案在GetObject() documentation:

If hgdiobj is a handle to a bitmap created by calling CreateDIBSection, and the specified buffer is large enough, the GetObject function returns a DIBSECTION structure. In addition, the bmBits member of the BITMAP structure contained within the DIBSECTION 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 the GetDIBits() or GetBitmapBits() function.

这意味着只有在为 DIBSECTION 结构查询 DIB 位图时才会填充 bmBits,其中包含 BITMAP 等。

您正在为 BITMAP 结构查询 DDB 位图,因此 bmBits 不会被填充,您必须单独检索像素位。