2014-02-13 59 views
1

这个问题与this非常相似,但那个问题还没有得到解答。我的问题是,我有一个来自d2dfactory-> CreateDxgiSurfaceRenderTarget()的D2D DXGI RenderTarget,并且我想使用WIC将其内容保存为图像文件。我只是读thisthis,所以它在我看来,我不能只是在WIC渲染目标上创建一个ID2D1Bitmap,并使用ID2D1Bitmap :: CopyFromRenderTarget()从我想保存的输入渲染目标中复制,因为它们正在使用不同的资源。因此,这里是我想出了使用ID2D1RenderTarget :: CreateSharedBitmap():Direct2D:如何将ID2D1RenderTarget的内容保存到图像文件?

HRESULT SaveRenderTargetToFile(
    ID2D1RenderTarget* pRTSrc, 
    LPCWSTR uri 
    ) 
{ 
    HRESULT hr = S_OK; 

    ComPtr<IWICBitmap> spWICBitmap; 
    ComPtr<ID2D1RenderTarget> spRT; 
    ComPtr<IWICBitmapEncoder> spEncoder; 
    ComPtr<IWICBitmapFrameEncode> spFrameEncode; 
    ComPtr<IWICStream> spStream; 

    // 
    // Create WIC bitmap to save and associated render target 
    // 

    UINT bitmapWidth = static_cast<UINT>(pRTSrc->GetSize().width + .5f); 
    UINT bitmapHeight = static_cast<UINT>(pRTSrc->GetSize().height + .5f); 

    HR(m_spWICFactory->CreateBitmap(
     bitmapWidth, 
     bitmapHeight, 
     GUID_WICPixelFormat32bppPBGRA, 
     WICBitmapCacheOnLoad, 
     &spWICBitmap 
     )); 

    D2D1_RENDER_TARGET_PROPERTIES prop = D2D1::RenderTargetProperties(); 
    prop.pixelFormat = D2D1::PixelFormat(
     DXGI_FORMAT_B8G8R8A8_UNORM, 
     D2D1_ALPHA_MODE_PREMULTIPLIED 
     ); 
    prop.type = D2D1_RENDER_TARGET_TYPE_DEFAULT; 
    prop.usage = D2D1_RENDER_TARGET_USAGE_NONE; 
    HR(m_spD2D1Factory->CreateWicBitmapRenderTarget(
     spWICBitmap, 
     prop, 
     &spRT 
     )); 

    // 
    // Create a shared bitmap from this RenderTarget 
    // 
    ComPtr<ID2D1Bitmap> spBitmap; 
    D2D1_BITMAP_PROPERTIES bp = D2D1::BitmapProperties(); 
    bp.pixelFormat = prop.pixelFormat; 

    HR(spRT->CreateSharedBitmap(
     __uuidof(IWICBitmap), 
     static_cast<void*>(spWICBitmap.GetRawPointer()), 
     &bp, 
     &spBitmap 
     )); // <------------------------- This fails with E_INVALIDARG 

    // 
    // Copy the source RenderTarget to this bitmap 
    // 
    HR(spBitmap->CopyFromRenderTarget(nullptr, pRTSrc, nullptr)); 

    // 
    // Draw this bitmap to the output render target 
    // 

    spRT->BeginDraw(); 
    spRT->Clear(D2D1::ColorF(D2D1::ColorF::GreenYellow)); 
    spRT->DrawBitmap(spBitmap); 
    HR(spRT->EndDraw()); 

    // 
    // Save image to file 
    // 

    HR(m_spWICFactory->CreateStream(&spStream)); 
    WICPixelFormatGUID format = GUID_WICPixelFormat32bppPBGRA; 
    HR(spStream->InitializeFromFilename(uri, GENERIC_WRITE)); 

    HR(m_spWICFactory->CreateEncoder(GUID_ContainerFormatPng, nullptr, &spEncoder)); 
    HR(spEncoder->Initialize(spStream, WICBitmapEncoderNoCache)); 
    HR(spEncoder->CreateNewFrame(&spFrameEncode, nullptr)); 
    HR(spFrameEncode->Initialize(nullptr)); 
    HR(spFrameEncode->SetSize(bitmapWidth, bitmapHeight)); 
    HR(spFrameEncode->SetPixelFormat(&format)); 
    HR(spFrameEncode->WriteSource(spWICBitmap, nullptr)); 
    HR(spFrameEncode->Commit()); 
    HR(spEncoder->Commit()); 
    HR(spStream->Commit(STGC_DEFAULT)); 

done: 
    return hr; 
} 

任何问题与此代码? (我确定有很多:))MSDN上的某处表示WIC渲染目标只支持软件模式,而DXGI渲染目标只支持硬件模式。这是上述对CreateSharedBitmap()的调用失败的原因吗?那么我应该如何将DXGI曲面内容保存到使用D2D的图像文件中?

回答

2
  1. 由于某些限制,您可以使用D3DX11SaveTextureToFile。在你的表面上使用QI来获得ID3D11Resource

  2. 在同一页面上,他们推荐DirectXTex库作为替换,CaptureTexture然后SaveToXXXFile(其中XXX是WIC,DDS或TGA)。所以这是另一种选择。另外,如果您的表面已创建为GDI兼容,则可以使用IDXGISurface1::GetDC。 (在你的IDXGISurface上使用QI来获得IDXGISurface1)。将DC保存到文件中作为练习留给读者。

记住与神秘返回代码使用Debug Layer求助像E_INVALIDARG

0

你可以试试这个(我没有):

  • 使您的老DXGISurface。
  • 制作辅助ID2D1DeviceContext渲染目标。
  • 使用ID2D1DeviceContext :: CreateBitmapFromDxgiSurface创建与DXGI表面关联的ID2D1Bitmap1。
  • 在您的DXGISurface上绘制。你应该在ID2D1Bitmap1上得到相同的结果。
  • 使用ID2D1Bitmap1 :: Map获取指向pixeldata的内存指针。
  • 将pixeldata复制到文件或wicbitmap进行编码(jpeg,tiff等)
相关问题