问题
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
with bar.png
overlapped on its top appears as (Notice the strange white contours on the bar):
but it should be:
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 AlphaBlend
line and what I've got is still not satisfactory :(
So, how can I get a correctly composed image?
回答1:
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.
来源:https://stackoverflow.com/questions/43183799/mfc-cimage-alpha-blending-gone-wrong