首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >访问CBitmap对象中的单个像素

访问CBitmap对象中的单个像素
EN

Stack Overflow用户
提问于 2017-05-03 13:13:02
回答 2查看 1.9K关注 0票数 3

作为练习,我尝试编写一段代码,它可以在特定的x/y位置从MFC CBitmap对象中采样单个像素。

这个类没有任何GetPixel类型接口,我看到的大多数信息都表明通过CBitmap::GetBitMapBits复制了CBitmap位的全部内容,这似乎效率极低。

是否无法通过指针访问字节数组并将其作为数组访问?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-05-04 21:42:41

如果CBitmap对象与设备无关位图 (DIB,由CreateDIBSection()创建)相关联,则可以通过调用GetObject()获得直接访问位图像素的指针。在使用直接访问之前,如果您已经访问了位图像素任何其他GDI函数,请确保调用任何其他GDI函数

如果CBitmap设备相关位图 (DDB,也称为兼容位图)相关联,那么使用哪种方法取决于要访问多少像素。

  • 如果只需要访问少量的像素,您可以选择CDC::SelectObject()CDC::GetPixel()路由。如果你想读取更多像素,这将是非常慢的。
  • 要访问大数量的像素,可以使用CBitmap::GetBitMapBits()GetDIBits()。当您只需要访问位图像素的一部分时,后者可能更有效,因为它具有定义要复制的扫描线范围的参数。

在任何一种情况下,当您需要逐像素访问DDB时,它总是比DIB慢。

下面的示例检测CBitmap是否与DIB或DDB相关联,并对每种情况使用最有效的访问方法。

代码语言:javascript
复制
void DoAwesomeStuff( CBitmap& bitmap )
{
    DIBSECTION dib{ 0 };
    if( ::GetObject( bitmap, sizeof( dib ), &dib ) )
    {
        // GetObject() succeeded so we know that bmp is associated with a DIB.

        // Evaluate the information in dib thoroughly, to determine if you can handle
        // the bitmap format. You will propably restrict yourself to a few uncompressed 
        // formats.
        // In the following example I accept only uncompressed top-down bitmaps 
        // with 32bpp.
        if( dib.dsBmih.biCompression == BI_RGB && 
            dib.dsBmih.biHeight < 0 &&  // negative height indicates top-down bitmap
            dib.dsBmih.biPlanes == 1 && 
            dib.dsBmih.biBitCount == 32 )
        {
            DWORD* pPixels = reinterpret_cast<DWORD*>( dib.dsBm.bmBits );
            // TODO: Access the bitmap directly through the pPixels pointer. 
            // Make sure to check bounds to avoid segfault.
        }
    }
    else
    {
        // GetObject() failed because bmp is not a DIB or for some other reason.
        BITMAP bmp{ 0 };
        if( ::GetObject( bitmap, sizeof( bmp ), &bmp ) )
        {
            // GetObject() succeeded so we know that bmp is associated with a DDB.
            CDC dc;
            // Create a memory DC.
            dc.CreateCompatibleDC( nullptr );
            if( CBitmap* pOldBmp = dc.SelectObject( &bitmap ) )
            {
                // Get the bitmap pixel at given coordinates.
                // For accessing a large number of pixels, CBitmap::GetBitMapBits() 
                // or GetDIBits() will be more efficient.
                COLORREF pixel = dc.GetPixel( 42, 24 );

                // Standard cleanup: restore the bitmap that was originally 
                // selected into the DC.
                dc.SelectObject( pOldBmp );
            }
            else
            {
                // TODO: handle error               
            }
        }
        else
        {
            // TODO: handle error
        }
    }
}
票数 2
EN

Stack Overflow用户

发布于 2017-05-03 13:40:36

首先需要将CBitmap选择为CDC (CDC:SelectObject)。设备上下文有一个CDC:GetPixel成员。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43761146

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档