第10章? 图象处理编程工具及简单的多媒体编程 在前九章,我们主要是介绍一些数字图象处理的基本原理和算法,很多细节和优化的算法都没有提,所以程序的通用性和效率并不理想。其实有很多优秀的图象处理编程工具,功能强大,速度很快。在实际的编程中,可以调用它们提供的功能来满足我们自己的需求,提高了编程效率和代码的正确性。 在这一章里,将介绍图象处理编程工具LeadTools(OCX)。给出的例程中要用到Visual C++(以下简称VC)的AppWizard和MFC的一些特性,不熟悉C++的读者可以先看看相关的参考书。 10.1 LeadTools 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的信息进行注册,否则用户无法正常运行程序。 10.2 DirectDraw 本节内容主要参考自微软公司的技术文档。 相信游戏玩家对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。 10.3 简单的多媒体编程 前面讲过的内容都是针对数字图象处理这一领域的,现在来谈一些题外的东西,比如说多媒体和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的帮助。 ? The University of Southern California does not screen or control the content on this website and thus does not guarantee the accuracy, integrity, or quality of such content. All content on this website is provided by and is the sole responsibility of the person from which such content originated, and such content does not necessarily reflect the opinions of the University administration or the Board of Trustees