locked
Direct2D: problem on loading (alpha-channel) images from files RRS feed

  • Question

  • Hello,

    I would have a question on you: I have created a function that loads images from files. Some images contain alpha-channel (.png & .bmp).
    The problem: normally, I have to use a converter to be sure that the image can be used in Direct2D, but, if I use a converter, I lose the alpha-channel in the sense that the transparency doesn't work (the portions of the image that is transparent, is black).
    If I don't use the converter, everything is ok, the transparency works, but, the 10-15% from all my images appears distorted. So, I have to use a converter.

    Question: do you have any idea on how can I improve my function, in order to support transparency/alpha-channel?

    Mention: HRESULT variable contains no error.

    Thanks a lot!

    HRESULT CMyClass::LoadWICBitmapFromFile(PCWSTR path)
    {
    	HRESULT hr = S_OK;
    
    	// Create WIC factory
    	hr = CoCreateInstance(
    		CLSID_WICImagingFactory1,
    		NULL,
    		CLSCTX_INPROC_SERVER,
    		IID_PPV_ARGS(&m_pIWICFactory)
    		);
    
    	IWICBitmapDecoder *pIDecoder = NULL;
    	IWICBitmapFrameDecode *pIDecoderFrame = NULL;
    	IWICFormatConverter *pConverter = NULL;
    
    	hr = m_pIWICFactory->CreateDecoderFromFilename(
    		path,							// Image to be decoded
    		NULL,                           // Do not prefer a particular vendor
    		GENERIC_READ,                   // Desired read access to the file
    		WICDecodeMetadataCacheOnDemand, // Cache metadata when needed
    		&pIDecoder                      // Pointer to the decoder
    		);
    
    	// Retrieve the first bitmap frame.
    	if (SUCCEEDED(hr))
    	{
    		hr = pIDecoder->GetFrame(0, &pIDecoderFrame);
    	}
    
    	if (SUCCEEDED(hr))
    	{
    		hr = m_pIWICFactory->CreateFormatConverter(&pConverter);
    	}
    
    	if (SUCCEEDED(hr))
    	{
    		hr = pConverter->Initialize(
    			pIDecoderFrame,
    			GUID_WICPixelFormat32bppPBGRA,
    			WICBitmapDitherTypeNone,
    			NULL,
    			0.0f,
    			WICBitmapPaletteTypeCustom
    			);
    	}
    
    	if (SUCCEEDED(hr))
    	{
    		hr = m_pIWICFactory->CreateBitmapFromSource(
    			pConverter/*pIDecoderFrame*/,  // If I use pIDecoderFrame instead of pConverter, the alpha channel is preserved, but I have problems on rendering some images since I don't use a converter anymore.
    			WICBitmapCacheOnDemand,				 
    			&pWicBitmap);
    	}
    
    
    	SafeRelease(pIDecoder);
    	SafeRelease(pIDecoderFrame);
    	SafeRelease(pConverter);
    
    	return hr;
    }

    Thursday, April 30, 2020 6:27 PM

