2014-02-13 91 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等)
相關問題