IWICImagingFactory::CreateDecoderFromStream() fails with error: WINCODEC_ERR_COMPONENTNOTFOUND

Answered IWICImagingFactory::CreateDecoderFromStream() fails with error: WINCODEC_ERR_COMPONENTNOTFOUND

  • Saturday, April 07, 2012 1:24 PM
     
      Has Code

    I'm trying to load a ID2D1Bitmap from a bitmap resource. To do so, I am using the Windows Imaging Component (IWIC) to process the image before Direct2D uses it.

    However, it fails when I call CreateDecoderFromStream(), and it returns a strange error message – 0x88982f50 – that tells me nothing. I've searched Google and used DirectX Error Lookup. The DirectX Error Lookup tool only tells me this:

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

    This is the code I'm using to try and load an ID2D1Bitmap from a resource:

    int LoadBitmapFromResource( IWICImagingFactory *pImageFactory, ID2D1RenderTarget *pRT, int resID, ID2D1Bitmap **ppD2DBitmap ) { int errmsg; BITMAP bitmap; WICBitmapAlphaChannelOption wicalpha; IWICBitmap *pwicbitmap; IWICStream *pStream; IWICBitmapDecoder *pDecoder; IWICFormatConverter *pConverter; WICRect wicrect; IWICBitmapLock *pwicbmplock; WICInProcPointer wicbmppointer; UINT bmpsize; IWICBitmapFrameDecode *pFrame; ID2D1Factory *d2dfactory; D2D1_BITMAP_PROPERTIES d2dbp; D2D1_PIXEL_FORMAT d2dpf; FLOAT dpiX; FLOAT dpiY; wicalpha = WICBitmapUseAlpha; errmsg = pImageFactory->CreateBitmapFromHBITMAP( LoadBitmap( GetModuleHandle(NULL), MAKEINTRESOURCEW(resID) ), NULL, wicalpha, &pwicbitmap ); if( !SUCCEEDED(errmsg) ) { printf("LoadBitmapFromResource::CreateBitmapFromHBITMAP() error: %x\r\n", errmsg ); return errmsg; } errmsg = pImageFactory->CreateStream( &pStream ); if( !SUCCEEDED(errmsg) ) { printf("LoadBitmapFromResource::CreateStream() error: %x\r\n", errmsg ); return errmsg; } wicrect.Height = 128; wicrect.Width = 128; wicrect.X = 0; wicrect.Y = 0; errmsg = pwicbitmap->Lock( &wicrect, WICBitmapLockWrite, &pwicbmplock ); if( !SUCCEEDED(errmsg) ) { printf("LoadBitmapFromResource::Lock() error: %x\r\n", errmsg ); return errmsg; } errmsg = pwicbmplock->GetDataPointer( &bmpsize, &wicbmppointer ); if( !SUCCEEDED(errmsg) ) { printf("LoadBitmapFromResource::GetDataPointer() error: %x\r\n", errmsg ); return errmsg; } errmsg = pStream->InitializeFromMemory( wicbmppointer, bmpsize ); if( !SUCCEEDED(errmsg) ) { printf("LoadBitmapFromResource::InitializeFromMemory() error: %x\r\n", errmsg ); return errmsg; } errmsg = pImageFactory->CreateDecoderFromStream( pStream, NULL, WICDecodeMetadataCacheOnLoad, &pDecoder ); if( !SUCCEEDED(errmsg) ) { printf("LoadBitmapFromResource::CreateDecoderFromStream() error: %x\r\n", errmsg ); Sleep(INFINITE); return errmsg; } errmsg = pDecoder->GetFrame( 0, &pFrame ); if( !SUCCEEDED(errmsg) ) { printf("LoadBitmapFromResource::GetFrame() error: %x\r\n", errmsg ); return errmsg; } errmsg = pImageFactory->CreateFormatConverter( &pConverter ); if( !SUCCEEDED(errmsg) ) { printf("LoadBitmapFromResource::CreateFormatConverter() error: %x\r\n", errmsg ); return errmsg; } d2dpf.format = DXGI_FORMAT_B8G8R8A8_UNORM; d2dpf.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED; pRT->GetFactory( &d2dfactory ); d2dfactory->GetDesktopDpi( &dpiX, &dpiY ); d2dbp.pixelFormat = d2dpf; d2dbp.dpiX = dpiX; d2dbp.dpiY = dpiY; pConverter->Initialize( pFrame, GUID_WICPixelFormat32bppPBGRA, WICBitmapDitherTypeNone, NULL, 0.0f, WICBitmapPaletteTypeMedianCut ); if( !SUCCEEDED(errmsg) ) { printf("LoadBitmapFromResource::Initialize() error: %x\r\n", errmsg ); return errmsg; } errmsg = pRT->CreateBitmapFromWicBitmap( pFrame, &d2dbp, ppD2DBitmap ); if( !SUCCEEDED(errmsg) ) { printf("LoadBitmapFromResource::CreateBitmapFromWicBitmap() error: %x\r\n", errmsg ); return errmsg; }

    pwicbmplock->Release();
    pFrame->Release();
    pConverter->Release();
    pDecoder->Release();
    pStream->Release();
    pwicbitmap->Release();

    return 0; }

    I can't seem to find a way to create an ID2D1Bitmap from a Resource without the Windows Imaging Component, and I spent ages trying to find out what the problem is (to no avail). The closest thing I have to a related discussion is here, and all it suggests is reinstalling .NET which does not work.

    Can anyone see the problem? Thanks!



