StretchBlt:从源矩形中复制一个位图到目标矩形,必要时按目标设备设置的模式进行图像的拉伸或压缩,如果目标设备是窗口DC,则意味着在窗口绘制位图,大致的使用代码如下:
1 void DrawImage(HDC hdc, HBITMAP hbm, const RECT target_rect) 2 { 3 HDC hdcMemory = ::CreateCompatibleDC(hdc); 4 HBITMAP old_bmp = (HBITMAP)::SelectObject(hdcMemory, hbm); 5 6 BITMAP bm = { 0 }; 7 ::GetObject(hbm, sizeof(bm), &bm); 8 9 ::StretchBlt( 10 hdc, // Target device HDC 11 target_rect.left, // X sink position 12 target_rect.top, // Y sink position 13 target_rect.right - target_rect.left, // Destination width 14 target_rect.bottom - target_rect.top, // Destination height 15 hdcMemory, // Source device HDC 16 0, // X source position 17 0, // Y source position 18 bm.bmWidth, // Source width 19 bm.bmHeight, // Source height 20 SRCCOPY); // Simple copy 21 22 ::SelectObject(hdcMemory, old_bmp); 23 ::DeleteObject(hdcMemory); 24 }
StretchDIBits:该函数将DIB(设备无关位图)中矩形区域内像素使用的颜色数据拷贝到指定的目标矩形中,如果目标设备是窗口DC,同样意味着在窗口绘制位图,大致的使用代码如下:
1 void DrawImage(HDC hdc, LPBITMAPINFOHEADER lpbi, void* bits, const RECT target_rect) 2 { 3 ::StretchDIBits( 4 hdc, // Target device HDC 5 target_rect.left, // X sink position 6 target_rect.top, // Y sink position 7 target_rect.right - target_rect.left, // Destination width 8 target_rect.bottom - target_rect.top, // Destination height 9 0, // X source position 10 0, // Adjusted Y source position 11 lpbi->biWidth, // Source width 12 abs(lpbi->biHeight), // Source height 13 bits, // Image data 14 (LPBITMAPINFO)lpbi, // DIB header 15 DIB_RGB_COLORS, // Type of palette 16 SRCCOPY); // Simple image copy 18 }
简单的讲,StretchBlt操作的是设备相关位图是HBITMAP句柄,StretchDIBits操作的是设备无关位图是内存中的RGB数据。
DirectShow示例代码中的CDrawImage类提供了FastRender和SlowRender两个函数用于渲染视频图像,FastRender用的StretchBlt,SlowRender用的StretchDIBits,其中SlowRender的注释是这样写的:
1 // This is called when there is a sample ready to be drawn, unfortunately the 2 // output pin was being rotten and didn't choose our super excellent shared 3 // memory DIB allocator so we have to do this slow render using boring old GDI 4 // SetDIBitsToDevice and StretchDIBits. The down side of using these GDI 5 // functions is that the image data has to be copied across from our address 6 // space into theirs before going to the screen (although in reality the cost 7 // is small because all they do is to map the buffer into their address space)
也就是说StretchDIBits比StretchBlt多消耗了从内存地址空间拷贝图像数据到GDI地址空间的时间。实际测试结果在XP和Win7系统下两者效率几乎没有区别,所以可以放心大胆的使用StretchDIBits,毕竟内存数据处理起来要方便的多。