GetDiBits:BITMAPINFOHEADER 中传递的不同维度
GetDiBits: different dimensions passed in BITMAPINFOHEADER
根据我使用此功能的经验,我对 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 或者它是否照看结构中的值: radius^2 *3 -忽略填充-?
基本上你有这样的代码:
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
需要几微秒,创建更大的位图不会节省太多。
GetDIBits 是 GDI 标准的一个相当奇怪的函数。它不是只采用 HDC
或 HBITMAP
的通常模式,而是两者都需要,并且对 HBITMAP
参数施加了额外的限制。 iirc 当您要求 GDI(可能)相对于颜色 table 转换位图时使用此模式 - 即在 8 位或更低版本的图像中,您应该在 HDC
中选择 HPALETTE
.
然而 MSDN 上的 GetDIBits function 页面非常清楚 - LPBITMAPINFO
参数是:
A pointer to a BITMAPINFO structure that specifies the desired format
for the DIB data.
后续评论阐明,如果 lpvBits
为 NULL,您可以使用 GetDIBits 通过将位图属性写入 BITMAPINFO
结构来检索它们。
回答您的具体问题; GetDIBits
使用您在 BITMAPINFOHEADER
中提供的维度和格式输出到 dataBuffer,如果 DDB
具有不同的维度或像素格式,将根据需要进行剪辑和转换。
根据我使用此功能的经验,我对 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 或者它是否照看结构中的值: radius^2 *3 -忽略填充-?
基本上你有这样的代码:
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
需要几微秒,创建更大的位图不会节省太多。
GetDIBits 是 GDI 标准的一个相当奇怪的函数。它不是只采用 HDC
或 HBITMAP
的通常模式,而是两者都需要,并且对 HBITMAP
参数施加了额外的限制。 iirc 当您要求 GDI(可能)相对于颜色 table 转换位图时使用此模式 - 即在 8 位或更低版本的图像中,您应该在 HDC
中选择 HPALETTE
.
然而 MSDN 上的 GetDIBits function 页面非常清楚 - LPBITMAPINFO
参数是:
A pointer to a BITMAPINFO structure that specifies the desired format for the DIB data.
后续评论阐明,如果 lpvBits
为 NULL,您可以使用 GetDIBits 通过将位图属性写入 BITMAPINFO
结构来检索它们。
回答您的具体问题; GetDIBits
使用您在 BITMAPINFOHEADER
中提供的维度和格式输出到 dataBuffer,如果 DDB
具有不同的维度或像素格式,将根据需要进行剪辑和转换。