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

时间:2017-08-29 00:11:17

标签: c++ winapi gdi

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

基本上,数组转换为HBITMAP,然后通过复制到剪贴板进行验证。但是,当BITMAP成员通过bmBits构造访问位值时,它会返回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);

1 个答案:

答案 0 :(得分:7)

答案在GetObject() documentation

  

如果hgdiobj是通过调用CreateDIBSection创建的位图的句柄,并且指定的缓冲区足够大,则GetObject函数返回DIBSECTION结构。此外,bmBits中包含的BITMAP结构的DIBSECTION成员将包含指向位图的位值的指针。

     

如果 hgdiobj 是通过任何其他方式创建的位图的句柄,GetObject仅返回位图的宽度,高度和颜色格式信息。您可以通过调用GetDIBits()GetBitmapBits()函数来获取位图的位值。

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

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