MFC CImage alpha混合出错

MFC CImage alpha混合出错,image,visual-c++,mfc,png,alphablending,Image,Visual C++,Mfc,Png,Alphablending,我必须在图片控件上显示由两个PNG文件组成的图像,上面的图像在某些位置上有透明像素 结果应该是plotter.png的结果 使用bar.png 顶部重叠显示为(请注意条上奇怪的白色轮廓): 但它应该是: 我为它编写的代码很简单 CImage image; if (FAILED(image.Load(L"plotter.png"))) return false; CImage imageBar; if (FAILED(imageBar.Lo

我必须在图片控件上显示由两个PNG文件组成的图像,上面的图像在某些位置上有透明像素

结果应该是plotter.png的结果

使用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);
我已经阅读了和的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;
    }
}
for(int i=0;i
AlphaBlend
行之前,我得到的仍然不令人满意:(


那么,我怎样才能得到正确的构图呢?

经过几天几夜的绝望,我终于找到了一个类似于我尝试过的解决方案,但在每个像素上增加了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;
    }
}
for(int i=0;i

现在显示的图像合成良好。

请确保您的PNG文件是24位的,因为8位PNG不支持透明度。