如何将ID2D1Bitmap保存为PNG文件

4
我在尝试将从ID2D1HwndRenderTarget创建的ID2D1Bitmap保存为PNG文件时遇到了问题。输出的图像只是空白的白色。从函数调用EndDraw()返回的HRESULT为-2003238894。
感谢任何帮助。
以下是我的代码:
HRESULT CImageUtil::SaveBitmapToFile(PCWSTR uri,ID2D1Bitmap* pBitmap,ID2D1RenderTarget* pRenderTarget)
{

HRESULT hr = S_OK;

ID2D1Factory *pD2DFactory = NULL;
IWICBitmap *pWICBitmap = NULL;
ID2D1RenderTarget *pRT = NULL;
IWICBitmapEncoder *pEncoder = NULL;
IWICBitmapFrameEncode *pFrameEncode = NULL;
IWICStream *pStream = NULL;

if (SUCCEEDED(hr))
{
    hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &pD2DFactory);
}

//
// Create IWICBitmap and RT
//

UINT sc_bitmapWidth = pBitmap->GetSize().width;
UINT sc_bitmapHeight = pBitmap->GetSize().height;

if (SUCCEEDED(hr))
{
    hr = m_pWICFactory->CreateBitmap(
        sc_bitmapWidth,
        sc_bitmapHeight,
    GUID_WICPixelFormat32bppPBGRA,
        WICBitmapCacheOnLoad,
        &pWICBitmap
        );
}

if (SUCCEEDED(hr))
{
    D2D1_RENDER_TARGET_PROPERTIES rtProps = D2D1::RenderTargetProperties();
    rtProps.pixelFormat = D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED);
    rtProps.type = D2D1_RENDER_TARGET_TYPE_DEFAULT;
    rtProps.usage = D2D1_RENDER_TARGET_USAGE_NONE;

    hr = pD2DFactory->CreateWicBitmapRenderTarget(
        pWICBitmap,
    rtProps,
        &pRT
        );
}

if (SUCCEEDED(hr))
{
    //
    // Render into the bitmap
    //
    pRT->BeginDraw();

pRT->Clear(D2D1::ColorF(D2D1::ColorF::White));


pRT->DrawBitmap(pBitmap);

    pRT->EndDraw();
}
if (SUCCEEDED(hr))
{

    //
    // Save image to file
    //
    hr = m_pWICFactory->CreateStream(&pStream);
}

WICPixelFormatGUID format = GUID_WICPixelFormat32bppPBGRA;
if (SUCCEEDED(hr))
{

    hr = pStream->InitializeFromFilename(uri, 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(&pFrameEncode, NULL);
}
if (SUCCEEDED(hr))
{
    hr = pFrameEncode->Initialize(NULL);
}

if (SUCCEEDED(hr))
{
    hr = pFrameEncode->SetSize(sc_bitmapWidth, sc_bitmapHeight);
}
if (SUCCEEDED(hr))
{
    hr = pFrameEncode->SetPixelFormat(&format);
}
if (SUCCEEDED(hr))
{
    hr = pFrameEncode->WriteSource(pWICBitmap, NULL);
}
if (SUCCEEDED(hr))
{
    hr = pFrameEncode->Commit();
}
if (SUCCEEDED(hr))
{
    hr = pEncoder->Commit();
}

SafeRelease(&pD2DFactory);
SafeRelease(&pWICBitmap);
SafeRelease(&pRT);
SafeRelease(&pEncoder);
SafeRelease(&pFrameEncode);
SafeRelease(&pStream);

return hr;
}
1个回答

0

如果你只是吞咽错误而不记录它们来自哪里,那么你怎么知道是否出现了错误呢?你会得到一个非零的Hresult,所以首先要通过在每个函数调用之后添加printf或fprintf来确定它来自哪个函数。此外,在块中你还有一个明显的遗漏:

if (SUCCEEDED(hr))
{
    //
    // Render into the bitmap
    //
    pRT->BeginDraw();

pRT->Clear(D2D1::ColorF(D2D1::ColorF::White));


pRT->DrawBitmap(pBitmap);

    pRT->EndDraw();
}
if (SUCCEEDED(hr))

你没有在那里任何地方分配hr,所以你甚至不知道它们中的任何一个是否出错。显然,Clear()和最终的png写入工作正常,因为你得到了一个好文件,所以是DrawBitmap或其中一个位图创建调用失败了。


是的,当我这样编码时:pRT->DrawBitmap(pBitmap); hr = pRT->EndDraw(),然后hr = -2003238894。这意味着调用DrawBitmap出错了。如果我注释掉pRT->DrawBitmap(...)这一行,那么hr = S_OK。 - Jacky Nguyen
我猜测错误是因为我绘制了不兼容的位图。我使用 WIC 渲染目标来绘制 Hwnd 渲染目标的位图。但我不知道该如何修复它。 - Jacky Nguyen
4
我在这里查到了你的错误代码:http://msdn.microsoft.com/en-us/library/windows/desktop/dd370979%28v=vs.85%29.aspx (0x88990012 = D2DERR_WRONG_FACTORY)。看起来问题是pBitmap和pRT没有从同一个ID2D1Factory对象创建。 - Esme Povirk
1
非常感谢,您的回复非常有用。我使用了不同的工厂导致了错误。问题现在已经解决了。 - Jacky Nguyen
@SilverbackNet:你可以将这个(省略hr检查)作为评论添加到问题中,而不是作为解决方案。真正的解决方案是Vincent提供的。 - legends2k
@VincentPovirk:你本可以把你的评论加为答案。 - legends2k

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接