IWICImagingFactory :: CreateDecoderFromStream()失败,错误消息消息没有帮助

时间:2012-04-02 16:10:19

标签: c++ winapi com directx direct2d

我正在尝试从位图资源加载ID2D1Bitmap。为此,我咨询了MSDN guide,告诉我在Direct2D使用之前使用Windows Imaging Component(IWIC)来处理图像。

然而,当我调用CreateDecoderFromStream()时它失败了,它返回一条奇怪的错误消息 - 0x88982f50 - 它什么也没告诉我。我搜索了Google并使用了DirectX Error Lookup。 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;
}

3 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

(我理解这个有点旧的帖子,但是我把它放在这里,以防它帮助别人或OP,如果他碰巧再次看到这个。)

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

所以而不是

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;
    }

答案 2 :(得分: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 的生命周期中,“缓冲区”必须处于活动状态。