StretchBlt和StretchDIBits

时间:2022-08-13 03:59:50

StretchBlt:从源矩形中复制一个位图到目标矩形,必要时按目标设备设置的模式进行图像的拉伸或压缩,如果目标设备是窗口DC,则意味着在窗口绘制位图,大致的使用代码如下:

 void DrawImage(HDC hdc, HBITMAP hbm, const RECT target_rect)
{
HDC hdcMemory = ::CreateCompatibleDC(hdc);
HBITMAP old_bmp = (HBITMAP)::SelectObject(hdcMemory, hbm); BITMAP bm = { };
::GetObject(hbm, sizeof(bm), &bm); ::StretchBlt(
hdc,           // Target device HDC
target_rect.left,        // X sink position
target_rect.top,         // Y sink position
target_rect.right - target_rect.left, // Destination width
target_rect.bottom - target_rect.top, // Destination height
hdcMemory, // Source device HDC
,            // X source position
,            // Y source position
bm.bmWidth,         // Source width
bm.bmHeight,         // Source height
SRCCOPY); // Simple copy ::SelectObject(hdcMemory, old_bmp);
::DeleteObject(hdcMemory);
}

StretchDIBits:该函数将DIB(设备无关位图)中矩形区域内像素使用的颜色数据拷贝到指定的目标矩形中,如果目标设备是窗口DC,同样意味着在窗口绘制位图,大致的使用代码如下:

 void DrawImage(HDC hdc, LPBITMAPINFOHEADER lpbi, void* bits, const RECT target_rect)
{
::StretchDIBits(
hdc, // Target device HDC
target_rect.left, // X sink position
target_rect.top, // Y sink position
target_rect.right - target_rect.left, // Destination width
target_rect.bottom - target_rect.top, // Destination height
, // X source position
, // Adjusted Y source position
lpbi->biWidth,      // Source width
abs(lpbi->biHeight),      // Source height
bits, // Image data
(LPBITMAPINFO)lpbi, // DIB header
DIB_RGB_COLORS, // Type of palette
SRCCOPY); // Simple image copy
}

简单的讲,StretchBlt操作的是设备相关位图是HBITMAP句柄,StretchDIBits操作的是设备无关位图是内存中的RGB数据。

DirectShow示例代码中的CDrawImage类提供了FastRender和SlowRender两个函数用于渲染视频图像,FastRender用的StretchBlt,SlowRender用的StretchDIBits,其中SlowRender的注释是这样写的:

 // This is called when there is a sample ready to be drawn, unfortunately the
// output pin was being rotten and didn't choose our super excellent shared
// memory DIB allocator so we have to do this slow render using boring old GDI
// SetDIBitsToDevice and StretchDIBits. The down side of using these GDI
// functions is that the image data has to be copied across from our address
// space into theirs before going to the screen (although in reality the cost
// is small because all they do is to map the buffer into their address space)

也就是说StretchDIBits比StretchBlt多消耗了从内存地址空间拷贝图像数据到GDI地址空间的时间。实际测试结果在XP和Win7系统下两者效率几乎没有区别,所以可以放心大胆的使用StretchDIBits,毕竟内存数据处理起来要方便的多。