MFC displaying png with transparent background

I need a way to display a PNG image with transparent background on a background with a gradient color.

I've tried this:

CImage img;
CBitmap bmp;
img.Load(_T(".\\res\\foo.png"));
bmp.Attach(img.Detach());
CDC dcStatus;
dcStatus.CreateCompatibleDC(&dc);
dcStatus.SelectObject(&bmp);
dcStatus.SetBkColor(TRANSPARENT);
dc.BitBlt(rectText.left + 250, rectText.top, 14, 14, &dcStatus, 0, 0, SRCCOPY);
bmp.DeleteObject();

      

but foo.png gets a black background wherever it is transparent in the original image.

I tried to make a new bitmap that was painted with a transparent color and did all the possible operations on it, but it didn't help. Sample of one permutation:

CImage img;
CBitmap bmp;
img.Load(_T(".\\res\\foo.png"));
bmp.Attach(img.Detach());
CBitmap bmpMaska;
bmpMaska.CreateBitmap(14, 14, 1, 1, NULL);
CDC dcStatus;
dcStatus.CreateCompatibleDC(&dc);
dcStatus.SelectObject(&bmp);
CDC dcMaska;
dcMaska.CreateCompatibleDC(&dc);
dcMaska.SelectObject(&bmpMaska);
dcMaska.SetBkColor(dcStatus.GetPixel(0, 0));
//TODO: Bitmap ni transparent
dc.BitBlt(rectText.left + 250, rectText.top, 14, 14, &dcMaska, 0, 0, SRCCOPY);
dc.BitBlt(rectText.left + 250, rectText.top, 14, 14, &dcStatus, 0, 0, SRCAND);  
bmp.DeleteObject();
bmpMaska.DeleteObject();

      

It did not help. Either there was an entire black square on the screen, or the result was the same as the original.

I also checked the AlphaBlend API, but my code should be pure MFC + C ++ without any additional APIs. [Edit]: Company policy is as little API as possible. The code should work on embedded Windows systems in real time.

[Edit 2]: I am not tied to the PNG image format, which means it will display as transparent.

Please tell me what am I doing wrong?

+3


source to share


2 answers


  • Convert png to 32-bit BMP file. Google AlphaConv and use that. PNG is a PITA for working with multiple API claims to support them, but in reality there are none or only partially or only on some platforms, etc.
  • Load 32bit BMP with CBitmap :: LoadBitmap (from resources - this is the easiest one)
  • Then use CDC :: AlphaBlend () to paint the bitmap. TransparentBlt () doesn't work with alpha channel - it just draws the pixel or not. AlphaBlend is part of the win32 API and you can still investigate CImage :: AlphaBlend if you like, but there is a bug somewhere (I forgot which one), so I always use raw :: AlphaBlend.
  • But be careful - you need to do well on the alpha channel for it to display correctly. See my answer to How do I draw 32 bit alpha channel bitmaps? ...


No variation of what you described will work. You need a different API for this. Or you can use GetDIBits and make your own version :: AlphaBlend () :)

+4


source


Based on what you are asking (just some set of pixels are transparent), it might be easiest to use a 24- or 32-bit BMP and just choose the color to process as transparent. Pre-process the image to get any pixel that exactly matches your transparent color and will increase the change in the least significant bit of one of the channels.

Given 8 bits per channel, this usually causes no visible change. Then paint the pixels you want transparently with one exact color. This can be done easily in a paint program.



Then you can do it for your DC using TransparentBlt

. This allows you to specify the color that you want to be treated as transparent.

+1


source







All Articles