将位数组转换为 HBITMAP 后 bmBits 的 NULL 指针
Posted
技术标签:
【中文标题】将位数组转换为 HBITMAP 后 bmBits 的 NULL 指针【英文标题】:NULL pointer for bmBits after converting a bit array to HBITMAP 【发布时间】:2017-08-29 00:11:17 【问题描述】:我正在尝试按照以下帖子中的说明将像素数组转换为 HBITMAP
:How to convert an Array of pixels to HBITMAP。
基本上,数组被转换为HBITMAP
,然后通过复制到剪贴板进行验证。但是,当通过其bmBits
成员访问BITMAP
构造中的位值时,它返回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);
【问题讨论】:
调用 GetLastError 来查看调用失败的原因——至少你会得到一个线索 @pm100:大多数 GDI 函数不使用GetLastError()
进行错误报告,本示例中使用的 GDI 函数肯定是这种情况(只有剪贴板函数使用)。
@RemyLebeau 够公平的。因此,除了“那行不通”之外,别无他法。但是,如果某些底层事情失败(文件错误),那么 GetLastError 将返回一些东西(尽管它可能是一个红鲱鱼)
尽管有它的名字,CreateDIBitmap()
实际上创建了一个 DDB 而不是 DIB。该引用告诉它曾经有一个标志 CBM_CREATDIB
不再受支持。
【参考方案1】:
答案在GetObject()
documentation:
如果
hgdiobj
是通过调用CreateDIBSection
创建的位图的句柄,并且指定的缓冲区足够大,则GetObject
函数返回DIBSECTION
结构。此外,DIBSECTION
中包含的BITMAP
结构的bmBits
成员将包含指向位图位值的指针。如果 hgdiobj 是通过任何其他方式创建的位图的句柄,
GetObject
仅返回位图的宽度、高度和颜色格式信息。可以通过调用GetDIBits()
或GetBitmapBits()
函数获取位图的位值。
这意味着 bmBits
仅在查询 DIB 位图以获取 DIBSECTION
结构时填充,其中包含 BITMAP
等。
您正在为 BITMAP
结构查询 DDB 位图,因此不会填充 bmBits
,您必须单独检索像素位。
【讨论】:
以上是关于将位数组转换为 HBITMAP 后 bmBits 的 NULL 指针的主要内容,如果未能解决你的问题,请参考以下文章
如何通过 Bitmap::GetHBITMAP 将位图转换为带有 alpha 的 HBITMAP?