使用Windows GetDIBits函数获取位图像素值

3

我想使用GetDIBits函数获取位图的像素。由于我没有学习过Windows GDI / API,因此对于第一个参数HDC非常不确定。我在SO和网络上搜索了无数帖子,但是没有找到关于如何在这种特定情况下初始化HDC的信息或示例。这是我读取像素值的进展:

    HBITMAP hBitmap = (HBITMAP) LoadImage(0, L"C:/tmp/Foo.bmp" ,IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
    // check hBitmap for error

    BITMAP bm;
    ::GetObject( hBitmap , sizeof(bm) , &bm );

    // TODO: GetDIBits()


解决方案:

经过进一步搜索,我已经能够凑出以下内容:

    /* Omitting error checks for brevity */
    HDC dcBitmap = CreateCompatibleDC ( NULL );
    SelectObject( dcBitmap, hBitmap );

    BITMAPINFO bmpInfo;
    bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bmpInfo.bmiHeader.biWidth = bm.bmWidth;
    bmpInfo.bmiHeader.biHeight = -bm.bmHeight;
    bmpInfo.bmiHeader.biPlanes = 1;
    bmpInfo.bmiHeader.biBitCount = 24;
    bmpInfo.bmiHeader.biCompression = BI_RGB;        
    bmpInfo.bmiHeader.biSizeImage = 0;        

    COLORREF* pixel = new COLORREF [ bm.bmWidth * bm.bmHeight ];
    GetDIBits( dcBitmap , hBitmap , 0 , bm.bmHeight , pixel , &bmpInfo , DIB_RGB_COLORS );

这取决于您想要对位图做什么。然而,在上个世纪,调色板位图或视频适配器模式才是重点。如果您没有自己的窗口,GetDesktopWindow + GetWindowDC 将完美地工作。考虑使用 GDI+ 和 Bitmap::LockBits()。 - Hans Passant
@CodyGray 我不处理事件,也没有窗口。我正在编写一个控制台应用程序,我想要打开一个文件并读取像素值。我不知道该使用哪个 HDC,也不想猜测。 - Olumide
2
hdc 是您打算显示位图的目标。如果位图说“你知道吗?我不会给你 RGB 值,而是会给你我的目标设备颜色表中的索引,然后你可以从那里获取 RGB 值。”(http://msdn.microsoft.com/en-us/library/ms969897.aspx),这一点非常重要。`LoadImage` 也使用它来决定位图的颜色格式。如果您传递一个 24bpp 设备上下文,则会得到一个 24bpp 位图。 - Raymond Chen
1
@RaymondChen 我感到困惑。据我所知,LoadImage 不接受 HDC。 - Olumide
请注意,您正在以24bpp格式请求位,但是您正在传递COLORREF数组,这些是32位像素值。 - Raymond Chen
显示剩余4条评论
2个回答

1
源位图通常是与设备有关的位图。尽管这在现今不太常见,但这可能意味着位图的像素值被存储为颜色表中的索引。在这种情况下,GetDIBits需要访问设备上下文中存储的颜色表。
如果您的位图使用RGB值而不是索引,则设备上下文应该无关紧要,尽管根据我的经验,您仍然必须提供有效的上下文 (请参阅GetDIBits中的HDC是什么?), 或许它会查看设备上下文的其他方面,比如颜色深度。

1

你的目标是获取像素颜色值还是调用GetDIBits函数?如果你只想要像素内容,你可以使用GetObject来获取与你的HBITMAP句柄对应的BITMAP结构体,该结构体中的bmBits指针可以访问像素(注意:它将以位图的原始格式呈现,可能不是24bpp,因此请检查结构体的其他字段以查看格式)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接