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

如何将一组Direct2D位图保存为动态图像?解决帧覆盖问题

问题根源

你直接复用了同一个IWICBitmapFrameEncode对象写入所有帧,WIC的帧编码器实例是绑定单帧的,重复调用WriteSource只会覆盖当前实例对应的帧,而非添加新帧。

正确实现步骤

针对多帧图像格式(如GIF),需要为每帧创建独立的IWICBitmapFrameEncode实例,流程如下:

    1. 创建并初始化IWICImagingFactory和IWICBitmapEncoder(指定支持多帧的格式,比如GUID_ContainerFormatGif)
    1. 为每一张Direct2D位图执行以下操作:
    • 调用IWICBitmapEncoder::CreateNewFrame获取新的IWICBitmapFrameEncode实例
    • 设置当前帧的属性(如GIF的延迟时间、帧处理方式等,可选但建议设置,否则可能播放异常)
    • 将Direct2D位图转换为WIC位图(可通过ID2D1DeviceContext::CreateBitmapRenderTarget绘制,或直接锁定内存拷贝)
    • 调用IWICBitmapFrameEncode::WriteSource写入当前帧的WIC位图数据
    • 调用IWICBitmapFrameEncode::Commit提交当前帧
    1. 所有帧处理完成后,调用IWICBitmapEncoder::Commit完成整个编码过程
代码示例(C++)
// 假设已初始化pImagingFactory、pEncoder(绑定到输出流),并有Direct2D位图数组pD2DBitmaps
for (auto& pD2DBitmap : pD2DBitmaps)
{
    CComPtr<IWICBitmapFrameEncode> pFrameEncode;
    HRESULT hr = pEncoder->CreateNewFrame(&pFrameEncode, nullptr);
    if (FAILED(hr)) break;

    // 设置GIF帧属性:延迟100ms,播放后恢复背景色
    PROPVARIANT propVar;
    PropVariantInit(&propVar);
    propVar.vt = VT_UI2;
    propVar.uiVal = 10; // GIF延迟单位为1/100秒,此处对应100ms
    pFrameEncode->SetMetadataQueryValue(L"/grctlext/Delay", &propVar);
    PropVariantClear(&propVar);

    propVar.vt = VT_UI1;
    propVar.bVal = 2; // 帧处理方式:恢复到背景色
    pFrameEncode->SetMetadataQueryValue(L"/grctlext/Disposal", &propVar);
    PropVariantClear(&propVar);

    // 初始化帧编码器
    hr = pFrameEncode->Initialize(nullptr);
    if (FAILED(hr)) break;

    // 将Direct2D位图转换为WIC位图
    CComPtr<IWICBitmap> pWICBitmap;
    hr = pImagingFactory->CreateBitmap(
        static_cast<UINT>(pD2DBitmap->GetSize().width),
        static_cast<UINT>(pD2DBitmap->GetSize().height),
        GUID_WICPixelFormat32bppBGRA,
        WICBitmapCacheOnLoad,
        &pWICBitmap
    );
    if (FAILED(hr)) break;

    CComPtr<ID2D1RenderTarget> pRenderTarget;
    hr = pD2DDeviceContext->CreateBitmapRenderTarget(
        pWICBitmap,
        D2D1::RenderTargetProperties(),
        &pRenderTarget
    );
    if (FAILED(hr)) break;

    pRenderTarget->BeginDraw();
    pRenderTarget->DrawBitmap(pD2DBitmap);
    hr = pRenderTarget->EndDraw();
    if (FAILED(hr)) break;

    // 写入帧数据
    hr = pFrameEncode->WriteSource(pWICBitmap, nullptr);
    if (FAILED(hr)) break;

    // 提交当前帧
    hr = pFrameEncode->Commit();
    if (FAILED(hr)) break;
}

// 提交整个编码器,完成多帧图像写入
pEncoder->Commit();
额外注意事项
  • 确保编码器格式支持多帧(如GIF、TIFF),JPEG等单帧格式无法保存多帧图像
  • Direct2D转WIC位图的方式可按需优化,直接锁定内存拷贝比RenderTarget绘制更高效
  • 对于GIF,可通过IWICBitmapEncoder::SetMetadataQueryValue设置全局循环次数,路径为/appext/ApplicationExtensions/LoopCount

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 09:18:26