我必须在一个由两个PNG文件组成的图片控件上呈现图像,其中顶部图像在某些位置上具有透明像素。
结果应该是plotter.png
with bar.png
顶部重叠显示为(注意栏上奇怪的白色轮廓):
但它应该是:
我为它制作的代码很简单
CImage image;
if (FAILED(image.Load(L"plotter.png")))
return false;
CImage imageBar;
if (FAILED(imageBar.Load(L"bar.png")))
return false;
imageBar.AlphaBlend(image.GetDC(), CPoint());
image.ReleaseDC();
((CStatic*)GetDlgItem(IDC_PICTURE))->SetBitmap(image);
我已阅读Alpha Blending a Bitmap和BLENDFUNCTION structure上的MSDN文档,并做了一些实验。一个细节让我盯着我引用的文字:
当位图具有Alpha通道时(即, 每像素alpha)。请注意,API使用预乘alpha,即 表示位图中的红色,绿色和蓝色通道值必须 与alpha通道值预乘。例如,如果 alpha通道值为x,红色,绿色和蓝色通道必须为 在调用之前乘以x并除以0xff。
Alphablend
使用预乘alpha ,这意味着在加载后我必须转到位图并将每个像素乘以其自己的alpha。所以我试过
for (int i = 0; i < imageBar.GetWidth(); i++)
{
for (int j = 0; j < imageBar.GetHeight(); j++)
{
BYTE* ptr = (BYTE*) imageBar.GetPixelAddress(i, j);
ptr[0] = (ptr[0] * ptr[3]) / 255;
ptr[1] = (ptr[1] * ptr[3]) / 255;
ptr[2] = (ptr[2] * ptr[3]) / 255;
}
}
在AlphaBlend
行之前我所获得的仍然不尽如人意:(
那么,我怎样才能得到正确合成的图像呢?
答案 0 :(得分:1)
经过几天的绝望之后,我终于找到http://forums.codeguru.com/showthread.php?420631-setting-CImage-alpha-values&p=1560260#post1560260这个解决方案类似于我尝试的解决方案,但每个像素的增加了127 ,是一件有用的东西,但当时我还没有理解,也没有做过任何努力来理解它。所以在AlphaBlend
行之前现在有:
for (int i = 0; i < imageBar.GetWidth(); i++)
{
for (int j = 0; j < imageBar.GetHeight(); j++)
{
BYTE* ptr = (BYTE*)imageBar.GetPixelAddress(i, j);
ptr[0] = ((ptr[0] * ptr[3]) + 127) / 255;
ptr[1] = ((ptr[1] * ptr[3]) + 127) / 255;
ptr[2] = ((ptr[2] * ptr[3]) + 127) / 255;
}
}
现在显示的图像组合得很好。