[原创] 关于 AlphaBlend 函数

来源:互联网 发布:linux退出管理员权限 编辑:程序博客网 时间:2024/05/22 07:47

最近工作中写个工具软件要支持带Alpha通道的PNG图,使用libpng成功读取出了PNG的数据,但是用AlphaBlend进行显示的时候却遇到了问题。

在网上搜索了一下,好像很多前辈使用这个函数都不成功,最后得出的一致结论是AlphaBlend除了SourceConstantAlpha不等于255时可用以外,对带Alpha通道的图是显示不了的,需要自己写Alpha混合算法。因为是搞嵌入式开发,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.Alpha 已经转换成了浮点数,并已除以 255 ,所以取值范围是 0 ~ 1.0 。

我们都知道,正确的Alpha混合的公式是:

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 

由此可知,只要将Src.Red, Src.Green, Src.Blue先乘以Src.Alpha就可以正常进行Alpha混合了。经过试验,证明了这样处理是可以正确进行Alpha混合的。以前混合不正确是由于没有将原图的各个分量先预乘Alpha值,相加后很容易就溢出了,所以混合出来的图除了Alpha值为0的像素可以正常以外,其他像素都偏白。

微软这样处理的目的可能是考虑到Alpha混合的效率,可以在每个像素Alpha混合时少做三次乘法运算,但是他又引入了浮点运算,这点又降低了效率。下面给出我的Alpha混合的公式以供各位参考,以下所有值都是0 ~ 255的8位无符号整数。

Dst.bytRed   = (BYTE)(((int)Src.bytRed * (int)Src.bytAlpha   + (255 - (int)Src.bytAlpha) * (int)Dst.bytRed) / 255);Dst.bytGreen = (BYTE)(((int)Src.bytGreen * (int)Src.bytAlpha + (255 - (int)Src.bytAlpha) * (int)Dst.bytGreen) / 255);Dst.bytBlue  = (BYTE)(((int)Src.bytBlue * (int)Src.bytAlpha  + (255 - (int)Src.bytAlpha) * (int)Dst.bytBlue) / 255);

 

原创粉丝点击