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

如何从ID2D1Bitmap中获取像素数据?含ID2D1BitmapRenderTarget场景

从ID2D1Bitmap中提取像素数据的解决方案

要从ID2D1Bitmap中获取像素数据,核心问题是默认的ID2D1Bitmap通常驻留在GPU内存,无法直接被CPU访问。以下是两种可靠的实现方案:

方案1:创建可CPU读取的D2D位图并复制数据

通过创建带有D2D1_BITMAP_OPTIONS_CPU_READ标志的ID2D1Bitmap,将原位图内容复制到该可访问的位图后,再通过Map方法获取像素指针:

// 前提:已获取原ID2D1Bitmap对象pOriginalBitmap,以及对应的ID2D1RenderTarget* pRenderTarget
D2D1_SIZE_U bitmapSize = pOriginalBitmap->GetSize();
D2D1_PIXEL_FORMAT pixelFormat = pOriginalBitmap->GetPixelFormat();

// 创建支持CPU读取的位图
ID2D1Bitmap* pReadableBitmap = nullptr;
HRESULT hr = pRenderTarget->CreateBitmap(
    bitmapSize,
    nullptr,
    0,
    D2D1_BITMAP_PROPERTIES{
        pixelFormat,
        pRenderTarget->GetDpiX(),
        pRenderTarget->GetDpiY()
    },
    D2D1_BITMAP_OPTIONS_CPU_READ,
    &pReadableBitmap
);

if (SUCCEEDED(hr)) {
    // 将原位图绘制到可读取位图
    pRenderTarget->SetTarget(pReadableBitmap);
    pRenderTarget->BeginDraw();
    pRenderTarget->Clear(D2D1::ColorF(D2D1::ColorF::Transparent));
    pRenderTarget->DrawBitmap(pOriginalBitmap);
    hr = pRenderTarget->EndDraw();

    if (SUCCEEDED(hr)) {
        // 映射位图获取像素数据
        D2D1_MAPPED_RECT mappedRect;
        hr = pReadableBitmap->Map(D2D1_MAP_OPTIONS_READ, &mappedRect);
        if (SUCCEEDED(hr)) {
            BYTE* pPixelData = static_cast<BYTE*>(mappedRect.pBits);
            UINT32 rowPitch = mappedRect.pitch;

            // 示例:遍历PBGRA格式的像素
            for (UINT y = 0; y < bitmapSize.height; ++y) {
                UINT32* pRow = reinterpret_cast<UINT32*>(pPixelData + y * rowPitch);
                for (UINT x = 0; x < bitmapSize.width; ++x) {
                    UINT32 pixel = pRow[x];
                    // 拆分通道:PBGRA -> RGBA
                    BYTE b = pixel & 0xFF;
                    BYTE g = (pixel >> 8) & 0xFF;
                    BYTE r = (pixel >> 16) & 0xFF;
                    BYTE a = (pixel >> 24) & 0xFF;
                    // 处理单个像素逻辑
                }
            }

            pReadableBitmap->Unmap();
        }
    }

    pReadableBitmap->Release();
}

方案2:通过WIC位图转换获取像素

利用Windows Imaging Component(WIC)将D2D位图转换为WIC位图,再通过WIC的Lock接口读取像素:

// 前提:已获取pOriginalBitmap、ID2D1Factory* pD2DFactory、IWICImagingFactory* pWicFactory
D2D1_SIZE_U bitmapSize = pOriginalBitmap->GetSize();

// 创建WIC位图(匹配D2D常用的PBGRA格式)
IWICBitmap* pWicBitmap = nullptr;
HRESULT hr = pWicFactory->CreateBitmap(
    bitmapSize.width,
    bitmapSize.height,
    GUID_WICPixelFormat32bppPBGRA,
    WICBitmapCacheOnLoad,
    &pWicBitmap
);

if (SUCCEEDED(hr)) {
    // 创建关联WIC位图的D2D渲染目标
    ID2D1RenderTarget* pWicRenderTarget = nullptr;
    hr = pD2DFactory->CreateWicBitmapRenderTarget(
        pWicBitmap,
        D2D1::RenderTargetProperties(),
        &pWicRenderTarget
    );

    if (SUCCEEDED(hr)) {
        // 绘制原位图到WIC渲染目标
        pWicRenderTarget->BeginDraw();
        pWicRenderTarget->Clear(D2D1::ColorF(D2D1::ColorF::Transparent));
        pWicRenderTarget->DrawBitmap(pOriginalBitmap);
        hr = pWicRenderTarget->EndDraw();

        if (SUCCEEDED(hr)) {
            // 锁定WIC位图读取数据
            WICRect lockRect = {0, 0, static_cast<int>(bitmapSize.width), static_cast<int>(bitmapSize.height)};
            IWICBitmapLock* pBitmapLock = nullptr;
            hr = pWicBitmap->Lock(&lockRect, WICBitmapLockRead, &pBitmapLock);

            if (SUCCEEDED(hr)) {
                UINT bufferSize = 0;
                BYTE* pPixelData = nullptr;
                hr = pBitmapLock->GetDataPointer(&bufferSize, &pPixelData);
                if (SUCCEEDED(hr)) {
                    UINT rowPitch = 0;
                    pBitmapLock->GetStride(&rowPitch);
                    // 像素处理逻辑同方案1
                }

                pBitmapLock->Release();
            }
        }

        pWicRenderTarget->Release();
    }

    pWicBitmap->Release();
}

关键注意事项

  • 像素格式:D2D默认使用DXGI_FORMAT_B8G8R8A8_UNORM(PBGRA)格式,处理时要注意通道顺序,避免颜色错乱
  • 内存管理:所有COM对象使用完毕后必须调用Release()释放,防止内存泄漏
  • 性能优化:GPU到CPU的数据传输存在开销,尽量减少像素读取的频率;如果需要多次读取,可复用可CPU读取的位图对象

内容的提问来源于stack exchange,提问作者Generic Name

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 14:57:11