分享
 
 
 

图形擦除技术及编程应用

王朝厨房·作者佚名  2007-01-04
窄屏简体版  字體: |||超大  

图形擦除是图形特技处理中最为常见的一种,在各种游戏中图形擦除技术有着广泛的应用。图形擦除在本质上是图形的消隐,即在两幅图片之间进行图片的平滑过渡显示。过渡的方式决定了图形擦除的不同视觉效果,其中最为常见的一种就是图片淡入淡出的更新:两幅图片由明到暗、由暗到明的循环交替显示。这种特技效果在编程中的实现,往往是通过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类中加入以下的全局成员变量声明:

class CWipeImageDlg : public CDialog

{

// Construction

public:

BLENDFUNCTION m_bf;

CBitmap cross,lantern;

BITMAP bmp;

int bmpWidth,bmpHeight;

CDC dcForCross,dcForLantern;

CDC dc;

BOOL bShowLantern;

………(系统自动生成部分)

};

接着在类向导中加入对WM_INITDIALOG和WM_TIMER消息的响应,其响应代码分别如下:

BOOL CWipeImageDlg::OnInitDialog()

{

………(系统自动生成部分)

// TODO: Add extra initialization here

//初始化全局成员变量

this->bShowLantern=TRUE;

m_bf.BlendOp = AC_SRC_OVER;

m_bf.BlendFlags = 0;

m_bf.SourceConstantAlpha =10;

m_bf.AlphaFormat = 0;

//为节约篇幅,以下代码中略去对操作不成功的处理代码

if(!cross.LoadBitmap(IDB_CROSS))

{

AfxMessageBox("装载位图出错!");

return FALSE;

}

cross.GetBitmap(&&bmp);

lantern.LoadBitmap(IDB_LANTERN);

cross.GetBitmap(&&bmp);

//获得位图的大小信息

bmpWidth=bmp.bmWidth;

bmpHeight=bmp.bmHeight;

dc=this->GetDC();

dcForCross.CreateCompatibleDC(dc);

dcForLantern.CreateCompatibleDC(dc);

//将位图装入设备环境句柄

dcForCross.SelectObject(&&cross);

dcForLantern.SelectObject(&&lantern);

//打开计时器

SetTimer(1000,50,NULL);

return TRUE;

}

void CWipeImageDlg::OnTimer(UINT nIDEvent)

{

//图片透明度每次递增5点

m_bf.SourceConstantAlpha+=5;

//当第一幅图片完全可见之后,显示另一张图片

if(m_bf.SourceConstantAlpha>=200)

{

m_bf.SourceConstantAlpha=10;

//将bShowLantern做为显示标志,确认应该显示哪一张图片

bShowLantern=!bShowLantern;

}

if(bShowLantern)

{

//按透明度递增的方式显示“吊灯”图片 AlphaBlend(dc,0,0,bmpWidth,bmpHeight,dcForLantern,0,0,bmpWidth,bmpHeight,m_bf);

}

else

{

//按透明度递增的方式显示“背景”图片

AlphaBlend(dc,0,0,bmpWidth,bmpHeight,dcForCross,0,0,bmpWidth,bmpHeight,m_bf);

}

CDialog::OnTimer(nIDEvent);

}

编译说明

由于AlphaBlend函数是在“Msimg32.dll”(对应于Msimg32.lib库文件)中定义的。所以,为了避免LNK2001错误,在编译前应该将“Msimg32.lib”文件加入FadeImage项目,然后运行上面的程序,你会发现,在或明或暗之间,你的两幅位图已经出现在屏幕之上了。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有