Win32 位图信息 如何可靠地为 RGBQUAD 数组/颜色表分配足够的内存(bmiColors 字段)?



我有一个HBITMAP,我想从该HBITMAP获取完整的BITMAPINFO结构,并带有相应的RGBQUAD数组,而不仅仅是BITMAPINFOHEADER

这是BITMAPINFO的结构:

typedef struct tagBITMAPINFO {
BITMAPINFOHEADER bmiHeader;
RGBQUAD          bmiColors[1];
} BITMAPINFO, *LPBITMAPINFO, *PBITMAPINFO;

我可以将GetDIBits与指针一起使用NULL以引用位缓冲区,以便BITMAPINFOHEADER获取到我分配的BITMAPINFO内存中。

我不知道的是,如何BITMAPINFOHEADER数据可靠地计算RGBQUAD数组的大小,以便我可以分配足够的空间来允许GetDIBits存储整个数组。文档(以及我发现的许多代码示例(非常令人困惑,甚至在这个主题的某些部分存在冲突。

在重新阅读文档、wiki、一些博客文章和其他来源(这些来源都没有内部一致(后,这似乎是确定颜色表(RGBQUAD 数组(中元素数量的最佳方法:

GetDIBits与像素缓冲区的NULL值一起使用以获取BITMAPINFO

BITMAPINFO* pbinfo = ( BITMAPINFO* ) malloc( sizeof( BITMAPINFOHEADER ) );
...
pbinfo->bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
GetDIBits( hScreenMemory, hBitmap, 0, 0, NULL, pbinfo, DIB_RGB_COLORS );

然后基于:

  1. pbinfo->bmiHeader.biBitCount
  2. pbinfo->bmiHeader.biClrUsed
  3. pbinfo->bmiHeader.biCompression

我们可以使用以下逻辑确定RGBQUAD数组元素的数量:

DWORD ColorTableLength( BITMAPINFOHEADER* h ) {
DWORD result        = 0;
DWORD biClrUsed     = h->biClrUsed;
WORD  biBitCount    = h->biBitCount;
DWORD biCompression = h->biCompression;
switch ( biBitCount ) {
case 24:
result = biClrUsed;
break;
case 16:
case 32:
if ( biCompression == BI_RGB )
result = biClrUsed;
else if ( biCompression == BI_BITFIELDS )
result = 3;
break;
default: // for 0, 1, 2, 4, and 8
if ( biClrUsed == 0 )
result = ( 1 << biBitCount ); // 2^biBitCount
else
result = biClrUsed;
break;
}
return result;
}

这是我在网上找到的许多资源和示例之间的"最低公分母"(并且仍有可能不适用于每种情况(。

需要为RGBQUAD数组分配的字节数可以通过sizeof(RGBQUAD) * ColorTableLength( &... )计算。

在某些情况下RGBQUAD数组被替换为 3DWORD秒,但DWORDRGBQUAD的大小是相同的,因此我们将哪个sizeof乘以ColorTableLength值并不重要。

我不确定为什么标准没有定义一个字段,明确说明为颜色表/RGBQUAD数组/RGBDWORD保留了多少字节,但看起来就是这样。

biClrUsed字段应该具有该目的,但并非在所有情况下。

最新更新