1
votes

I have to present images on a picture control that are a composition of two PNG files, where the top image has transparent pixels on certain positions.

The result should of plotter.png

enter image description here

with bar.png

enter image description here

overlapped on its top appears as (Notice the strange white contours on the bar):

enter image description here

but it should be:

enter image description here

The code I made for it is simple as

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

I have read the MSDN documentation on Alpha Blending a Bitmap and BLENDFUNCTION structure and did some experiments. A detail made me stare on the text I am quoting:

This flag is set when the bitmap has an Alpha channel (that is, per-pixel alpha). Note that the APIs use premultiplied alpha, which means that the red, green and blue channel values in the bitmap must be premultiplied with the alpha channel value. For example, if the alpha channel value is x, the red, green and blue channels must be multiplied by x and divided by 0xff prior to the call.

Alphablend uses premultiplied alpha, which means after loading I have to go to the bitmap and multiply every pixel by its own alpha. So I tried

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;
    }
}

before the AlphaBlendline and what I've got is still not satisfactory :(

So, how can I get a correctly composed image?

2
Make sure that your PNG files are 24-bit as 8-bit PNGs do not support transparency.l33t

2 Answers

1
votes

After some days and night of desperation, I've finally found http://forums.codeguru.com/showthread.php?420631-setting-CImage-alpha-values&p=1560260#post1560260 which a solution similar to what I've tried, but with the addition of 127 to every pixel, which is a thing that worked but I've not understood at the time, nor I had made any effort to understand it yet. So before the AlphaBlend line now there is:

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;
    }
}

and now the displayed image is well composed.

0
votes

I had the same issue and solved it by setting dwFlags = 0 while creating a background image.

background->Create(100, 100, 32, 0);