All Replies

  • Saturday, April 07, 2012 10:01 PM
     
     Answered

    CreateDecoderFromStream is for image data in a standard image file format. What you're giving it is raw bitmap data, with no information about its meaning.

    There's no need to use CreateDecoderFromStream at all, since CreateBitmapFromHBITMAP gives you an IWICBitmapSource (IWICBitmap inherits from IWICBitmapSource), which you can use directly to initialize your format converter.

  • Saturday, April 07, 2012 10:05 PM
     
     
    By the way, you may be leaking your HBITMAP, which would be very bad since GDI handles are limited. I'm not sure whether CreateBitmapFromHBITMAP will delete it when it's no longer needed.
  • Sunday, April 08, 2012 4:03 AM
     
      Has Code

    Thanks for catching my HBITMAP leak!

    I took out the Stream and Stream Decoder and fed the IWICBitmapSource into the format converter, but now it gives me a D2DERR_UNSUPPORTED_PIXEL_FORMAT (0x88982f80) error. This is my updated code:

    int LoadBitmapFromResource( IWICImagingFactory *pImageFactory, ID2D1RenderTarget *pRT, int resID, ID2D1Bitmap **ppD2DBitmap )
    {
    	int errmsg;
    
    	HBITMAP hbitmap;
    	WICBitmapAlphaChannelOption wicalpha;
    	IWICBitmap *pwicbitmap;
    	IWICFormatConverter *pConverter;
    
    	ID2D1Factory *d2dfactory;
    	D2D1_BITMAP_PROPERTIES d2dbp;
    	D2D1_PIXEL_FORMAT d2dpf;
    	FLOAT dpiX;
    	FLOAT dpiY;
    
    	hbitmap = LoadBitmap( GetModuleHandle(NULL), MAKEINTRESOURCEW(resID) );
    	wicalpha = WICBitmapUseAlpha;
    
    	errmsg = pImageFactory->CreateBitmapFromHBITMAP( hbitmap, NULL, wicalpha, &pwicbitmap );
    	if( !SUCCEEDED(errmsg) )
    	{
    		printf("LoadBitmapFromResource::CreateBitmapFromHBITMAP() error: %x\r\n", errmsg );
    		return errmsg;
    	}
    
    	errmsg = pImageFactory->CreateFormatConverter( &pConverter );
    	if( !SUCCEEDED(errmsg) )
    	{
    		printf("LoadBitmapFromResource::CreateFormatConverter() error: %x\r\n", errmsg );
    		return errmsg;
    	}
    
    	d2dpf.format = DXGI_FORMAT_B8G8R8A8_UNORM;
    	d2dpf.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
    	pRT->GetFactory( &d2dfactory );
    	d2dfactory->GetDesktopDpi( &dpiX, &dpiY );
    	d2dbp.pixelFormat = d2dpf;
    	d2dbp.dpiX = dpiX;
    	d2dbp.dpiY = dpiY;
    
    	pConverter->Initialize( pwicbitmap, GUID_WICPixelFormat32bppPBGRA, WICBitmapDitherTypeNone, NULL, 0.0f, WICBitmapPaletteTypeMedianCut );
    	if( !SUCCEEDED(errmsg) )
    	{
    		printf("LoadBitmapFromResource::Initialize() error: %x\r\n", errmsg );
    		return errmsg;
    	}
    
    	errmsg = pRT->CreateBitmapFromWicBitmap( pwicbitmap, &d2dbp, ppD2DBitmap );
    	if( !SUCCEEDED(errmsg) )
    	{
    		printf("LoadBitmapFromResource::CreateBitmapFromWicBitmap() error: %x\r\n", errmsg );
    		return errmsg;
    	}
    
    	pConverter->Release();
    	pwicbitmap->Release();
    	DeleteObject( hbitmap );
    	
    	return 0;
    }

    I used the pixel formats in this MSDN page:

    GUID_WICPixelFormat32bpp PBGRADXGI_FORMAT_B8G8R8A8_UNORM D2D1_ALPHA_MODE_PREMULTIPLIED

    Is there a problem with the pixel formats I chose?