作为练习,我尝试编写一段代码,它可以在特定的x/y位置从MFC CBitmap对象中采样单个像素。
这个类没有任何GetPixel类型接口,我看到的大多数信息都表明通过CBitmap::GetBitMapBits复制了CBitmap位的全部内容,这似乎效率极低。
是否无法通过指针访问字节数组并将其作为数组访问?
发布于 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相关联,并对每种情况使用最有效的访问方法。
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
}
}
}发布于 2017-05-03 13:40:36
首先需要将CBitmap选择为CDC (CDC:SelectObject)。设备上下文有一个CDC:GetPixel成员。
https://stackoverflow.com/questions/43761146
复制相似问题