使用CImage显示透明的PNG图片
2011-11-25 17:39
369 查看
CImage 的AlphaBlend
函数可以显示半透明或透明的图片,
但是当使用这个函数显示PNG
图片时,
经常会发现PNG
图片的背景没有透明,
而是被显示为白色.
在网上多处搜索都没有找到原因,
只能自己动手了.
通过调试代码可以发现,CImage
的AlphaBlend
函数内部调用的是全局的Window API
函数:
AlphaBlend(HDC hdcDest,
int nXOriginDest,
int nYOriginDest,
int nWidthDest,
int hHeightDest,
HDC hdcSrc,
int nXOriginSrc,
int nYOriginSrc,
int nWidthSrc,
int nHeightSrc,
BLENDFUNCTION blendFunction)
;
CImage
类在调用这个函数时,
将自己的内部DC
传递给hdcSrc,
将目标DC
传递给hdcDest.MSDN
详细描述这个函数的最后一个参数BLENDFUNCTION blendFunction.
BLENDFUNCTION
定义如下:
typedef struct _BLENDFUNCTION {
BYTE
BlendOp;
BYTE
BlendFlags;
BYTE
SourceConstantAlpha;
BYTE
AlphaFormat;
}BLENDFUNCTION, *PBLENDFUNCTION, *LPBLENDFUNCTION;
BlendOp 总是为AC_SRC_OVER;BlendFlags
为保留项,
必须为0;SourceConstantAlpha
是图片整体的不透明度,
如果要使用图片像素自身的Alpha
值,
则要将这个参数设置为255;
最后一个参数,
如果使用SourceConstantAlpha
作为描画图片的整体不透明度,
则为设置为0,
如果使用图片像素自身的Alpha
值,
则设置为AC_SRC_ALPHA.
我们在描画带有透明效果的PNG
图片时,
要使用图片像素自身的Alpha
值,
所以要将SourceConstantAlpha
设置为255,
将AlphaFormat
设置为AC_SRC_ALPHA.MSDN
对这种情况下颜色混合的计算方法作了描述,
如下:
Src 是指我们要描画的图片,Dst
是指目标DC
的上下文,Src.Alpha
应该不是像素的Alpha
值,
而应该是Alpha/255;
按照这个公式,
我们可以举个例子计算一下:Src
上一个像素为RGB(255, 255, 255),Alpha
值为0,
与之混合的Dst
上相应像素为RGB(128, 128, 128),
混合后得出的结果为:
R = 255 + (1 - 0 / 255) * 128;
G = 255 + (1 - 0 / 255) * 128;
B = 255 + (1 - 0 / 255) * 128;
计算结果大于255,函数内部自动将其设置为255,最后为RGB(255, 255, 255),
仍然为白色.
而当Src
中像素的颜色为RGB(0, 0, 0),
则结果为Dst
的颜色RGB(128, 128, 128),
实现了透明效果.
按照这个公式计算,
很多颜色的半透明或透明效果都无法实现.
参考MSDN
上在SourceConstantAlpha
不等于255
时的混合计算公式,
我们可以将公式修改为
按照这个公式计算,
我们上面例子的结果为RGB(128, 128, 128),
可以实现透明效果.
根据以上分析,
我们只用修改CImage
中像素的颜色,
就可以实现透明与半透明的效果了,
代码如下:
void CSample::Draw(CDC* pDC, int iX, int iY)
{
//m_stImage 为CImage
的对象
for(int i = 0; i < m_stImage.GetWidth(); ++i)
{
for(int j = 0; j < m_stImage.GetHeight(); ++j
{
unsigned char* pucColor = m_stImage.GetPixelAddress(i , j);
pucColor[0] = pucColor[0] * pucColor[3] / 255;
pucColor[1] = pucColor[1] * pucColor[3] / 255;
pucColor[2] = pucColor[2] * pucColor[3] / 255;
}
}
m_stImage.AlphaBlend(pDC->m_hDC, iX, iY);
}
函数可以显示半透明或透明的图片,
但是当使用这个函数显示PNG
图片时,
经常会发现PNG
图片的背景没有透明,
而是被显示为白色.
在网上多处搜索都没有找到原因,
只能自己动手了.
通过调试代码可以发现,CImage
的AlphaBlend
函数内部调用的是全局的Window API
函数:
AlphaBlend(HDC hdcDest,
int nXOriginDest,
int nYOriginDest,
int nWidthDest,
int hHeightDest,
HDC hdcSrc,
int nXOriginSrc,
int nYOriginSrc,
int nWidthSrc,
int nHeightSrc,
BLENDFUNCTION blendFunction)
;
CImage
类在调用这个函数时,
将自己的内部DC
传递给hdcSrc,
将目标DC
传递给hdcDest.MSDN
详细描述这个函数的最后一个参数BLENDFUNCTION blendFunction.
BLENDFUNCTION
定义如下:
typedef struct _BLENDFUNCTION {
BYTE
BlendOp;
BYTE
BlendFlags;
BYTE
SourceConstantAlpha;
BYTE
AlphaFormat;
}BLENDFUNCTION, *PBLENDFUNCTION, *LPBLENDFUNCTION;
BlendOp 总是为AC_SRC_OVER;BlendFlags
为保留项,
必须为0;SourceConstantAlpha
是图片整体的不透明度,
如果要使用图片像素自身的Alpha
值,
则要将这个参数设置为255;
最后一个参数,
如果使用SourceConstantAlpha
作为描画图片的整体不透明度,
则为设置为0,
如果使用图片像素自身的Alpha
值,
则设置为AC_SRC_ALPHA.
我们在描画带有透明效果的PNG
图片时,
要使用图片像素自身的Alpha
值,
所以要将SourceConstantAlpha
设置为255,
将AlphaFormat
设置为AC_SRC_ALPHA.MSDN
对这种情况下颜色混合的计算方法作了描述,
如下:
Dst.Red | = Src.Red | + (1 - Src.Alpha) * Dst.Red |
Dst.Green | = Src.Green | + (1 - Src.Alpha) * Dst.Green |
Dst.Blue | = Src.Blue | + (1 - Src.Alpha) * Dst.Blue |
是指目标DC
的上下文,Src.Alpha
应该不是像素的Alpha
值,
而应该是Alpha/255;
按照这个公式,
我们可以举个例子计算一下:Src
上一个像素为RGB(255, 255, 255),Alpha
值为0,
与之混合的Dst
上相应像素为RGB(128, 128, 128),
混合后得出的结果为:
R = 255 + (1 - 0 / 255) * 128;
G = 255 + (1 - 0 / 255) * 128;
B = 255 + (1 - 0 / 255) * 128;
计算结果大于255,函数内部自动将其设置为255,最后为RGB(255, 255, 255),
仍然为白色.
而当Src
中像素的颜色为RGB(0, 0, 0),
则结果为Dst
的颜色RGB(128, 128, 128),
实现了透明效果.
按照这个公式计算,
很多颜色的半透明或透明效果都无法实现.
参考MSDN
上在SourceConstantAlpha
不等于255
时的混合计算公式,
我们可以将公式修改为
Dst.Red | = Src.Red * Src.Alpha | + (1 - Src.Alpha) * Dst.Red |
Dst.Green | = Src.Green * Src.Alpha | + (1 - Src.Alpha) * Dst.Green |
Dst.Blue | = Src.Blue * Src.Alpha | + (1 - Src.Alpha) * Dst.Blue |
我们上面例子的结果为RGB(128, 128, 128),
可以实现透明效果.
根据以上分析,
我们只用修改CImage
中像素的颜色,
就可以实现透明与半透明的效果了,
代码如下:
void CSample::Draw(CDC* pDC, int iX, int iY)
{
//m_stImage 为CImage
的对象
for(int i = 0; i < m_stImage.GetWidth(); ++i)
{
for(int j = 0; j < m_stImage.GetHeight(); ++j
{
unsigned char* pucColor = m_stImage.GetPixelAddress(i , j);
pucColor[0] = pucColor[0] * pucColor[3] / 255;
pucColor[1] = pucColor[1] * pucColor[3] / 255;
pucColor[2] = pucColor[2] * pucColor[3] / 255;
}
}
m_stImage.AlphaBlend(pDC->m_hDC, iX, iY);
}
相关文章推荐
- 使用CImage显示透明的PNG图片
- (转)使用CImage显示透明的PNG图片
- 使用CImage显示透明的PNG图片
- 使用CImage显示透明的PNG图片
- 利用CImage显示透明PNG图片
- VC++使用CImage PNG转BMP图片透明背景处理
- VC++使用CImage PNG转BMP图片透明背景处理
- OSG中使用png图片显示透明效果
- (转)CImage显示透明背景的PNG图片
- 关于CImage和AlphaBlend的透明PNG图片显示问题
- 利用CImage显示透明PNG图片
- ie6下png图片背景不透明的解决办法使用js实现
- 使用DD_belatedPNG让IE6支持PNG透明图片
- vc++加载透明png图片方法——GDI+和CImage两种
- CImage 对话框初始化时候显示透明 PNG
- java 显示透明背景png图片
- vc++加载透明png图片方法——GDI+和CImage两种
- 用CImage类来显示PNG、JPG等图片
- 解决使用了DD_belatedPNG后,图片显示不全,只显示一部分
- CImage类显示透明PNG