[原创]Cardgamevb源码分析之——抠图篇
Cardgamevb源码分析之——抠图篇Cardgamevb是用VB+GDI编写的纸牌游戏,整个程序完全使用Windows GDI API来处理图像,没有任何第三方控件和Dll,对想学习用VB来处理图像的人来说,是一个非常好的入门教材。
先来看看cardgamevb中用到的图片:
在BG目录中有三张图,Bg\bg1.bmp,Bg\bg2.bmp,Bg\bg3.bmp 游戏桌面的背景图片,没什么特殊。
与源代码在同一目录下的图片,则是游戏中用到图片,包括Logo、机器人头像、牌面,值得注意的是790.bmp,sign.bmp,sort.bmp这几张图,是不是觉得画面有些奇怪?
这三张图就是我们今天要讲的“抠图”的源图了。
在程序中显示一张背景透明的图片,我们首先会想到GIF图片,因为在VB支持的图片格式中,只有GIF支持透明背景。我们还得把这张透明背景的GIF图片放到Image控件中才行,因为PictureBox控件本身是不支持透明背景的,也就是说,在PictureBox中被图片挡住的地方,仍然可以看到透明背景后的内容,而窗体上被PictureBox挡住的地方,就看不到这部分的内容了。而Image控件是轻量级控件(所谓轻量级,是指控件本身没有外部文件,不需要引用动态链接库,控件的外观和内容是在程序运行时由系统“画”出来的,这样的控件占用系统资源较少,相应的功能也较弱,对比一下Image控件和PictureBox控件所提供的方法和属性就知道了),轻量级控件有一些限制,没有hwnd属性,无法使用绝大部分API函数对它进行操作,不能置于其它控件的上面(Zorder),只适合用来显示一些静态的文本或图片(Label控件也是轻量级控件),虽然用Image编写简单的纸牌游戏也是可行的,不过这不是我们今天要讨论的内容。
回头来看cardgamevb,它使用的全是BMP图片,仍然达到透明背景的效果,秘诀就在790.bmp,sign.bmp,sort.bmp这几张图片奇怪的画面上,这几张图实际上是分成两部分,一张是包含了要显示的图像,同时把需要设置为透明的区域全部涂成黑色,另一张则相反,把透明区域涂成白色,而需要显示的地方则全部涂成黑色,经过简单的颜色运算,就可以显示一幅透明背景的图片了。
做个测试先:
打开VB,新建一个工程,放两个PictureBox和一个CommandButton,把Picture1的图片设为790.bmp,Picture1的属性设置为:
Picture1.BorderStyle = 0
Picture1.AutoRedraw = True
Picture1.AutoSize = True
在程序中添加如下代码
Private Sub Command1_Click()
Picture2.PaintPicture Picture1.Picture, 0, 0, Picture1.Width, Picture1.Height / 2, _
0, Picture1.Height / 2, Picture1.Width, Picture1.Height / 2, vbSrcAnd
Picture2.PaintPicture Picture1.Picture, 0, 0, Picture1.Width, Picture1.Height / 2, _
0, 0, Picture1.Width, Picture1.Height / 2, vbSrcInvert
End Sub
为了产生明显的效果,你可以给Picture2加一张图片或设置不同的背景色,按F5运行程序,点CommandButton,Picture2是不是多了一个机器人头?
这种效果有点像把机器人头像从Picture1中“抠”出来放到Picture2中,所以被称做“抠图”。
来看看代码,为什么会有种效果
Picture2.PaintPicture Picture1.Picture, 0, 0, Picture1.Width, Picture1.Height / 2, _
0, Picture1.Height / 2, Picture1.Width, Picture1.Height / 2, vbSrcAnd
PaintPicture是PictureBox提供的一个方法,作用是把一个Picture按指定方式、大小、起始位置拷贝到PictureBox指定的区域中,这里,我们用了vbSrcAnd方式,意思是将Picture1.Picture的下半部分与Picture2中相应区域进行And运算后再显示出来。Picture1.Picture的下半部,机器人头部以外的区域为纯白色,它的十六进制值是&HFFFFFF,转换成二进制,就是所有位都是1,我们知道,任何数和1进行And运算,结果都是这个数本身。机器人头部是纯黑色,十六进制值是0,任何数和0进行And运算,结果为0。因此,执行完上面的语句后,Picture2中机器人头部是黑色,而头部以外则是Picture2原来的背景色。
接下来,我们再将Picture1的上半部分以vbSrcInvert的方式拷贝到Picture2中。VbSrcInvert是让源图与目标区域进行Xor运算。同理,任何数和0进行Xor运算,结果都是这个数本身。这时,机器人头部以外是黑色,对应Picture2的背景部分,而Picture2的机器人头部区域是黑色,和源图运算后,就得到我们最终结果。
[此贴子已经被作者于2004-04-15 17:26:56编辑过]