0

我正在尝试从位图资源加载 ID2D1Bitmap。为此,我查阅了MSDN 指南,该指南告诉我在 Direct2D 使用图像之前使用 Windows 映像组件 (IWIC) 处理图像。

但是,当我调用它时它失败CreateDecoderFromStream()了,它返回了一条奇怪的错误消息——0x88982f50它什么也没告诉我。我搜索了谷歌并使用了 DirectX 错误查找。DirectX 错误查找工具只告诉我:

HRESULT: 0x88982f50 (2291674960)
Name: Unknown
Description: n/a
Severity code: Failed
Facility Code: FACILITY_DWRITE (2200)
Error Code: 0x2f50 (12112)

这是我用来尝试从资源加载 ID2D1Bitmap 的代码:

int LoadBitmapFromResource( IWICImagingFactory *pIWICFactory, ID2D1RenderTarget *pRT, int resID, ID2D1Bitmap **ppD2DBitmap )
{
    int errmsg;

    HRSRC hbmp;
    HGLOBAL hbmpdata;
    void *pbmp; //system memory pointer to bitmap resource
    DWORD bmpsize;
    IWICStream *pStream;
    IWICBitmapDecoder *pbmpdecoder;
    IWICBitmapFrameDecode *pSource;
    IWICFormatConverter *pConverter;

    hbmp = FindResourceW( GetModuleHandleW(NULL), MAKEINTRESOURCEW(resID), RT_BITMAP );
    if( NULL == hbmp )
    {
        printf("LoadBitmapFromResource::FindResourceW() error: %d\r\n", GetLastError() );
        return GetLastError();
    }

    hbmpdata = LoadResource( GetModuleHandleW(NULL), hbmp );
    if( NULL == hbmpdata )
    {
        printf("LoadBitmapFromResource::LoadResource() error: %d\r\n", GetLastError() );
        return GetLastError();
    }

    pbmp = LockResource( hbmpdata );
    if( NULL == pbmp )
    {
        printf("LoadBitmapFromResource::LockResource() error: %d\r\n", GetLastError() );
        return GetLastError();
    }

    bmpsize = SizeofResource( GetModuleHandleW(NULL), hbmp );
    if( NULL == bmpsize )
    {
        printf("LoadBitmapFromResource::SizeofResource() error: %d\r\n", GetLastError() );
        return GetLastError();
    }

    errmsg = pIWICFactory->CreateStream( &pStream );
    if( !SUCCEEDED(errmsg) )
    {
        printf("LoadBitmapFromResource::CreateStream() error: %x\r\n", errmsg );
        return errmsg;
    }

    errmsg = pStream->InitializeFromMemory( (BYTE*)pbmp, bmpsize );
    if( !SUCCEEDED(errmsg) )
    {
        printf("LoadBitmapFromResource::InitializeFromMemory() error: %x\r\n", errmsg );
        return errmsg;
    }

    errmsg = pIWICFactory->CreateDecoderFromStream( pStream, NULL, WICDecodeMetadataCacheOnLoad, &pbmpdecoder );
    if( !SUCCEEDED(errmsg) )
    {
        printf("LoadBitmapFromResource::CreateDecoderFromStream() error: %x\r\n", errmsg );
        return errmsg;
    }

    errmsg = pbmpdecoder->GetFrame( 0, &pSource );
    if( !SUCCEEDED(errmsg) )
    {
        printf("LoadBitmapFromResource::GetFrame() error: %x\r\n", errmsg );
        return errmsg;
    }

    errmsg = pIWICFactory->CreateFormatConverter( &pConverter );
    if( !SUCCEEDED(errmsg) )
    {
        printf("LoadBitmapFromResource::CreateFormatConverter() error: %x\r\n", errmsg );
        return errmsg;
    }

    errmsg = pConverter->Initialize( pSource, GUID_WICPixelFormat32bppPBGRA, WICBitmapDitherTypeNone, NULL, 0.0f, WICBitmapPaletteTypeMedianCut );
    if( !SUCCEEDED(errmsg) )
    {
        printf("LoadBitmapFromResource::Initialize() error: %x\r\n", errmsg );
        return errmsg;
    }

    errmsg = pRT->CreateBitmapFromWicBitmap( pConverter, ppD2DBitmap );
    if( !SUCCEEDED(errmsg) )
    {
        printf("LoadBitmapFromResource::CreateBitmapFromWicBitmap() error: %x\r\n", errmsg );
        return errmsg;
    }

    pConverter->Release();
    pSource->Release();
    pbmpdecoder->Release();
    pStream->Release();

    return 0;
}
4

3 回答 3

0

事实证明,我不应该将 WIC 解码器用于我的位图资源,因为它显然是无法解码的原始像素数据。

于 2012-04-08T16:52:30.820 回答
0

(我理解这篇文章有点老了,但我把它放在这里以防万一他碰巧再次看到它,它可以帮助其他人或 OP。)

我有与您使用 WIC 从您的 exe 文件中的资源加载 ID2D1Bitmap 完全相同的代码,但我的工作完美。我可以完美地从我的 exe 文件中加载位图。我发现您的代码与我的不同之处在于,我没有使用 (BYTE*) 强制转换,而是使用了 reinterpret_cast。

所以而不是

errmsg = pStream->InitializeFromMemory( (BYTE*)pbmp, bmpsize );
    if( !SUCCEEDED(errmsg) )
    {
        printf("LoadBitmapFromResource::InitializeFromMemory() error: %x\r\n", errmsg );
        return errmsg;
    }

我会尝试做

errmsg = pStream->InitializeFromMemory( reinterpret_cast<BYTE*>(pbmp), bmpsize );
    if( !SUCCEEDED(errmsg) )
    {
        printf("LoadBitmapFromResource::InitializeFromMemory() error: %x\r\n", errmsg );
        return errmsg;
    }
于 2012-10-28T22:19:30.970 回答
0

发生此问题的原因是 LockResource() 返回的位图数据不包含前 14 个字节的位图标头。您可以比较从 LockResource() 返回的数据和原始位图文件来查看。这是C语言中的简单测试代码。您可以在 SizeofResource() 之后添加它,然后检查 out.bmp 文件,这是一个无效的位图文件。并且由于错误的图像数据,它没有任何有效的解码器(WINCODEC_ERR_COMPONENTNOTFOUND)。

    FILE* file;
    fopen_s( &file, "out.bmp", "wb");
    fwrite((const char*)(pbmp), 1, bmpsize, file);
    fclose(file);

有两个明显的解决方案。

  1. 不要从资源创建 IWICStream/IWICBitmapDecoder。相反,直接使用外部位图文件来创建它们。检查 MSDN 的示例代码。https://docs.microsoft.com/en-us/windows/win32/direct2d/how-to-load-a-direct2d-bitmap-from-a-file

  2. 在资源数据前添加位图头。就像是:

     BITMAPFILEHEADER header;
     header.bfType = 0x4D42; // 'BM'
     header.bfSize = bmpsize + 14; // resource data size + 14 bytes header
     header.bfReserved1 = 0;
     header.bfReserved2 = 0;
     header.bfOffBits = 14 + 40; // details in bitmap format
    
     BYTE* buffer = new BYTE[header.bfSize];
    
     memcpy(buffer, &header, 14);
     memcpy(buffer + 14, pbmp, bmpsize);
    
     // Initialize the stream with the memory pointer and size.
     hr = pStream->InitializeFromMemory(
         reinterpret_cast<BYTE*>(buffer),
         header.bfSize
     );
    

请注意,“缓冲区”必须在 IWICStream 的生命周期中处于活动状态。

于 2021-01-27T05:41:29.050 回答