GetDiBits:BITMAPINFOHEADER传递的不同尺寸

时间:2018-04-14 12:58:09

标签: c++ winapi dib getdibits

根据我对此功能的使用经验,我对GetDiBits有一些疑问。 我错误地创建了一个比我需要的大两倍的位图:

let h3 = document.createElement('h3');
h3.id = array[i].name;
...
else {
    h3 = document.getElementById(array[i].name);
    ... // modify the h3 created earlier
}

我没有注意到,因为代码的下一部分有效。 我BitBlt屏幕的一部分在这个位图的一半:

HBITMAP hBmpSection = CreateCompatibleBitmap(ScreenDC, 2 * radius, 2 * radius);

然后我得到了相应的数组:

bmpSmallInfo.bmiHeader.biHeight = (2*radius / 2);
bmpSmallInfo.bmiHeader.biWidth = (2*radius / 2);
BitBlt(hSectionDC, 0, 0, bmpSmallInfo.bmiHeader.biWidth, bmpSmallInfo.bmiHeader.biHeight, ScreenDC, 0, 0, SRCCOPY);

当我将所有这些数据发送到另一台计算机时,图像完全正确(没有黑色边缘,就像发送超大位图的情况一样)。这意味着GetDiBits忽略了位图的正确大小,并使用BITMAPINFOHEADER中提供的大小,而不会崩溃。 (我正在使用Win10。)

这是正常的吗?由于我不想通过网络发送不需要的字节,我不得不问:GetDiBits是否输出了一个正确尺寸大小的数组:(4 * radius ^ 2)* 3或者它是否接受结构中的值: radius ^ 2 * 3 -ignoring padding - ?

2 个答案:

答案 0 :(得分:1)

基本上你有这样的代码:

hbitmap = CreateCompatibleBitmap(hdc, max_width, max_height);
oldbmp = (HBITMAP)SelectObject(memdc, hbitmap);
BitBlt(memdc, 0, 0, width, height, hdc, x, y, SRCCOPY);
SelectObject(memdc, oldbmp);
int size = width_in_bytes_with_padding * height;
allocate size count memory ...
BITMAPINFOHEADER bi = { 40, width, height, 1, 24, BI_RGB };
GetDIBits(...);

您似乎在问的问题:如果width/height小于max_width/max_height,可以吗?

答案是肯定的。 GetDIBits期望dataBuffer3足够大以接收size个字节。 width/height应小于或等于max_width/max_height

请注意,BitBlt是此代码中最慢的函数,这是您需要优化的函数。 CreateCompatibleBitmap需要几微秒,你不会通过创建更大的位图来节省太多。

答案 1 :(得分:1)

GetDIBits 是GDI标准的一个相当奇怪的功能。而不是只采用HDCHBITMAP的通常模式,它需要两者,并且对HBITMAP参数施加了额外的限制。 iirc当您要求GDI(可能)相对于颜色表转换位图时使用此模式 - 即在8位或更低的图像中,您应该在HPALETTE中选择HDC

MSDN上的GetDIBits function页面非常清楚 - LPBITMAPINFO参数是:

  

指向BITMAPINFO结构的指针,指定所需的格式   对于DIB数据。

后续注释澄清,如果lpvBits为NULL,则可以使用GetDIBits通过将位图属性写入BITMAPINFO结构来检索位图属性。

回答您的具体问题; GetDIBits使用您在BITMAPINFOHEADER中提供的维度和格式输出到dataBuffer,并将剪辑&如果DDB具有不同的维度或像素格式,则根据需要进行转换。