使用MFC或Win32从内存缓冲区显示所有位图类型

时间:2013-03-28 18:45:24

标签: c++ winapi graphics mfc bitmap

目标是显示存储在内存缓冲区中的位图。内存缓冲区的内容与磁盘存储的.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位图像。

提前致谢。

2 个答案:

答案 0 :(得分:1)

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

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

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

答案 1 :(得分:0)

汉斯说bi.bmiColors未被正确对待是正确的。不要直接处理bi.bmiColors表,只需将pBitmapInfo指向BITMAPFILEHEADER中的相应偏移量并进行投射即可。这会自动处理颜色表。是的,pBitmapInfopBitmapInfoHeader确实指向同一个地方;在每种情况下,他们指出的是不同的。这两个指针都是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);