如何从PixelBuffer创建Win32 HBITMAP

时间:2019-02-15 07:10:23

标签: winapi bitmap

我尝试从像素缓冲区创建一个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 个答案:

答案 0 :(得分: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的宽度,您的公式将失败,而引用的公式从文章中得出正确的结果。