3

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

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

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

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(hSectionDC, hBmpSection, 0, bmpSmallInfo.bmiHeader.biHeight, dataBuffer3, &bmpSmallInfo, DIB_RGB_COLORS);

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

这是正常的吗?因为我不想通过网络发送不需要的字节,所以我不得不问:GetDiBits 是否输出正确尺寸大小的数组: (4*radius^2)*3 或者它是否关注结构中的值:半径^2 *3 -忽略填充-?

4

2 回答 2

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需要几微秒,创建更大的位图不会节省太多。

于 2018-04-14T16:40:22.920 回答
1

根据 GDI 标准, GetDIBits是一个相当奇怪的函数。与通常只取一个HDC或一个它想要两者不同的模式不同,AND 对参数HBITMAP施加了额外的限制。HBITMAPiirc 当您要求 GDI(可能)相对于颜色表转换位图时使用此模式 - 即在 8 位或更低的图像中,您应该HPALETTEHDC.

然而,MSDN 上的GetDIBits 功能页面非常清楚 -LPBITMAPINFO参数是:

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

随后的注释阐明,如果lpvBits为 NULL,您可以使用 GetDIBits 通过将位图属性写入BITMAPINFO结构来检索它们。

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

于 2018-04-15T15:14:14.580 回答