图像合成是指将一张图像的全部或者局部与另一张图像合并,形成一张新的图像。图像合成的基本形式有2种:
一是按图像源像素本身的不透明度信息合成到目标图片上,这是最简单的形式,像素的合并公式为:
nRGB = (sAlpha * sRGB + (255 - sAlpha) * dRGB) / 255
公式中,nRGB为新的R(G,B)分量,sRGB为源的R(G,B)分量,dRGB为目标的R(G,B)分量,sAlpha为源的不透明度。
二是用指定的不透明度将图像源合成到目标图片上,像素的合并公式为:
nRGB = (Alpha * sAlpha * sRGB + (255 - Alpha * sAlpha) * dRGB) / 255
如果图像源的像素本身不含不透明度信息,则sAlpha = 255:
nRGB = (Alpha * 255 * sRGB + (255 - Alpha * 255) * dRGB) / 255
公式中,Alpha为指定的不透明度,取值范围为0 -- 1,其它同上。
本文将提供上述2种形式的图像合成过程,在实现代码中,为了加快合成速度,采用了像素合并简化公式,如前述的第一种形式公式将简化为:
nRGB = (sAlpha * (sRGB - dRGB) + dRGB * 256) / 256
简化后的公式与原公式有一些微小的误差,不过与人眼的视觉误差相比,可忽略不计。
在实际图像合成过程中,往往会要求将图像源的某个景物合成到目标图像上,这就要借助设置像素关键颜色,甚至羽化等手段将景物从图像源中抠出来,形成上面的2种基本形式后,再进行图像合并。这些已经不是本文讨论的范围。
下面是图像合成的代码:
上面的代码中定义了多个图像合成过程,以满足不同情况、不同对象的图像合并,但图像合成的核心代码还是DoSysthesis过程。为了节省MMX提取图像源的不透明度分量的时间,我采取了预先计算出Alpha掩码表,在合并过程中进行地址引用的方式。Alpha掩码表存放在SysthesisAplhaMask变量中,在单元的初始化代码中对其进行初始化(代码参见《Delphi图像处理 -- 图像像素结构与图像数据转换》第八部分)。
下面是一个图像合成例子:
因手头没有好的图片,故随便找了2张演示了一下,由于图像源比目标图像高一些,所以图像合成过程对图像源进行了裁剪。也可调用拉伸合成过程将图像源进行缩放合成,但那使用的过程并不是本文要介绍的图像合成过程,而是图像缩放过程ImageScale了(见《Delphi图像处理 -- 图像缩放》)。你也可以使用GetSubImageData或者GetClipImageData过程(见《Delphi图像处理 -- 图像像素结构与图像数据转换》),将图像源的任意局部合成到目标图像。例子代码的合成效果图如下:
文章中使用GDI+版本下载地址和说明见《GDI+ for VCL基础 -- GDI+ 与 VCL》。
文章中所用数据类型及一些过程见《Delphi图像处理 -- 数据类型及内部过程》和《Delphi图像处理 -- 图像像素结构与图像数据转换》。
尽管我十分努力,但水平有限,错误在所难免,欢迎指正和指导。邮箱地址:
说明:本文代码于2010.5.20重新修订过。