MFC显示透明背景的png

时间:2014-10-22 21:38:23

标签: c++ mfc png

我需要一种在渐变色背景上显示透明背景的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图像格式的约束,这意味着任何显示为透明的内容都会出现。

请告诉我,我做错了什么?

2 个答案:

答案 0 :(得分:4)

  • 将png转换为32位bmp文件。 Google' AlphaConv'并使用它。 PNG是一个可以使用的PITA - 几个API声称支持它们但实际上不是,或者只是部分或仅在某些平台上等。
  • 使用CBitmap :: LoadBitmap加载你的32位bmp(来自资源 - 这是迄今为止最容易的)
  • 然后使用CDC :: AlphaBlend()绘制您的位图。 TransparentBlt()不能使用alpha通道 - 它只是绘制像素或不绘制像素。 AlphaBlend是win32 API的一部分,如果你愿意,你仍然可以调查CImage :: AlphaBlend,但是那里有一个bug(我忘了究竟是什么)所以我总是使用raw :: AlphaBlend。
  • 但要注意 - 您需要预先对alpha通道进行预先验证才能正确显示。请参阅How to draw 32-bit alpha channel bitmaps?上的答案。

您描述的内容不会有任何变化。您需要另一个API才能使其正常工作。或者,您可以使用GetDIBits并执行您自己的:: AlphaBlend()版本:)

答案 1 :(得分:1)

根据您的要求(只是一些像素组是透明的),使用24位或32位BMP最简单,只需选择一种颜色即可。预处理您的照片以拍摄与您的透明色精确匹配的任何像素,并增加更改其中一个通道的最低有效位。

每个通道给定8位,这通常不会导致明显的变化。然后以一种精确的颜色绘制您想要透明的像素。这很像涂料程序。

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