How to draw transparent BMP with GDI+

10,218

Solution 1

The simplest solution is to use some format other than BMP.

You need the bits to contain alpha data, and you need the Bitmap to be in a format that has alpha data. When you load a BMP with GDI+, it will always use a format without alpha, even if the BMP has an alpha channel. I believe the data is there in the image bits, but it's not being used.

The problem when you clone or draw to a PixelFormat32bppPARGB Bitmap is that GDI+ will convert the image data to the new format, which means discarding the alpha data.

Assuming it's loading the bits correctly, what you need to do is copy the bits over directly to another bitmap with the correct format. You can do this with Bitmap::LockBits and Bitmap::UnlockBits. (Make sure you lock each bitmap with its native pixel format so no conversion is done.)

Solution 2

A late answer but:

ImageAttributes imAtt;    
imAtt.SetColorKey(Color(255,255,255), Color(255,255,255), ColorAdjustTypeBitmap);  

Will make white (255,255,255) transparent on any bitmap you use this image attribute with.

Share:
10,218
sigy
Author by

sigy

Updated on June 04, 2022

Comments

  • sigy
    sigy almost 2 years

    I'm currently editing some old GDI code to use GDI+ and ran into a problem when it comes to draw a BMP file with transparent background. The old GDI code did not use any obvious extra code to draw the background transparent so I'm wondering how to achieve this using GDI+.

    My current code looks like this

    HINSTANCE hinstance = GetModuleHandle(NULL);
    bmp = Gdiplus::Bitmap::FromResource(hinstance, MAKEINTRESOURCEW(IDB_BMP));
    Gdiplus::Graphics graphics(pDC->m_hDC);
    graphics.DrawImage(&bmp, posX, posY);
    

    I also tried to create a new bitmap from the resource by using the clone method and by drawing the bitmap to a newly created one but neither did help. Both times I used PixelFormat32bppPARGB.

    Then I tried to use alpha blending but this way the whole image gets transparent and not only the background:

    Gdiplus::ColorMatrix clrMatrix = { 
        1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
        0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
        0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
        0.0f, 0.0f, 0.0f, 0.5f, 0.0f,
        0.0f, 0.0f, 0.0f, 0.0f, 1.0f
    };
    
    Gdiplus::ImageAttributes imgAttr;
    imgAttr.SetColorMatrix(&clrMatrix);
    
    graphics.DrawImage(&bmp, destRect, 0, 0, width(), height(), Gdiplus::UnitPixel, &imgAttr);
    

    The transparency information is already contained in the image but I don't have a clue how to apply it when drawing the image. How does one achieve this?

  • sigy
    sigy almost 12 years
    Ok, it really seems that the old GDI is capable of drawing such images without any extra line of code and the new GDI+ cant do the same without heavy extra work....sad but true
  • BrainSlugs83
    BrainSlugs83 over 9 years
    As the answer indicated, GDI+ can do it also, you just have to use an image format that supports an alpha channel (like PNG). [I have no doubt that you can store alpha data in a BMP file, but you're not supposed to. That's not normal. If it works, it works because of a bug in GDI, and you shouldn't rely on that.]
  • Paul
    Paul over 5 years
    How to use this on a bitmap?
  • Gautam Jain
    Gautam Jain about 3 years
    Pass that ImageAttributes object to one of the overloaded version of Graphics.DrawImage