You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Bitblt更快读取屏幕像素颜色?

加速屏幕像素捕获的优化建议

1. 消除BitBlt格式转换:用与屏幕同格式的兼容位图

你的核心耗时原因是BitBlt需要在Windows 11默认的32位ARGB屏幕格式和你指定的24位DIB之间做格式转换。让兼容位图与屏幕DC使用完全一致的像素格式,就能跳过这个转换步骤:

  • 先获取屏幕DC的像素格式参数:
    int bitsPerPixel = GetDeviceCaps(hdc, BITSPIXEL);
    int planes = GetDeviceCaps(hdc, PLANES);
    
  • 调整BITMAPINFOHEADER匹配屏幕格式(以32位为例):
    BITMAPINFOHEADER bmi = { 0 };
    bmi.biSize = sizeof(BITMAPINFOHEADER);
    bmi.biPlanes = planes;
    bmi.biBitCount = bitsPerPixel;
    bmi.biWidth = ScreenX;
    bmi.biHeight = -ScreenY;
    bmi.biCompression = BI_RGB;
    // 32位格式需指定biSizeImage,避免GetDIBits报错
    bmi.biSizeImage = ((ScreenX * bitsPerPixel + 31) / 32) * 4 * ScreenY;
    
    这样创建的兼容位图与屏幕格式一致,BitBlt无需转换,速度会明显提升。

2. 用DIBSection替代普通兼容位图,跳过GetDIBits拷贝

普通兼容位图存在GDI设备内存中,GetDIBits需要把数据从显存拷贝到系统内存。改用DIBSection可以直接访问像素内存,省去这一步额外拷贝:

// 循环外初始化(仅执行一次)
HDC hdcScreen = GetDC(NULL);
BITMAPINFO bmi = { 0 };
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32; // 匹配屏幕格式
bmi.bmiHeader.biWidth = ScreenX;
bmi.bmiHeader.biHeight = -ScreenY;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biSizeImage = ((ScreenX * 32 + 31) / 32) * 4 * ScreenY;

BYTE* pScreenData = nullptr;
HBITMAP hDibSection = CreateDIBSection(hdcScreen, &bmi, DIB_RGB_COLORS, (void**)&pScreenData, NULL, 0);
HDC hdcMem = CreateCompatibleDC(hdcScreen);
SelectObject(hdcMem, hDibSection);

// 循环内仅执行捕获操作
BitBlt(hdcMem, 0, 0, ScreenX, ScreenY, hdcScreen, 0, 0, SRCCOPY);
// 直接通过pScreenData访问像素,无需调用GetDIBits

// 循环结束后销毁资源
DeleteObject(hDibSection);
DeleteDC(hdcMem);
ReleaseDC(NULL, hdcScreen);

3. 缓存GDI资源,避免重复创建销毁

你当前代码每次循环都创建/销毁hdcMem、hBitmap等资源,这会带来额外开销。把这些资源的初始化和销毁移到循环外部,循环内只执行BitBlt和数据读取即可。

4. 改用DXGI桌面复制API(Windows 10+)

GDI的BitBlt在现代系统中已不是最优选择,DXGI桌面复制API可以直接从GPU获取桌面帧,速度比GDI快数倍,完全避开格式转换瓶颈:

  • 用Direct3D 11创建设备和交换链
  • 通过IDXGIOutputDuplication接口捕获桌面帧
  • 直接读取GPU内存中的像素数据(无需大量CPU-GPU拷贝)
    这种方式适合需要高频屏幕捕获的场景。

5. 缩小捕获区域

如果业务不需要全屏幕像素,只捕获目标区域(比如特定窗口或矩形),减少BitBlt处理的数据量,能直接降低耗时:

// 仅捕获(x,y)开始的w*h区域
BitBlt(hdcMem, 0, 0, CaptureWidth, CaptureHeight, hdcScreen, CaptureX, CaptureY, SRCCOPY);

内容的提问来源于stack exchange,提问作者A J

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 06:40:26