Discussion:
wrong alpha blending with CImage::AlphaBlend() & *.png
(too old to reply)
thomas rehaag
2009-02-27 12:05:56 UTC
Permalink
Hi,

I use the CImage class to load PNG file and do the alpha blending in a
dialog's OnPaint:

CImage m_imgTest;//in the header file

m_imgTest.Load(_T("test.png"));//in OnInitDialog

//In OnPaint:
CPaintDC dc(this);
m_imgBack.BitBlt((HDC)dc,0,0);//an other image as background
if(!m_imgTest.IsNull())
m_imgTest.AlphaBlend((HDC)dc,5,164);

Somehow the alpha blendig works - I can see the background throug some
parts of my test.png and completely transparent parts of test.png
ain't visible at all.
But there must be something wrong with the alpha function or the alpha
data: parts with a very low alpha are displayed as if they had a high
alpha.
I put the same pictures as back- and foreground into an html file and
started it in IExplore & FireFox. Both programs deliver alpha blending
as expected.

What am I doing wrong?

Best Regards & thanks in advance,

Thomas
thomas rehaag
2009-02-27 16:58:56 UTC
Permalink
Problem solved. CImage::AlphaBlend() works fine with premultiplied
colour data.
Does anybody know if this is documented somewhere?

I overwrote CImage::Load() and now everything works fine:


HRESULT CImg::Load(LPCTSTR pszFileName, bool bPreMultiply)
{
HRESULT retRes = CImage::Load(pszFileName);
if(!IsNull() && bPreMultiply)
{
unsigned char * pCol = 0;
long lW = GetWidth();
long lH = GetHeight();
for(long ixy = 0; ixy < lH; ixy ++)
{
for(long ixx = 0; ixx < lW; ixx ++)
{
pCol = (unsigned char *)GetPixelAddress(ixx,ixy);
unsigned char alpha = pCol[3];
if(alpha < 255)
{
pCol[0] = ((pCol[0] * alpha) + 127) / 255;
pCol[1] = ((pCol[1] * alpha) + 127) / 255;
pCol[2] = ((pCol[2] * alpha) + 127) / 255;
}
}
}
}
return retRes;
}
m***@gmail.com
2014-06-03 18:18:46 UTC
Permalink
Post by thomas rehaag
Problem solved. CImage::AlphaBlend() works fine with premultiplied
colour data.
Does anybody know if this is documented somewhere?
HRESULT CImg::Load(LPCTSTR pszFileName, bool bPreMultiply)
{
HRESULT retRes = CImage::Load(pszFileName);
if(!IsNull() && bPreMultiply)
{
unsigned char * pCol = 0;
long lW = GetWidth();
long lH = GetHeight();
for(long ixy = 0; ixy < lH; ixy ++)
{
for(long ixx = 0; ixx < lW; ixx ++)
{
pCol = (unsigned char *)GetPixelAddress(ixx,ixy);
unsigned char alpha = pCol[3];
if(alpha < 255)
{
pCol[0] = ((pCol[0] * alpha) + 127) / 255;
pCol[1] = ((pCol[1] * alpha) + 127) / 255;
pCol[2] = ((pCol[2] * alpha) + 127) / 255;
}
}
}
}
return retRes;
}
Thank you! I was having the exact same issue, and your solution solved my problem perfectly! Very strange blending artifacts were appearing, but now they are gone entirely. Something must be wrong with the math/rounding in the original code.
Loading...