MFC显示具有透明背景的PNG

4

我需要一种方法在具有渐变色背景的情况下展示带有透明背景的PNG图片.

我尝试过以下方法:

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();

但是,无论原始图像中透明的地方在哪里,foo.png都会获得黑色背景。

我尝试创建一个用透明颜色绘制的新位图,并对其进行所有可能的操作,但这并没有帮助。以下是其中一种排列的示例:

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();

这并没有起作用。屏幕上要么是一个全黑的正方形,要么结果与原始结果相同。

我还检查过AlphaBlend API,但我的代码必须是纯MFC + C++,不能使用任何其他API。[编辑]: 公司政策要尽可能少使用API。该代码应在嵌入式Windows系统中实时运行。

[编辑2]: 我不限于PNG图像格式,也就是说,任何能够显示为透明的内容都可以。

请告诉我我做错了什么?


1
MFC公开的旧位图调用无法处理Alpha通道。AlphaBlend是更好的选择,它是与MFC内部使用的同一Windows API的一部分。不使用它的原因是什么? - Mark Ransom
该公司的愚蠢政策是尽可能少地使用API,尤其是因为应用程序运行在嵌入式Windows系统上。 - Vladimir Kocjancic
祝你好运。 - Mark Ransom
嗨,@MarkRansom...假设我使用AlphaBlend...为了达到期望的结果,我需要做什么呢?就我所看到的样本而言,AlphaBlend用于设置不透明度。 - Vladimir Kocjancic
我忘了问,这个.png文件是8位还是24位? - Mark Ransom
我没有进行任何缩小操作,所以基本上它要么是24位,要么是32位。 - Vladimir Kocjancic
2个回答

6
  • 将png文件转换为32位bmp文件。搜索“AlphaConv”并使用它。PNG文件很难处理-几个API声称支持它们,但实际上不支持或部分支持,或只在某些平台上支持等。
  • 使用CBitmap :: LoadBitmap(从资源加载32位bmp文件-这是最简单的方法)
  • 然后使用CDC :: AlphaBlend()绘制位图。TransparentBlt()无法与alpha通道一起使用-它只是绘制像素或不绘制。AlphaBlend是win32 API的一部分,您仍然可以尝试使用CImage :: AlphaBlend,但其中有一个错误(我忘记了具体是什么),因此我始终使用原始的:: AlphaBlend。
  • 但要注意-您需要对alpha通道进行预乘以正确显示。请参见我的答案:如何绘制32位alpha通道位图?

你所描述的任何变化都行不通。您需要另一个API才能使其正常工作。或者,您可以使用GetDIBits并自己编写版本的:: AlphaBlend():)


1

根据您的需求(简单地说,只是一些像素透明),最容易使用24位或32位BMP,并选择一种颜色作为透明颜色。预处理您的图片,以便将任何精确匹配您的透明颜色的像素并增加更改一个通道的最低有效位。

给定每个通道8位,这通常不会引起可见变化。然后用一种确切的颜色绘制您想要透明的像素。在像绘画程序之类的软件中很容易实现。

然后,您可以使用TransparentBlt将其绘制到您的DC上。这使您可以指定要视为透明的颜色。


1
这个在抗锯齿方面也能起作用吗?基本上,我的图像是一个透明背景上的绘制圆形。如果我将透明改为比如粉色,一些像素将不是粉色,但也不会有应用程序背景或圆形本身的颜色。 - Vladimir Kocjancic

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接