我有一个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 );
然后基于:
pbinfo->bmiHeader.biBitCount
pbinfo->bmiHeader.biClrUsed
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
秒,但DWORD
和RGBQUAD
的大小是相同的,因此我们将哪个sizeof
乘以ColorTableLength
值并不重要。
我不确定为什么标准没有定义一个字段,明确说明为颜色表/RGBQUAD
数组/RGBDWORD
保留了多少字节,但看起来就是这样。
biClrUsed
字段应该具有该目的,但并非在所有情况下。