How to save a ID2D1Bitmap to a file using WIC?

1

I have a problem with saving a bitmap into a file. I'm using How to save ID2D1Bitmap to PNG file as a reference, but I have a different error than the one posted in that.

I get error 0x88990015 HRESULT, which means: The resource used was created by a render target in a different resource domain.

Here's my code:

void Wnd::SavePng(LPCWSTR Path,ID2D1Bitmap* pBit) {
    CComPtr<ID2D1RenderTarget> pRT;
    CComPtr<IWICBitmap> pB;
    CComPtr<IWICBitmapEncoder> pEncoder;
    CComPtr<IWICBitmapFrameEncode> pFrame;
    CComPtr<IWICStream> pStream;

    WICPixelFormatGUID format = GUID_WICPixelFormat32bppPBGRA;
    HRESULT Hr = m_pWICFactory->CreateBitmap(pBit->GetSize().width,pBit->GetSize().height,format,WICBitmapCacheOnLoad,&pB); 

    if (SUCCEEDED(Hr)) {
        D2D1_RENDER_TARGET_PROPERTIES RTProps = RenderTargetProperties();
        RTProps.pixelFormat = PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM,D2D1_ALPHA_MODE_PREMULTIPLIED);
        Hr = m_pDirect2dFactory->CreateWicBitmapRenderTarget(pB,&RTProps,&pRT);
    }

    if (SUCCEEDED(Hr)) {
        pRT->BeginDraw();
        pRT->Clear();
        pRT->DrawBitmap(pBit);
        Hr = pRT->EndDraw();
    }

    if (SUCCEEDED(Hr)) {
        Hr = m_pWICFactory->CreateStream(&pStream);
    }

    if (SUCCEEDED(Hr)) {
        Hr = pStream->InitializeFromFilename(Path,GENERIC_WRITE);
    }

    if (SUCCEEDED(Hr)) {
        Hr = m_pWICFactory->CreateEncoder(GUID_ContainerFormatPng,NULL,&pEncoder);
    }

    if (SUCCEEDED(Hr)) {
        Hr = pEncoder->Initialize(pStream,WICBitmapEncoderNoCache);
    }

    if (SUCCEEDED(Hr)) {
        Hr = pEncoder->CreateNewFrame(&pFrame,NULL);
    }

    if (SUCCEEDED(Hr)) {
        Hr = pFrame->Initialize(NULL);
    }

    if (SUCCEEDED(Hr)) {
        Hr = pFrame->SetSize(pBit->GetSize().width,pBit->GetSize().height);
    }

    if (SUCCEEDED(Hr)) {
        Hr = pFrame->SetPixelFormat(&format);
    }

    if (SUCCEEDED(Hr)) {
        Hr = pFrame->WriteSource(pB,NULL);
    }

    if (SUCCEEDED(Hr)) {
        Hr = pFrame->Commit();
    }

    if (SUCCEEDED(Hr)) {
        Hr = pEncoder->Commit();
    }
}

I understand that you can't use resources made by another factory with another, but there has to be a way to make this work.

c++
direct2d
wic
asked on Stack Overflow Jan 10, 2013 by Nooobody • edited May 23, 2017 by Community

1 Answer

1

Your understanding of resource affinity is insufficient. Resources are device-specific rather than factory-specific. Yes, they tend to be factory-specific as well, but the key is the device specificity.

In your example, you are passing in a bitmap created by some other render target, which you then pass to the DrawBitmap method of a different render target. You may only draw a bitmap created by the same render target. This ensures that the bitmap and the render target (source and target) are in the same resource domain (address space).

answered on Stack Overflow Jan 17, 2013 by Kenny Kerr

User contributions licensed under CC BY-SA 3.0