图形擦除是图形特技处理中最为常见的一种,在各种游戏中图形擦除技术有着广泛的应用。图形擦除在本质上是图形的消隐,即在两幅图片之间进行图片的平滑过渡显示。过渡的方式决定了图形擦除的不同视觉效果,其中最为常见的一种就是图片淡入淡出的更新:两幅图片由明到暗、由暗到明的循环交替显示。这种特技效果在编程中的实现,往往是通过DirectX技术实现的:DirectX Transform为我们提供了一个“Microsoft DirectAnimation Control”的类(在注册表中可以找到该类的
注册信息HKEY_CLASS_ROOT\CLSID\{B6FFC24C-7E13-11D0- 9B47-00C04FC2F51D})供调用,以此实现高质量的
图片擦除。不过,对于DirectX编程,大部分的编程爱好者对其
程序框架难以适应,可以说,花在理解DirectX编程上的工夫要远远大于对图形擦除技术本身的理解。有没有一种更简单的方法,使用常规的编程方式来实现图形擦除呢?
解决方案
不同于Windows 95中的GUI(图形用户接口),在Windows 98以后的版本中,GUI增加了对Alpha Blending(通道混合)的支持,Alpha Blending在概念上最为明显的就是对“通道”的应用。熟悉图形处理的朋友对“通道”这个概念并不会感到陌生, Alpha通道是用来表示数字图像的透明度,改变各种通道的特性,就相当于改变各种基本颜色的浓度。通常情况下,Alpha通道使用8位(Byte)二进制数,可以表示256级灰度,即256级的透明度。假设我们想要在目标区(Dst)里显示一个像素(Src:Alpha通道值为Src.Alpha),并且要求系统进行“通道合成”运算,那么,进行合成运算的具体公式为:
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
从上面的公式可以看出,在进行合成运算之后,更新显示后的目标区域颜色值(RGB)并不完全是源位图的RGB值的拷贝,而是源位图和目标区域进行了“合成”之后的RGB值。和BitBlt函数的像素运算不同,Alpha Blending强调的是源位图的透明度,正是利用这样一种合成运算,我们能够达到图像“透明”的效果。
在VC中,系统提供了AlphaBlend函数来实现位图的通道合成运算,AlphaBlend 函数主要用来显示透明或半透明的位图,其调用格式如下:
BOOL AlphaBlend(
HDC hdcDest,
// 目标设备环境句柄
int nXOriginDest,
// 目标坐标x
int nYOriginDest,
// 目标坐标y
int nWidthDest,
// 目标宽度
int nHeightDest,
//目标高度
HDC hdcSrc,
//源设备环境句柄
int nXOriginSrc,
// 源坐标x
int nYOriginSrc,
// 源坐标y
int nWidthSrc,
//源宽度
int nHeightSrc,
//源高度
BLENDFUNCTION blendFunction
// 合成方式具体数据结构
);
BLENDFUNCTION定义了在源位图和目标位图之间进行合成的具体方式,其具体数据成员及含义如下:
typedef struct _BLENDFUNCTION {
BYTE BlendOp;
BYTE BlendFlags;//必须为零
BYTE SourceConstantAlpha;//位图使用的透明度,0为完全透明、255为正常方式显示
BYTE AlphaFormat;//通常为零,如果源位图为32位真彩色,此值可取为AC_SRC_ALPHA
}BLENDFUNCTION, PBLENDFUNCTION, LPBLENDFUNCTION;
由上面的函数说明我们知道,AlphaBlend能够以特定的透明度来显示一幅位图,那么,如果让AlphaBlend以不同的通道值(从0到255)不断地交替显示两幅
图片,这样就实现了“擦除”效果。
编程实现
了解了上述原理,编程中的具体运用就不会再是难事了,下面以在VC中为例,说明这种图形处理技术在编程中的具体实现。
首先在VC中新建一基于对话框的项目WipeImage。准备好两幅等大的图片(IDB_CROSS、IDB_LANTERN),并将
图片引入资源管理器。在CWipeImageDlg类中加入以下的全局成员变量声明