简体   繁体   English

MFC显示透明背景的png

[英]MFC displaying png with transparent background

I need a way to display a PNG image with transparent background on a background with gradient color. 我需要一种方法来在具有渐变颜色的背景上显示具有透明背景的PNG图像。

I have 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 black background wherever it is transparent in original image. 但是foo.png在原始图像中的任何地方都会变成黑色背景。

I did try to do a new bitmap that was painted with transparent color and did all possible operations on it, but that 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();

This did not do the trick. 这没有做到这一点。 Either, there was all black square on the screen, or the result was the same as original. 要么,屏幕上都有黑色方块,或者结果与原始相同。

I have also checked AlphaBlend API, but my code must be pure MFC + C++ witthout any additional APIs. 我还检查了AlphaBlend API,但我的代码必须是纯MFC + C ++,不管任何其他API。 [Edit]: Company policy is as little APIs as possible. [编辑]:公司政策尽可能少的API。 The code is supposed to run on embedded windows systems in real time. 该代码应该在嵌入式Windows系统上实时运行。

[Edit 2]: I am not bound to PNG image format, meaning, anything that will display as transparent, goes. [编辑2]:我不受PNG图像格式的约束,这意味着任何显示为透明的东西都会出现。

Please, tell me what am I doing wrong? 拜托,告诉我,我做错了什么?

  • Convert the png to a 32 bit bmp file. 将png转换为32位bmp文件。 Google 'AlphaConv' and use that. 谷歌'AlphaConv'并使用它。 PNG's are a PITA to work with - several API's claim to support them but actually don't, or only partially, or only on some platforms etc. PNG是一个可以使用的PITA - 几个API声称支持它们但实际上不支持,或者只是部分支持,或者只支持某些平台等。
  • Load your 32-bit bmp using CBitmap::LoadBitmap (from resources - this is by far the easiest) 使用CBitmap :: LoadBitmap加载32位bmp(来自资源 - 这是迄今为止最简单的)
  • Then use CDC::AlphaBlend() to draw your bitmap. 然后使用CDC :: AlphaBlend()绘制您的位图。 TransparentBlt() doesn't work with an alpha channel - it's just either draw the pixel or not. TransparentBlt()不适用于alpha通道 - 它只是绘制像素或不绘制像素。 AlphaBlend is part of the win32 API, and you could still investigate CImage::AlphaBlend if you'd like, but that has a bug somewhere (I forgot what exactly) so I always use the raw ::AlphaBlend. AlphaBlend是win32 API的一部分,如果你愿意的话,你仍然可以调查CImage :: AlphaBlend,但是那里有一个bug(我忘了究竟是什么)所以我总是使用raw :: AlphaBlend。
  • But beware - you need to premultipy the alpha channel for correct display. 但要注意 - 您需要预先对Alpha通道进行多重处理才能正确显示。 See my answer on How to draw 32-bit alpha channel bitmaps? 请参阅我的答案如何绘制32位alpha通道位图? .

No variation of what you described will work. 没有你所描述的变化将起作用。 You need another API to get this to work. 您需要另一个API才能使其正常工作。 Or, you could use GetDIBits and do your own version of ::AlphaBlend() :) 或者,您可以使用GetDIBits并执行您自己的:: AlphaBlend():)

Based on what you're asking for (simply some set of pixels being transparent) it's probably easiest to use a 24- or 32-bit BMP, and simply pick a color to treat as transparent. 根据您的要求(只是一些像素透明),使用24位或32位BMP最简单,只需选择一种颜色即可。 Pre-process your picture to take any pixel that precisely matches your transparent color and increase change the least significant bit of one of the channels. 预处理图片以获取与您的透明颜色精确匹配的任何像素,并增加更改其中一个通道的最低有效位。

Given 8 bits per channel, this won't normally cause a visible change. 给定每通道8位,这通常不会导致明显的变化。 Then draw the pixels you want transparent in one exact color. 然后以一种精确的颜色绘制您想要透明的像素。 This is easy to do in something like a paint program. 这很像涂料程序。

You can then draw that to your DC using TransparentBlt . 然后,您可以使用TransparentBlt将其绘制到DC。 That lets you specify the color you want to treat as transparent. 这使您可以指定要视为透明的颜色。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM