2

目标是显示存储在内存缓冲区中的位图。内存缓冲区的内容与磁盘存储的 .bmp 文件相同。出于性能原因,将这些缓冲区写入磁盘然后显示它们不是一种选择。GDI+ 也不是一个选项。目前,我可以根据需要从内存缓冲区显示每像素 24 位的位图。但是,当我尝试显示每像素 8 位的位图时,图像以错误的颜色显示(即图像中的数字是可识别的;缩放、方向等都是正确的,但一切都是错误的颜色)。

这是我初始化位图标题结构的方法:

bfh = *(tagBITMAPFILEHEADER*)buf1;
bih = *(tagBITMAPINFOHEADER*)(buf1+sizeof(tagBITMAPFILEHEADER));
rgb = *(RGBQUAD*)(buf1+sizeof(tagBITMAPFILEHEADER)+sizeof(tagBITMAPINFOHEADER));
bi.bmiColors[0] = rgb;
bi.bmiHeader = bih;
pPixels = (buf1+bfh.bfOffBits);

然后,我尝试了几种不同的方法来创建 HBITMAP,这里有一些:

    g_hBmp = CreateDIBitmap(dcPaint, &bih, CBM_INIT, (VOID *) pPixels, &bi, DIB_RGB_COLORS);

或者:

g_hBmp = CreateDIBSection(dcPaint, &bi, DIB_RGB_COLORS, (void**) &ppvBits, NULL, 0);
SetDIBits(dcPaint, g_hBmp, 0, bih.biHeight, pPixels, &bi, DIB_RGB_COLORS);

我也尝试了不同的参数:

  • NULL 而不是 CPaintDC 对象
  • DIB_PAL_COLORS 而不是 DIB_RGB_COLORS

我已经转储了存储 .bmp 文件结构的内存缓冲区的内容,并验证了它们与使用 LoadBitmap() 加载时正确显示的磁盘存储的 .bmp 文件相同。

需要强调的是,上述方法适用于每像素 24 位的图像。但是,它不适用于每像素 8 位的图像。

提前致谢。

4

2 回答 2

1

问题在于,CreateDIBSection()每个DIB_RGB_COLORS像素(即 24 位)都需要 RGB 值,而您的 8 位位图包含的像素是 RGB 调色板的 8 位索引,存储在bi-bmiColors.

因此,您可以选择在预处理步骤中将 8 位位图转换为 24 位 - 例如,为 RGB 值分配内存并查找原始调色板以填充这些值。这样您就可以使用相同的代码来显示结果。或者,您可以使用原始数据创建 HBITMAP,然后将其选择到内存 DC,然后BitBlt()将其添加到显示窗口。

除了 GDI 或 GDI+ 之外,其他选项可能是考虑 WIC(Windows 映像组件)和/或 Direct2D。

于 2013-03-29T10:23:31.300 回答
0

汉斯说bi.bmiColors没有得到正确对待是正确的。而不是直接处理bi.bmiColors表格,只需指向pBitmapInfo适当的偏移量BITMAPFILEHEADER并进行转换。这会自动处理颜色表。是的,pBitmapInfo并且pBitmapInfoHeader确实指向同一个地方;在每种情况下,他们指向的内容都不同。这两个指针都是CreateDIBitmap()函数所需的。

pBitmapFileHeader = (LPBITMAPFILEHEADER)buf1;
pBitmapInfoHeader = (LPBITMAPINFOHEADER)(buf1+sizeof(BITMAPFILEHEADER));
pBitmapInfo = (LPBITMAPINFO)(buf1+sizeof(BITMAPFILEHEADER));
pPixels = (buf1+pBitmapFileHeader->bfOffBits);

然后在 OnPaint() 做:

g_hBmp = CreateDIBitmap(dcPaint, pBitmapInfoHeader, CBM_INIT, (VOID *) pPixels, pBitmapInfo, DIB_RGB_COLORS);
于 2013-04-20T00:46:11.723 回答