在前九章,我们主要是介绍一些数字图象处理的基本原理和算法,很多细节和优化的算法都没有提,所以程序的通用性和效率并不理想。其实有很多优秀的图象处理编程工具,功能强大,速度很快。在实际的编程中,可以调用它们提供的功能来满足我们自己的需求,提高了编程效率和代码的正确性。
在这一章里,将介绍图象处理编程工具LeadTools(OCX)。给出的例程中要用到Visual C++(以下简称VC)的AppWizard和MFC的一些特性,不熟悉C++的读者可以先看看相关的参考书。
LeadTools(OCX)是Lead Technologies公司出品的一款功能强大的图象处理编程工具,目前的最新版本是Lead8.0(1997.7.25)。LeadTools实质上是一个OCX控件。先来说说什么是OCX控件?
如果你用过Visual Basic或者Delphi一类的可视化编程工具,那么对控件这个概念一定不会陌生,就是那些工具条上的小按钮,如EditBox,Grid,ImageBox,Timer等等。每个控件都有自己的事件(事件) 、方法(方法)和属性(属性)。使用了控件的编程非常容易。首先,在程序的设计阶段可以设置一些属性,如大小,位置,标题(caption)等等;在程序运行阶段,可以更改这些属性,还可以针对不同的事件,调用不同的方法来实现对该控件的控制。控件就好象一块块的积木,程序要做的事只是将这些积木搭起来。控件的最大好处是可以重复使用,甚至可以在不同的编程语言之间使用,例如你可以在VB中嵌入用VC开发的控件。
控件的本质是微软公司的对象链接和嵌入(OLE)标准。由于它充分利用了面向对象的优点,使得程序效率得到了很大的提高,从而得到了广泛的应用。国外有很多公司就是专门制作各种各样控件的。控件的最早形式是以.VBX的格式出现的,后来变成了.OCX。由于Internet的广泛流行,微软公司推出了ActiveX技术,就是从OLE发展起来的,加入了WWW上的功能。所以目前最流行的是ActiveX控件。
介绍完了OCX控件的概念,下面我们以Lead Version5.1为例,来看看LeadTools究竟有哪些功能?Lead Version5.1可以在正版MicroSoft Visual C++4.1安装光盘中Msdev\samples\ocx\leadtools和Msdev\redist\redist下找到,主要是4个文件, Lead51n.dll,Lead32.ocx,Lead.lic,Ltocx.hlp。如果你想了解LeadTools的最新信息,可以访问以下www网址:http://www.leadtools.com/。
LeadTools主要有以下几大功能:
(1) 对显示设备的全面支持:在显示时,你的程序中无需考虑是哪种显示模式,如16色还是真彩色。LeadTools为你做了所有的事。当然你也可以通过设置参数获得对显示设备更多的控制。你还可以实现自己的调色板。
(2) 支持多种文件格式:表10.1是LeadTools所支持的常用文件格式,其中读表示用LeadTools能打开的文件格式,写表示LeatTools能存成的文件格式:
表10.1 LeadTools支持的常用文件格式
文件格式 |
读(位/象素) |
写(位/象素) |
JFIF:一种常用的Jpeg文件格式,LeadTools支持YUV 4:4:4, 4:2:2, 4:1:1(彩色)YUV 4:0:0(灰度) |
8 (灰度) 24(彩色) |
8 (灰度) 24(彩色) |
JFIF:另一种常用的Jpeg文件格式,LeadTools支持YUV 4:4:4, 4:2:2, 4:1:1(彩色)YUV 4:0:0(灰度) |
8 (灰度) 24(彩色) |
8 (灰度) 24(彩色) |
TIFF:Tiff文件有很多种,LeadTools支持常用的几种 |
1,4,8,16,24,32,还包括另一种颜色表示方法CMYK (LZW压缩) 和 RLE (LZW压缩) |
1, 4, 8, 16, 24 |
MPT:一种多页(MultiPage)的Tiff文件格式,类似于动画Gif。 |
1,4,8,16,24,32,还包括另一种颜色表示方法CMYK (LZW压缩) 和 RLE (LZW压缩) |
1, 4, 8, 16, 24 |
TIFF LZW:采用LZW压缩的Tiff格式,使用时要获得Unisys公司的认可。 |
1, 4, 8, 16, 24, 32 |
1, 8, 16, 24 |
TIFF CCITT Group 3:是一种用于二值黑白图(如传真)的Tiff压缩格式。 |
1 |
1 |
TIFF CCITT Group 4:是一种用于二值黑白图(如传真)的Tiff压缩格式。比Group 3有更高的压缩比。 |
1 |
1 |
TGA (TARGA):Truevision公司的一种文件格式,LeadTools支持所有未压缩的,及用RLE算法压缩的TGA文件。 |
8, 16, 24, 32 |
8, 16, 24, 32 |
GIF:由CompuServe公司定义的一种文件格式,是html语言采用的一种文件格式。要注意的是,使用采用了LZW压缩的Gif文件时,首先要获得Unisys公司的认可。 |
1, 4, 8 |
8 |
Photoshop 3.0 (PSD):Adobe公司PhotoShop3.0所采用的文件格式。 |
1, 8, 24 |
1, 8, 24 |
Windows Bitmap (BMP):由微软公司定义的文件格式。 |
1, 4, 8, 24(未压缩) 1, 4, 8(采用RLE压缩) |
1, 4, 8, 24 |
Windows Metafile (WMF):一种矢量图文件格式。在Word中用到。 |
8, 24 |
8, 24 |
PCX:由Zsoft公司制定的一种文件格式,采用了行程编码。 |
1, 4, 8, 24 |
1, 4, 8, 24 |
SUN Raster (RAS):在Sun UNIX平台上的一种文件格式。 |
1, 4, 8, 24, 32 |
1, 4, 8, 24, 32 |
PCD:柯达公司的PhotoCD 文件格式。要注意的是要有PCDLIB32.DLL这个文件。 |
所有 |
不能写 |
以上只是常用的文件格式,除此以外还有很多其它的文件格式,感兴趣的读者可以参考帮助。
(3) 图象处理:如二值化、平滑、加噪声、增加对比度、色调、饱和度、亮度、Gamma校正、中值滤波、半影调、抖动、橡皮筋、滚动、填充、反色、镜象、马赛克、浮雕、打印、扫描、拷贝、粘贴、裁剪、缩放、截屏、调色板、直方图、有关数据库的操作、还有制作幻灯的功能,如淡入、淡出、卷帘等等、真的很爽。表10.2是Version5.1的所有属性、事件、和方法列表,看看有没有你所需要的功能。以字母顺序排列,其中标[P]的表示只有专业级(Professional)和特殊级(Express)用户才能使用。
表10.2 LeadTools的事件、属性、方法
AboutBox 方法:显示LeadTools的“关于”信息 |
[P] AddNoise 方法:增加随机噪声 |
AutoRepaint 属性:该属性为真时,位图自动重画 |
AutoScroll 属性:该属性为真时,当位图超出窗口范围时,自动出现滚动条 |
AutoSetRects 属性:该属性为真时,自动调整窗口大小 |
[P] Average 方法:平滑 |
BackColor 属性:该属性设置位图的背景色 |
BackErase 属性:该属性为真时,擦除控件的背景 |
[E] BinaryFilter 方法:对黑色对象进行腐蚀或膨胀操作 |
Bitmap 属性:该属性为位图句柄 |
BitmapBits 属性:该属性为每个象素所占的比特数 |
BitmapHeight 属性:该属性为位图的高 |
BitmapPalette 属性:该属性设置调色板中某一项的RGB值 |
BitmapWidth 属性:该属性为位图的宽 |
BitmapXRes 属性:该属性为位图的水平分辨率 |
BitmapYRes 属性:该属性为位图的垂直分辨率 |
[E] BitonalScaling 属性:设置该属性,以增强二值图的显示效果 |
BorderStyle 属性:该属性为0时,控件周围没有边框,为1时有边框 |
[P] Capture 方法:从某一设备上下文指定的矩形区域中获得位图(截屏) |
Click 事件:当用户点击控件时,触发该事件 |
[P] ColorMerge 方法:融合调色板 |
[P] ColorPlanes 属性:该属性为灰度图的调色板数组 |
ColorRes 方法:颜色数转换 |
[P] ColorSeparate 方法:按照调色板将位图分离成一个个的灰度图 |
[P] Combine 方法:将两幅图结合,例如另一幅图是一个边沿检测的滤波器 |
Contrast 方法:增加或减少位图的对比度 |
Copy 方法:将位图拷贝至剪贴板 |
CreateBitmap 方法:对位图初始化并分配内存,但不调入任何数据 |
[P] dbAddNew 方法:为当前记录集增加一个新的空记录 |
[P] dbCanAppend 属性:该属性为真时,表示可以在当前记录集中增加一个记录 |
[P] dbCanRestart 属性:该属性为真时,表示可以从数据库中重建记录集 |
[P] dbCanScroll 属性:该属性为真时,表示数据源支持dbMove方法,可以在记录集中滚 动 |
[P] dbCanUpdate 属性:该属性为真时,表示可以在当前记录集中增加或者更新一个记录 |
[P] dbClose 方法:关闭当前记录集和数据库 |
[P] dbCurrentRecord 属性:记录集中当前记录号 |
[P] dbDelete 方法:删除当前记录 |
[P] dbEdit 方法:为更新当前记录做准备 |
[P] dbEditMode 属性:指示当前记录的编辑模式,如只读,可编辑,可添加 |
[P] dbIsBOF 属性:指示是否到了最前面的记录 |
[P] dbIsDeleted 属性:指示当前记录是否已经被删除 |
[P] dbIsEOF 属性:指示是否到了最后面的记录 |
[P] dbIsOpen 属性:指示是否和一个数据库相连 |
DblClick 事件:当用户双击控件时,触发该事件 |
[P] dbLoadBits 属性:指示从数据库中调入位图时,每个象素所占的比特数,为0时,和原来位图的颜色数保持一致 |
[P] dbLockingMode 属性:当对数据库中已有记录进行更新时,该属性用来指定记录锁定模式 |
[P] dbMove 方法:将当前记录移动到指定位置 |
[P] dbMoveFirst 方法:选定记录集中的第一个记录 |
[P] dbMoveLast 方法:选定记录集中的最后一个记录 |
[P] dbMoveNext 方法:选定记录集中的下一个记录 |
[P] dbMovePrev 方法:选定记录集中的前一个记录 |
[P] dbOpen 方法:在ODBC类型的数据库中打开一个记录集 |
[P] dbRecordCount 属性:指示记录集中的记录数 |
[P] dbRequery 方法:从数据库中重建记录集 |
[P] dbUpdate 方法:更新数据库(当调用dbAddNew或者dbEdit后) |
[E] Deskew 方法:旋转位图使其变正,常用于扫描图象的自动纠斜 |
[E] Despeckle 方法:去除位图中的小斑点 |
DstClipHeight 属性:指定目标剪切矩形的高度 |
DstClipLeft 属性:指定目标剪切矩形的左坐标 |
DstClipTop 属性:指定目标剪切矩形的上坐标 |
DstClipWidth 属性:指定目标剪切矩形的宽度 |
DstHeight 属性:指定目标矩形的高度 |
DstLeft 属性:指定目标矩形的左坐标 |
DstTop 属性:指定目标矩形的上坐标 |
DstWidth 属性:指定目标矩形的宽度 |
[P] Emboss 方法:制作浮雕效果 |
Enabled 属性:指定控件是否使能 |
EnableMethodErrors 属性:指示控件是否导致了系统错误 |
[P] EnableProgressEvent 属性:指示控件是否产生一个进度状态的事件,用来指示已经完成的百分比 |
[P] EnableTwainEvent 属性:为真时,表示支持多页扫描,每扫一页产生一个TwainPage事件 |
Fill 方法:用指定颜色填充位图 |
Flip 方法:上下反转位图 |
ForceRepaint 方法:重画位图 |
ForePalette 属性:当为真时,将使用控件的调色板作为前景调色板 |
[P] GammaCorrect 方法:Gamma校正 |
GetBitmapDC 方法:获得位图的设备上下文 |
GetClientDC 方法:获得控件客户区的设备上下文 |
[P] GetDDB 方法:从控件位图中获得设备相关位图 |
[P] GetDIB 方法:从控件位图中获得设备无关位图 |
GetFileInfo 方法:获得指定文件的信息 |
[P] GetHistogram 方法:获得颜色直方图 |
GetPalette 方法:获得调色板 |
[P] GetPicture 方法:返回一个Picture的对象,是位图的一个拷贝 |
Grayscale 方法:将彩色图转成256级灰度图 |
Halftone 方法:半影调效果 |
[P] HistoContrast 方法:使用直方图指定中间亮度,用以增加图象的对比度 |
[P] HistoEqualize 方法:直方图均衡化 |
[P] HistogramTable 属性:得到指定强度级别的颜色出现的次数 |
[P] Hue 方法:改变图象色调 |
hWnd 属性:得到控件的窗口句柄 |
InfoBits 属性:得到指定图象文件每个象素所占的比特数 |
InfoCompress 属性:得到指定图象文件所用的压缩方法 |
InfoFormat 属性:得到指定图象文件的格式 |
InfoHeight 属性:得到指定图象文件的高度 |
InfoPage 属性:对于多页图象文件,指示出该页的页号 |
[P] InfoPCDRes 属性:用来指示PhotoCD文件格式的分辨率 |
InfoSizeDisk 属性:得到文件大小 |
InfoSizeMem 属性:得到要调入该文件,其位图所占的内存大小 |
InfoWidth 属性:得到指定图象文件的宽度 |
Intensity 方法:改变图象的亮度 |
[P] IntensityDetect 方法:用来检测指定范围内的颜色 |
Invert 方法:反色,制作底片效果 |
KeyDown 事件:当用户按下键盘时,触发该事件 |
KeyPress 事件:当用户按下并抬起键盘时,触发该事件 |
KeyUp 事件:当用户抬起键盘时,触发该事件 |
Load 方法:调入一个图象文件到位图中 |
[P] LoadStamp 方法:在JFIF或者LEAD CMP压缩文件中调入一幅Thumbnail图象 |
[P] Median 方法:中值滤波 |
[P] Mosaic 方法:马赛克效果 |
MouseDown 事件:当鼠标按钮按下时,触发该事件 |
MouseIcon 属性:用户定制的鼠标光标形状 |
MouseMove 事件:当鼠标移动时,触发该事件 |
MousePointer 属性:已有的鼠标光标形状(如沙漏,箭头等等) |
MouseUp 事件:当鼠标按钮抬起时,触发该事件 |
Paint 事件:控件的某一部分需要重画时,触发该事件 |
PaintDither 属性:指定抖动方法,是顺序的还是误差传递的 |
[P] PaintEffect 属性:指定显示效果,如卷帘,淡入,淡出 |
PaintPalette 属性:当用只能显示256色或更低的设备显示高颜色数位图时,用来指定调色板的模式,是用固定的调色板,还是用最佳调色板 |
[P] PaintWhileLoad 属性:当为真时,调入图象的同时就在屏幕上显示,当为假时,全部调入后才在屏幕上显示 |
Paste 方法:将图象数据从剪切板粘贴到指定的位图 |
[P] PCDRes 属性:指定PCD文件的分辨率 |
[P] Posterize 方法:增加海报效果,即将颜色数重新量化成较少的级别 |
PrintEnd 方法:结束打印工作 |
PrintStart 方法:开始打印工作 |
[P] ProgressStatus 事件:进度事件,用来得到已经完成的百分比 |
ReleaseBitmapDC 方法:释放位图设备上下文 |
ReleaseClientDC 方法:释放客户区设备上下文 |
[P] RemapIntensity 方法:使用一个查找表来改变位图的颜色值 |
[P] RemapTable 属性:RemapIntensity方法中用到的查找表 |
Render 方法:在任何设备上下文中打印或者显示图象 |
Resize 事件:当控件第一次显示或者大小改变时触发该事件 |
Reverse 方法:水平反转位图 |
Rotate 方法:旋转位图 |
RubberBandHeight 属性:橡皮筋的高度 |
RubberBandLeft 属性:橡皮筋的左坐标 |
RubberBandTop 属性:橡皮筋的上坐标 |
RubberBandVisible 属性:为真时,橡皮筋可见 |
RubberBandWidth 属性:橡皮筋的宽度 |
[P] Saturation 方法:改变图象的饱和度 |
Save 方法:将图象存成文件 |
[P] SaveWithStamp 方法:将位图存成包括一幅Thumbnail图象的JPEG或者LEAD CMP文件 |
ScaleHeight 属性:控件客户区高度 |
ScaleLeft 属性:控件客户区左坐标 |
ScaleMode 属性:控件的丈量单位,如厘米,象素,英寸等等 |
ScaleTop 属性:控件客户区上坐标 |
ScaleWidth 属性:控件客户区宽度 |
Scroll 事件:当滚动时,触发该事件 |
[P] SetDDB 方法:将一设备相关位图拷贝,并将该拷贝指派到控件上 |
[P] SetDIB 方法:将一设备无关位图拷贝,并将该拷贝指派到控件上 |
SetDstClipRect 方法:指定目标剪切矩形 |
SetDstRect 方法:指定目标矩形 |
[P] SetPicture 方法:将一Picture对象拷贝,并将该拷贝指派到控件上 |
SetRubberBandRect 方法:指定橡皮筋矩形 |
SetSrcClipRect 方法:指定源剪切矩形 |
SetSrcRect 方法:指定源矩形 |
[P] Sharpen 方法:锐化 |
[P] Shear 方法:错切 |
Size 方法:放缩 |
[P] SpatialFilter 方法:用指定的滤波器处理,如LAPLACE,SOBEL,EMBOSS等等 |
SrcClipHeight 属性:指定源剪切矩形的高度 |
SrcClipLeft 属性:指定源剪切矩形的左坐标 |
SrcClipTop 属性:指定源剪切矩形的上坐标 |
SrcClipWidth 属性:指定源剪切矩形的宽度 |
SrcHeight 属性:指定源矩形的高度 |
SrcLeft 属性:指定源矩形的左坐标 |
SrcTop 属性:指定源矩形的上坐标 |
SrcWidth 属性:指定源矩形的宽度 |
[P] StretchIntensity 方法:对比度扩展 |
Trim 方法:在指定的矩形区域内剪切图象 |
TwainAcquire 方法:扫描(Twain标准) |
[P] TwainPage 事件:当进行多页扫描时,每扫完一页触发该事件(Twain标准) |
TwainSelect 方法:选择扫描仪(Twain标准) |
[P] Underlay 方法:将两幅结合起来,使得一幅图做另一幅图的文理 |
UserPalette 属性:指定调色板中的某一项颜色 |
VersionDate 属性:版本日期 |
VersionLevel 属性:版本级别(EXPRESS 或者PROFESSIONAL) |
VersionMajor 属性:主版本号 |
VersionMinor 属性:副版本号 |
VersionProduct 属性:当前版本的全名 |
VersionTime 属性:版本时间 |
(4) 源代码例子:LeadTools的帮助做的特别好,这一点非常吸引人。每一个事件、方法、属性都有很详细的说明,后面都附有一个详细的例子。而且例子有很多种版本,如VC版、VB版、Delphi版、Access版,这样使用不同编程语言的程序员都能从中获得直接的帮助。
好了,介绍了这么多LeadTools的功能,下面我们给出一个最简单的利用LeadTools例子,其功能是显示任意一幅图(当然是Lead能支持的文件格式),图被缩放成和控件一样大小。
[例子10.1] 用Lead显示一幅图
步骤1:打开VC++5.0,用MFC AppWizard (exe)新建一个Project,起名为TestLead。要注意的是在Step1中,选定"Dialog based",Step2中,选定"ActiveX Controls",其它过程全部采用缺省值。
步骤2:把Lead控件添加到工具条中,方法是:(1)打开Project->Add To Project->Components and Controls菜单(其它的VC版本,如4.0、4.1、4.2,为Insert->Component…菜单),出现对话框,选择“Registered ActiveX Controls”那个目录(其它的VC版本为”OLE Controls”那一页);(2)选中"Lead Std Control"那一项,如图10.1所示。然后按下Insert菜单即可;
图10.1 Lead控件 |
图10.2 工具条 |
(3)如果没有该项,找到lead32.ocx文件所在的目录(一般为95的系统目录),选择该文件,按下Insert按钮即可(其它VC版本的操作方法是:按下Customize菜单,出现一个新的对话框,按下Import菜单,找到lead32.ocx文件所在的目录,选择该文件,按下Import按钮,再按下OK按钮,然后做(2)所做的工作即可)。按下Close按钮,关闭Component对话框。插入该控件后,会出现一个对话框,提示你新增加了两个类:Clead和Cpicture,选择Ok。打开对话框资源,选择ID为IDD_TESTLEAD_DIALOG的对话框,这时可以看到该控件已经添加到工具条中,如图10.2所示。
步骤3:将Lead控件从工具条拖到对话框中,设置好合适的大小,右击该控件,选择Property菜单,设置其ID属性为IDC_LEAD1,删除“TODO: Place form controls on this dialog”的静态文本。
步骤4:按Ctrl+w,出现ClassWizard对话框,选择Member Variables那一页,为该ID添加一个变量m_Lead1,Category为Control,Variable Type为Clead。
步骤5:编辑TestLeadDlg.cpp文件中的OnInitDialog()函数,在 // TODO: Add extra initialization here后加入如下的代码:
m_Lead1.Load(“c:\\test.jpg”,0,0);
m_Lead1.SetAutoScroll(TRUE);
m_Lead1.SetDstRect(0,0,m_Lead1.GetScaleWidth(), m_Lead1.GetScaleHeight());
m_Lead1.SetDstClipRect(0,0,m_Lead1.GetScaleWidth(), m_Lead1.GetScaleHeight());
m_Lead1.SetAutoRepaint(FALSE);
m_Lead1.ForceRepaint();
步骤6:编译运行,结果如图10.3所示。
图10.3 例10.1的运行结果
可以看到,使用了控件的编程是多么的简单。更复杂的应用,读者可以参考帮助来完成,要注意的是,使用了LeadTools的应用程序一定要注意版权问题,另外,程序中如果用到了LeatTools的OCX,在制作安装程序(如用InstallShield)时一定要将OLE的信息进行注册,否则用户无法正常运行程序。
本节内容主要参考自微软公司的技术文档。
相信游戏玩家对DirectX这个词并不陌生。最近有越来越多的游戏用到了DirectX。那么DirectX究竟是什么呢?
在Windows3.x的时代,由于Microsoft提供的Windows API不能对硬件直接操作,使得Windows3.x下的游戏不仅效果差,而且运行速度极慢。而DOS4GW有很多很好的性能,例如:可对硬件直接操作;访问超过16比特大小的内存区;可对保护模式编程等等,使得大部分游戏是在DOS4GW下利用如WATCOMC一类的开发工具编制的,如老版本的《仙剑奇侠传》。为了吸引游戏商到Windows平台上来,Microsoft专门开发了Windows的游戏接口WinG,然而效果并不理想。在推出Windows95之后,Microsoft又开发了该平台的GAME SDK,这就是DirectX。
DirectX是非常成功的,很多优秀的游戏都又从DOS平台移植到Windows95平台,《仙剑奇侠传》出了Win95版本,Red Alert, Diablo,以及最近十分流行的Age of Empire,都用到了DirectX。
DirectX技术的最大特点是能直接对硬件抽象层(HAL)操作,实现视频、声音的输出、网络相互通信,特别能对游戏杆直接编程。与传统的GDI和MCI相比,不仅大大加快了速度,而且大大地提高了游戏的质量,有人甚至已将DirectX称为Windows95的GAME OS。目前的最新版DirectX5.0 SDK包括DirectDraw、DirectSound、DirectPlay、Direct3D、DirectInput、DirectSetup六个部分。其中DirectDraw管理游戏的视频输出,DirectSound管理游戏的声音输出,DirectPlay管理游戏的网络通信,Direct3D管理游戏的三维图形,DirectInput管理游戏的游戏杆控制,DirectSetup管理游戏的安装。
因为本书的题目是图象处理编程,我们这里只介绍DirectDraw的大致原理。有的读者可能会说:“跑题了,图象处理编程和编游戏有什么关系?”其实DirectDraw并不只是用在游戏中,由于它的显示处理速度快,在很多和视频有关的软件中(比如说Mpeg的解码器)都可以用到。
DirectDraw是为速度而设计的,它绕过与Windows的图形设备相连的多个层次,直接与硬件的底层打交道。这很适合游戏编程,因为它着重于快速产生平稳的图形。
但DirectDraw最重要的一点在于它对不同的显示适配器具有一个共同的接口。你不必管你的程序它是否会工作。DirectDraw利用包含在硬件抽象层(HAL)中的信息来决定显示适配器的功能。(HAL是由显示适配器厂商提供的)HAL为不同的硬件厂商和使用.DirectDraw的开发者提供了共同的接口。
然而,DirectDraw并不只限于利用显示适配器的硬件功能。如果你的程序指定了某一种特定的显示适配器,例如XXXX hardware blitter,但用户并没有该硬件,程序就会使用DirectDraw的硬件仿真层(HEL)。在这种情况下,DirectDraw利用内建的硬件仿真来仿真缺少的硬件。
下图一说明了DirectDraw和其他Windows显示构件的联系。
图10.4 DirectDraw和其他Windows显示构件
DirectDraw API由DirectDraw对象组成,它表示具体的显示适配器。另外,DirectDraw API还包括表示surface的DirectDrawSurface对象,表示surface调色板的DirectDrawPalette对象和表示剪接列表的DirectDrawClipper对象。可以用DirectDraw对象来创建DirectDrawSurface和DirectDrawPalette对象。
本节只介绍到这里,目的主要是想说明由于游戏对显示速度的要求非常高,所以DirectDraw是为速度而设计的。如果要编写一个对速度要求很高(如Mpeg的解码器)的图象处理系统中,可以考虑使用DirectDraw。
前面讲过的内容都是针对数字图象处理这一领域的,现在来谈一些题外的东西,比如说多媒体和MPEG。
多媒体这几个字,近年来是非常流行的。它包含的东西也是非常多的,除了文本,静态图象,还包括音频,视频等媒体信息。有时候在程序中加入一小段多媒体的东西,能给你的软件增色不少。
其实编制一个多媒体播放程序非常简单,关键代码不超过10行代码,你相信吗?其实质是MCI。MCI是Media Control Interface(媒体控制接口)的缩写,它提供了一套与设备无关的命令消息和命令字来控制媒体的播放。MCI可以播放的文件类型有AVI,WAV,MIDI,MPEG(如果系统中已经安装了MPEG的驱动程序,如安装XING,ACTIVEMOVIE时带的),JPEG等等。MCI窗口底部有一个播放条,上面有播放/暂停(Play/Pause)按键、有显示播放进度的标尺,还有一个菜单,可调整窗口大小、声音大小,速度快慢等等,就和媒体播放器的界面一样。库VFW32.LIB中提供了MCI的所有功能,编译后生成的是真正的可执行文件,无需附加动态库和控件,如VBX和OCX等。
源代码如下,其中黑体部分为关键代码,可以采用如下的命令行编译:
cl testmci.c user32.lib vfw32.lib
//testmci.c
#include <windows.h>
#include <vfw.h>
void SetClientRect(HWND hwnd, HWND hwndMCI)
{
RECT rect;
GetWindowRect(hwndMCI, &rect);
AdjustWindowRectEx(&rect, GetWindowLong(hwnd, GWL_STYLE), FALSE,
GetWindowLong(hwnd, GWL_EXSTYLE));
MoveWindow(hwnd, rect.left, rect.top, rect.right - rect.left,rect.bottom - rect.top,
TRUE);
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg,WPARAM wParam,
LPARAM lParam)
{
switch(uMsg)
{
case MCIWNDM_NOTIFYPOS:
case MCIWNDM_NOTIFYSIZE:
SetClientRect(hwnd, (HWND)wParam);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine,int nCmdShow)
{
MSG msg;
HWND hwnd;
WNDCLASS wndClass;
if (hPrevInstance == NULL)
{
memset(&wndClass, 0, sizeof(wndClass));
wndClass.style = CS_HREDRAW | CS_VREDRAW;
wndClass.lpfnWndProc = WndProc;
wndClass.hInstance = hInstance;
wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wndClass.lpszClassName = "HELLO";
if (!RegisterClass(&wndClass)) return FALSE;
}
hwnd = CreateWindow("HELLO", "HELLO",
WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
NULL, NULL, hInstance, NULL);
SetClientRect(hwnd, MCIWndCreate(hwnd, hInstance,
WS_VISIBLE|WS_CHILD|
MCIWNDF_SHOWALL|
MCIWNDF_NOTIFYSIZE|
MCIWNDF_NOTIFYPOS, “c:\\test.avi”));
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
while (GetMessage(&msg, NULL, 0, 0))
DispatchMessage(&msg);
return msg.wParam;
}
运行时文件C:\test.avi必须准备好,当然,你可以改成其它的文件名。其运行结果如图10.5所示。
图10.5 TestMCI的运行结果
该程序非常简单,所有的代码加在一起不超过60行,其关键部分只有一个MCIWndCreate函数,细节就不介绍了,有兴趣的读者可以参看VC的帮助。