如何从像素缓冲区创建 Win32 HBITMAP

Posted

技术标签:

【中文标题】如何从像素缓冲区创建 Win32 HBITMAP【英文标题】:How to create Win32 HBITMAP from pixelbuffer 【发布时间】:2019-02-15 07:10:22 【问题描述】:

我正在尝试从像素缓冲区创建一个 HBITMAP 并显示它。这是我创建 HBITMAP 的代码

char buffer[640 * 480 * 3];
memset(buffer, 255, 640 * 480 * 3);
BITMAPINFO bm =  sizeof(BITMAPINFOHEADER),
        640,
        480, 1, 24,
        BI_RGB, 640 * 480 * 3, 0, 0, 0, 0 ;
HBITMAP imageBmp = CreateDIBSection(hdc, &bm, DIB_RGB_COLORS, (void**)buffer, 0, 0);
if (imageBmp == NULL) 
    DWORD lastError = GetLastError();
    return;

这是显示它的代码:

 HDC imageDC = CreateCompatibleDC(NULL);     // create an offscreen DC
SelectObject(imageDC, imageBmp);  // put the loaded image into our DC
RECT rect;
GetClientRect(hDlg, &rect);
BitBlt(
    hdc,         // tell it we want to draw to the screen
    0, 0,            // as position 0,0 (upper-left corner)
    rect.right - rect.left,   // width of the rect to draw
    rect.bottom - rect.top,   // height of the rect
    imageDC,        // the DC to get the rect from (our image DC)
    0, 0,            // take it from position 0,0 in the image DC
    SRCCOPY         // tell it to do a pixel-by-pixel copy
);

我希望看到一个白色的图像,但我得到的是一个黑色的窗口屏幕。我很确定我的显示代码是正确的,但不知道为什么创建 HBITMAP 的代码是错误的。

【问题讨论】:

【参考方案1】:

CreateDIBSection 已经通过ppvBits 参数向您返回分配的缓冲区,因此它会覆盖您的buffer 变量。来自文档(强调我的):

ppvBits 指向变量的指针,接收指向 DIB 位值的位置。

您的代码所需的修复:

删除代码以创建数组。 传递ppvBits 参数的指针地址。 仅在成功调用CreateDIBSection之后设置像素。
char* buffer = NULL;
BITMAPINFO bm =  sizeof(BITMAPINFOHEADER),
        640,
        480, 1, 24,
        BI_RGB, 640 * 480 * 3, 0, 0, 0, 0 ;
HBITMAP imageBmp = CreateDIBSection(hdc, &bm, DIB_RGB_COLORS, (void**) &buffer, 0, 0);
if (imageBmp == NULL) 
    DWORD lastError = GetLastError();
    return;

memset(buffer, 255, 640 * 480 * 3);

注意:

确保在生产代码中,通过将位图宽度与下一个 DWORD 边界对齐来正确计算大小,如文章“DIBs and Their Use”中所述:

计算位图的大小并不难:

biSizeImage = ((((biWidth * biBitCount) + 31) & ~31) >> 3) * biHeight

位图的疯狂四舍五入和移位 在每条扫描线的末尾以 DWORD 对齐。

在您的示例中,640 * 480 * 3 给出正确的结果只是因为640 的宽度已经可以被 4 整除。对于641 的宽度,您的公式将失败,而文章中引用的公式将给出结果正确。

【讨论】:

扫描线双字对齐? @Anders 好建议,有时间我会补充的。 嗨@zett42,感谢您的帖子。但是,它似乎不起作用。 CreateDIBSection之后,buffer还是0

以上是关于如何从像素缓冲区创建 Win32 HBITMAP的主要内容,如果未能解决你的问题,请参考以下文章

从 Win32 项目中的 *.bmp 文件加载 HBITMAP

从内存创建 Windows GDI 位图

win32-UpdateLayeredWindow

用C++在Win32中用LoadImage()绘制HBITMAP的二维数组

如何从 Windows LPBITMAP 或 HBITMAP 获取实际的字节数组?

Win32 CreatePatternBrush