使用CImage显示透明的图片 cimage保存图片

CImage的AlphaBlend函数可以显示半透明或透明的图片,但是当使用这个函数显示PNG图片时,经常会发现PNG图片的背景没有透明,而是被显示为白色.在网上多处搜索都没有找到原因,只能自己动手了.
通过调试代码可以发现,CImage的AlphaBlend函数内部调用的是全局的Window API函数:
使用CImage显示透明的图片 cimage保存图片
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详细描述这个函数的最后一个参数BLENDFUNCTIONblendFunction.
BLENDFUNCTION定义如下:

typedefstruct _BLENDFUNCTION {
BYTEBlendOp;
BYTEBlendFlags;
BYTESourceConstantAlpha;
BYTEAlphaFormat;
}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

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时的混合计算公式,我们可以将公式修改为


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

  

爱华网本文地址 » http://www.aihuau.com/a/25101010/31575.html

更多阅读

如何做gif格式的图片 动态图片gif格式

如何做gif格式的图片——简介ImageReady是制作像素图的GIF动画的专业软件。ImageReady 2.0 是Photoshop5.0 自带的一个图像处理软件,所以在Photoshop里画好的图片就可以直接进入ImageReady(以下简称IR)去处理。如何做gif格式的图片—

win7系统如何显示隐藏的文件扩展名 win7系统隐藏的文件夹

win7系统如何显示隐藏的文件扩展名——简介有时候我们需要修改文件的扩展名,但是发现直接修改扩展名后不起作用,那是因为你修改的其实只是文件名,而扩展名在win7系统下默认是隐藏的,需要手动调整为显示文件扩展名。win7系统如何显示隐

qq隐藏了让他显示出来的快捷键 右下角qq图标不见了

qq隐藏了让他显示出来的快捷键——简介qq隐藏了之后很多人就找不到显示出来的方法了,尤其是登录了几个QQ的时候总是按CTRL+ALT+Z也没用,下面教大家如何设置快捷键来快速显示已经隐藏的QQ。qq隐藏了让他显示出来的快捷键—

如何使用金山毒霸的免费wifi 金山毒霸wifi共享

如何使用金山毒霸的免费wifi——简介最新版的金山毒霸一键wifi很好用,让我们方便进行热点的创建,让我们更好的使用网络,不怕手机没有流量了。如何使用金山毒霸的免费wifi——方法/步骤如何使用金山毒霸的免费wifi 1、首先,在百度上搜索

声明:《使用CImage显示透明的图片 cimage保存图片》为网友那叫范儿分享!如侵犯到您的合法权益请联系我们删除