All replies

  • I adapted one of the MS functions LoadBitmapFromFile from the SDK and it has always worked fine for me :

    from SimpleDirect2dApplication.cpp

    Thursday, April 30, 2020 8:53 PM
  • Try run,type: DXDIAG run the Direct X tests.
    Thursday, April 30, 2020 9:05 PM
  • Hello,

    Does @Castorix31's solution work for you?

    If not, could you snapshots to demonstrate this issue? Or how do you check the alpha channel is valid or not?

    Best regards,

    Rita


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Friday, May 1, 2020 9:40 AM
  • Hi Rita,

    No, doesn't work. @Castorix creates a ID2D1Bitmap, but in my case I need a IWICBitmap. It would have been a good solution if I could copy pixels from ID2D1Bitmap, but this is not possible.

    I think this is a bug in Direct2D since I specified clearly that I need a BGRA converter (GUID_WICPixelFormat32bppPBGRA).

    These are two images: in one of them transparency is not working, and in the other one, it is.

    Friday, May 1, 2020 10:47 AM
  • The function creates a ID2D1Bitmap from WIC bitmap with ID2D1RenderTarget::CreateBitmapFromWicBitmap

    because in Direct2D, everything works with ID2D1Bitmap

    I use it to load .png files and the transparency works normally (for example sprites animations on an image in background) 

    Otherwise I had posted in this thread a sample with WIC only to display a .png by using other MS functions

    but for GDI, not Direct2D

    Friday, May 1, 2020 11:33 AM
  • You're declaring that your pixel values have already been multiplied by the alpha value (the "P" in GUID_WICPixelFormat32bppPBGRA).  That's unusual for a bitmap.  Are you sure you don't really want GUID_WICPixelFormat32bppBGRA?



    Tim Roberts | Driver MVP Emeritus | Providenza & Boekelheide, Inc.

    Friday, May 1, 2020 6:29 PM
  • Hi Tim,

    Thanks, I tried, but it has no effect.

    Best

    Sunday, May 3, 2020 8:23 AM
  • Hello GHEORGHE_926,

    Thanks for sharing images.

    >>>I think this is a bug in Direct2D since I specified clearly that I need a BGRA converter (GUID_WICPixelFormat32bppPBGRA).

    What's your source image pixel format? There is IWICFormatConverter::CanConvert API you can check if it supports convert from your source image pixel format to GUID_WICPixelFormat32bppPBGRA.

    >>>No, doesn't work. @Castorix creates a ID2D1Bitmap, but in my case I need a IWICBitmap.

    And refer to this official sample: CApplication::CreateD2D1BitmapFromFile to see if it helps.

        if (SUCCEEDED(hr))
        {
            hr = _wicFactory->CreateBitmapFromSource(wicFormatConverter, WICBitmapCacheOnLoad, &wicBitmap);
        }
    
        if (SUCCEEDED(hr))
        {
            hr = _d2d1DeviceContext->CreateBitmapFromWicBitmap(wicBitmap, bitmap); 
        }

    Best regards,

    Rita


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Monday, May 4, 2020 6:30 AM
  • It is possible to copy the bitmap from Direct2D though, unless you are somehow still stuck on Windows Vista.

    This will work on Windows 7 SP1 with the platform update onwards. This does however require using the features that were added with Windows 8. They were added to Windows 7 as part of the platform update.

    1) IWICImagingFactory2 allows you to create an IWICImageEncoder object, this allows you to write Direct2D bitmaps to WIC bitmap encoders. This does require that you have an ID2D1Device instance though.

    2) ID2D1Bitmap1 has the Map and Unmap members that allow you to map the bitmap to memory. This does require you create the bitmap so that it can be read by the CPU, and you must do this via ID2D1DeviceContext.

    Even if you are not using the Windows 8 way of creating the D2D objects, if you can get access to an ID2D1RenderTarget instance then you can get both of these.

    ID2D1RenderTarget can be used to get a ID2D1DeviceContext instance by using QueryInterface to query for the device context. You can then use this device context to get access to the device. These interfaces are still created if you use the older ID2D1RenderTarget interface.

    Finally, even if you use some other method for getting the WIC bitmap into Direct2D, the fact is that there is a requirement for creating a Direct2D bitmap somewhere because it is hardware accelerated and must be directly accessed by your graphics adapter. 

    This means that there is a portion of code that you have not shown which could be the cause of this. This converter that you use to get the bitmap into Direct2D, if it isn't creating the alpha channel properly then you will have issues. So be sure that the converter that you stated that you are using is creating the Direct2D bitmap with alpha.


    This is a signature. Any samples given are not meant to have error checking or show best practices. They are meant to just illustrate a point. I may also give inefficient code or introduce some problems to discourage copy/paste coding. This is because the major point of my posts is to aid in the learning process.

    Friday, May 8, 2020 2:50 PM