c++ 从位图中读取像素(原始字节)而不复制?

hjzp0vay  于 2023-03-05  发布在  其他
关注(0)|答案(1)|浏览(203)

我有一个设备相关位图的HBITMAP句柄,由以下代码生成:

// copy screen to bitmap
HDC     hScreen = GetDC(NULL);//don't use hwnd, it doesn't work for non native windows
HDC     hDC = CreateCompatibleDC(hScreen);
HBITMAP hBitmap = CreateCompatibleBitmap(hScreen, w, h);
HGDIOBJ old_obj = SelectObject(hDC, hBitmap);
BOOL    bRet = BitBlt(hDC, 0, 0, w, h, hScreen, x1, y1, SRCCOPY);

我想访问(只读)位图的位,读取一些值,执行一些计算,然后丢弃它。
根据this answer,我不应该使用GetDIBits()GetBitmapBits(),因为它们复制数据,而应该用途:

BITMAP bitmap;
GetObject(hBitmap, sizeof(bitmap), (LPVOID)&bitmap);

但是根据GetObject 's documentation
如果hgdiobj是通过调用CreateDIBSection创建的位图的句柄,并且指定的缓冲区足够大,则GetObject函数返回DIBSECTION结构。此外,DIBSECTION中包含的BITMAP结构的bmBits成员将包含指向位图位值的指针。
如果hgdiobj是通过任何其他方式创建的位图的句柄,则GetObject仅返回位图的宽度、高度和颜色格式信息。您可以通过调用GetDIBitsGetBitmapBits函数来获取位图的位值。
这是指在评论上述答案:
根据此https://msdn.microsoft.com/en-us/library/dd144904(v=vs.85).aspx,如果位图不是由CreateDIBSection创建的,则bitmap.bmBit指针将为空。
那么,有没有办法访问位图的位(RGB值),而不复制它们呢?
如果有帮助的话,位图所依赖的设备总是屏幕,所以我猜它总是24位或32位位图。
this article中,关于如何将HBITMAP保存到文件中,有以下章节:

// Allocate memory for the BITMAPINFO structure. (This structure  
// contains a BITMAPINFOHEADER structure and an array of RGBQUAD  
// data structures.)  

if (cClrBits < 24) pbmi = (PBITMAPINFO)LocalAlloc(LPTR, sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * (1 << cClrBits));

// There is no RGBQUAD array for these formats: 24-bit-per-pixel or 32-bit-per-pixel 

else pbmi = (PBITMAPINFO)LocalAlloc(LPTR, sizeof(BITMAPINFOHEADER));

所以,我真的不明白这里发生了什么,哪个是对的?

hc8w905p

hc8w905p1#

我不应该用GetDIBits() ...因为他们复制数据...
...
如果有帮助的话,位图所依赖的设备总是屏幕,所以我猜它总是24位或32位位图。
根据您使用的具体硬件,像素的存储方式可能会有所不同(可能是Rr Gg Bb在一台计算机上,Bb Gg Rr 00在另一台计算机上,RG Br gb在第三台计算机上)。
为了确保您知道数据格式,应该使用GetDIBits(),因为该函数不仅复制数据,而且还将数据转换为"已知"格式,该格式不依赖于硬件。
使用GetPixel()是否比复制它更有效?
如果你只想检查几个像素(eidogg.你想知道其中10个像素的颜色),它应该更有效率。
如果你对所有20000像素感兴趣,GetDIBits()应该更有效。
pbmi = (PBITMAPINFO)LocalAlloc ...
所以,我真的不明白这里发生了什么...
GetDIBits()支持各种位图格式,例如:

  • "24位":这意味着每像素3个字节(R、G、B)
  • "256色":每个像素一个字节,以及包含256种颜色中每种颜色的R、G、B定义的颜色Map表

在"24位"的情况下,BITMAPINFO结构只由一个BITMAPINFOHEADER结构组成,我自己在这种情况下经常这样写代码:

BITMAPINFOHEADER hdr;
...
GetDIBits(..., (BITMAPINFO *)&hdr, ...);

在"256色"的情况下,BITMAPINFO结构由一个BITMAPINFOHEADER结构和后面的256个"R,G,B"元组(颜色Map)组成-因此与"24位"的情况相比,该结构需要更多的内存。
请注意,首先存储图像的最后一行,如果该行的长度不是4字节的倍数,则在每行的末尾有填充字节。

相关问题