市场营销VC多媒体编程_第1页
市场营销VC多媒体编程_第2页
市场营销VC多媒体编程_第3页
市场营销VC多媒体编程_第4页
市场营销VC多媒体编程_第5页
已阅读5页,还剩72页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、 HYPERLINK /nicolas16/article/details/一五88688 置顶 VC多媒体编程分类: HYPERLINK /nicolas16/article/category/208295 软件开发 2007-04-28 14:09 14021人阅读 HYPERLINK l comments 评论(8) HYPERLINK javascript:void(0); o 收藏 收藏 HYPERLINK l report o 举报 举报 HYPERLINK /tag/details.html?tag=%e7%bc%96%e7%a8%8b 编程 HYPERLINK /tag/det

2、ails.html?tag=null null HYPERLINK /tag/details.html?tag=microsoft microsoft HYPERLINK /tag/details.html?tag=windows windows HYPERLINK /tag/details.html?tag=gdi%2b gdi+ HYPERLINK /tag/details.html?tag=%e6%96%87%e6%a1%a3 文档-VC多媒体编程-Visual C+中基于多文档视窗模型的重叠图象拼接技术摘要图象拼接是在全景视频系统、地理信息系统等应用中经常遇到的一个问题,本文基于网格匹

3、配的方法对边界部分有重叠的图象提出了一种行之有效的对准算法,并通过平滑因子对图象实现了无缝拼接。并应用文档视窗模型实现了该算法,并完成了位图文件的显示、存储等操作,具有一定的普遍意义。关键词:图象拼接,算法,重叠图象,文档视窗,位图文件,图象显示文章正文一、多文档视窗模型概述MFC的AppWizard可以生成三种类型的应用程序:基于对话框的应用、单文档应用(SDI)和多文档应用(MDI)。三种应用中,以多文档应用(MDI)最为复杂,其功能也最强大。当我们用AppWizard生成一个多文档应用时,系统由CMultiDocTemplate自动生成了一个从Cdocument类继承的文档类,一个从Cv

4、iew类继承的视窗类,一个从CMDIChildWnd类继承的框架类。当我们每次建立一个新的文档时,程序根据文档模板生成一个新实例,这些我们均可不用关心AppWizard已经自动生成了代码。但如果我们要在程序中使用多个不同的文档类时,则需自己建立文档模板并控制文档实例的建立。假设我们要向一基于多文档的工程MDI中增加一Test的文档。具体步骤如下:1、用Clazard建立一个框架类CTestFrame基类选CMDIChildWnd。2、用Clazard建立一个文档类CTestDoc基类选CDocument。3、用Clazard建立一个文档类CTestView基类选CView。4、将三个类的头文件

5、加入应用类CMDIApp中。5、创建新文档模板,在CMDIApp:InitInstance()函数中加入如下代码 CMultiDocTemplate* pDocTemplate; pDocTemplate = new CMultiDocTemplate( IDR_TESTTYPE, RUNTIME_CLASS(CTestDoc), RUNTIME_CLASS(CTestFrame), RUNTIME_CLASS(CTestView); AddDocTemplate(pDocTemplate); 6、定义一菜单项ID号为ID_NEWTEST,利用Clazard将其处理函数加入应用类(或主框架类)

6、,在其处理函数CMDIApp:OnNewtest()函数中加入如下代码POSITION curTemplatePos = GetFirstDocTemplatePosition(); while(curTemplatePos != NULL) /取下一个文档模板指针 CDocTemplate* curTemplate =GetNextDocTemplate(curTemplatePos); CString str; curTemplate-GetDocString(str, CDocTemplate:docName); /取文档名称 if(str = _T(Test) /判断当前文档文档是否T

7、est类 curTemplate-OpenDocumentFile(NULL); /创建新的文档实例 return; 这样我们就建立了一个新的文档类。注意在5中创建文档模板时我们用到了一文档类型资源IDR_TESTTYPE,该资源ID在资源文件中定义如下(未包括图标和菜单的定义):STRINGTABLE PRELOAD DISCARDABLE BEGIN . IDR_TESTTYPE/nTest/nTest/n/n/nMDI.Document/nTest Document END 文档类型标识包括七个子串,包括窗口标题、文档名称、文件扩展名等。在6中curTemplate-GetDocStri

8、ng(str, CDocTemplate:docName);取的就是第二个子串,文档名称。文档建立之后我们就可以对其进行操作了。当然文档类和视窗类,文档类和主窗口类,以及不同文档类之间进行通信也是较为复杂的,并非几句话就能说清楚,如不熟悉文档视窗的读者请参看其它有关资料。二、重叠图象拼接技术1算法思想在实现全景视频(Panoramic Video)系统、地理信息系统(GIS)及其它一些应用的过程中,我们通常会碰到这样的一个问题,就是要把几幅小的图象拼接成一幅大的图象。为了能让计算机自动对准图象我们要求待拼接的图象边界有部分重叠,计算机正是利用这些信息进行匹配对准。匹配算法的总体思想是既要保证对

9、准的精度,又要保证运算量不至过大。这里算法利用了图象的自身特性,既在一般图象中,相邻的象素点的灰度值相差不大。因此,可在第二幅图象的边界取一个网格,然后将网格在第一幅图象上移动,计算所有网格点的两幅图象对应象素点的RGB值的差的平方和。记录最小的值的网格位置,即认为是最佳匹配位置。(如图1)为了减小运算量,我们将匹配分为两个步骤,第一步是粗略匹配,在该阶段网格每次水平或垂直移动一个网格间距。在完成粗略匹配之后,我们在当前最佳匹配点处进行精确匹配,在该阶段以当前最佳匹配点为中心,网格向上下、左右各移动一个小步长。初始步长为粗略拼接时移动步长的一半,即为半个网格间距。不断的与当前最小平方和进行比较

10、,如果比当前值优,就替换当前最佳匹配点。循环进行这个过程每次步长减半,直到水平步长和垂直步长均为0为止。2算法描述procedure ImageMatching 输入FirstImage; 输入SecondImage; /获得两幅图象的大小Height1=GetImageHeight(FirstImage); Height2=GetImageHeight(SecondImage); Width1=GetImageWidth(FirstImage); Width2=GetImageWidth(SecondImage); / 从第二幅图象取网格匹配模板SecondImageGrid = GetSe

11、condImageGrid(SecondImage); / 粗略匹配,网格在第一幅图象中先从左向右移动,再从下到上移动,每次移动一个网格间距,Step_Width 或Step_Height,当网格移出重叠区域后结束y=Heitht1-GridHeight; MinValue = MaxInteger; While ( yHeight1-OverlapNumber)/当网格移出重叠部分后结束 x=Grid_Width/2; /当网格位于第一幅图象的最左边时,A点的横坐标。 While ( x(Width1-Grid_Width/2) ) FirstImageGrid=GetImgaeGrid(F

12、irstImgaeGrid, x, y); differ=CaculateDiff(FirstImgaeGrid, SecondImageGrid);/计算象素值差的平 /方和 if (differ0 & Step_Width0)/当水平步长和垂直步长均减为零时结束 if(Step_Height=0)/当仅有垂直步长减为零时,将其置为1 Step_Height=1; If(Step_Width=0) /当仅有水平步长减为零时,将其置为1 Step_Width=1; temp_x = BestMatch_x; temp_y = BestMatch_y; for ( i= -1; i1; i+)

13、for( j= -1; j1; j+) if (i=0&j!=0)|(i!=0&j=0) FirstImageGrid=GetImgaeGrid(FirstImgaeGrid, temp_x+i*Step_Width, temp_y +j*Step_Height); differ=CaculateDiff(FirstImgaeGrid, SecondImageGrid); if (differ3(1)假设位数组的起始指针为lpStartBits屏幕坐标(x,y)在的象素值的指针可用下式计算。lpBits=lpStartBits + (WidthBytes*(Height-y-1) + x*bi

14、BitCount);(2) 其中WidthBytes为(1)式计算的值,Height为图象的高度。3、不同文档类之间的数据交换的实现不同文档类之间的数据交换我们可以通过应用程序类或主窗口类作为媒介进行。在文档类或视窗类可通过AfxGetApp()或AfxGetMainWnd()获得应用类和主窗口类的指针,在应用类和主窗口类则可以通过获得文档模板来获得文档类的指针来访问文档类的数据。这样我们可以通过应用类或主窗口类的成员变量进行数据交换了。4、图象的平滑连接当找到最佳匹配点后,随后的工作将是把两幅图象合成一幅图象。对于重叠部分,我们如果只是简单的取第一幅图象或第二幅图象的数据,会造成图象的模糊和

15、明显的边界,这是不能容忍的。即使取两幅图象的平均值,效果也不能令人满意。为了能使拼接区域平滑,保证图象质量,我们采用了渐入渐出的方法,即在重叠部分由第一幅图象慢慢过渡到第二幅图象,很自然我们可以想到设一渐变因子为0dget_Width(&hmWidth); pPic-get_Height(&hmHeight); double fX,fY; fX = (double)pDC-GetDeviceCaps(HORZRES)*(double)hmWidth/(double)pDC-GetDeviceCaps(HORZSIZE)*100.0); fY = (double)pDC-GetDeviceCap

16、s(VERTRES)*(double)hmHeight/(double)pDC-GetDeviceCaps(VERTSIZE)*100.0); if(FAILED(pPic-Render(*pDC,0,0,(DWORD)fX,(DWORD)fY,0,hmHeight,hmWidth,-hmHeight,NULL) AfxMessageBox(渲染图像失败!); pPic-Release(); else AfxMessageBox(从流中装载图像失败!); 其中,显示工作主要是由IPicture接口对象的Render函数来完成的,该函数主要用来将图片的指定部分画到指定的设备环境的指定位置。原型如

17、下:HRESULT Render( HDC hdc, /渲染图像用的设备环境句柄long x, /在hdc上的水平坐标long y, /在hdc上的垂直坐标long cx, /图像宽度long cy, /图像高度OLE_XPOS_HIMETRIC xSrc, /在源图像上的水平偏移OLE_YPOS_HIMETRIC ySrc, /在源图像上的垂直偏移OLE_XSIZE_HIMETRIC cxSrc,/在源图像上水平拷贝的数量OLE_YSIZE_HIMETRIC cySrc,/在源图像上垂直拷贝的数量LPCRECT prcWBounds /指向目标图元设备环境句柄的指针); 小结:到此为止,通过

18、上述代码已经能够在程序的客户区内显示JPEG、GIF等标准的图像了,但对于有多帧图片(即有动画)的GIF格式的图像,目前还只能显示第一帧,如要完整的显示GIF 动画的全过程,还需要外部Active X控件的支持。-Visual C+实现Flash动画播放摘要:本文通过在VC中将外格式文件内嵌为VC的内部资源,使其在程序运行过程中从资源动态释放到临时文件,从而实现VC对Flash动画的播放。引言 Flash动画由于可以很方便地把用户的想象通过动画显现出来,使原本只属于专业制作人员的动画制作变的异乎寻常的快捷、方便。由于Flash制作的动画在层次、内容、表现形式等诸多方面均比较出色,因此在网络上得

19、到迅猛的发展,更有不少厂商用Flash在互联网上做起了广告和产品演示,效果丝毫不比视频的差,而体积则要小的多。Flash不仅在网络上有广泛的应用,在普通的应用程序中也可以借助Flash实现一些VC、Delphi等编程语言所难以实现的特效,比如在一些演示版的程序中完全可以将程序运行前的闪屏用Flash来制作。本文下面将通过对内嵌资源的动态释放来实现VC对Flash动画的播放,并给出了部分实现代码。内嵌资源的动态释放 Flash动画在此是作为程序的一个模块,虽然也可以以文件的形式作为一个外部资源来使用,但为了避免因外部模块遗失而造成程序的非正常运行,可将由Flash 5.0预先制作好格式的文件以资

20、源的形式打包到应用程序中去,而在程序运行时再将其从资源恢复到文件,使用完毕再通过程序将其从磁盘删除。在导入资源时由格式文件并非VC的标准资源,所以在导入时需要在Resource type栏指定资源类型,特别需要注意的是在此必须要包含引号。加入到资源后可以通过资源视图看到导入资源是以二进制形式保存的,一但加入就不能再通过资源视图对其进行编辑了。在使用资源前首先要将其动态从应用程序中释放到文件中才可对资源做进一步的使用。可先通过宏MAKEINTRESOURCE()将资源标识号IDR转换成字符串Name,再分别通过FindResource()、LoadResource()函数查找、装载该资源到内存:

21、CString Type=;HRSRC res=FindResource (NULL,Name,Type); HGLOBAL gl=LoadResource (NULL,res); 当资源加载到内存后,还要通过对资源内存的锁定来返回指向资源内存的地址的指针,并籍此实现资源从内存到磁盘的保存,至于存盘的操作则由文件函数CreateFile()、和WriteFile()来完成:LPVOID lp=LockResource(gl); /返回指向资源内存的地址的指针。CString filename=Temp; /保存的临时文件名/ CREATE_ALWAYS为不管文件存不存在都产生新文件。fp= C

22、reateFile(filename ,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,0,NULL); DWORD a; /sizeofResource 得到资源文件的大小if (!WriteFile (fp,lp,SizeofResource (NULL,res),&a,NULL) return false; CloseHandle (fp); /关闭句柄FreeResource (gl); /释放内存通过上述代码,可资源从应用程序中提取并释放到临时文件Temp中,在此后只对此临时文件操作,与程序内嵌资源无关。 Flash动画的播放格式的Flash动画通常主要应用在网

23、页上,也就是说IE浏览器本身可以支持Flash动画的播放。这样就不必再单独编写用于播文件的代码,从而大大减少编程的工作量。在VC + 6.0中新增了一个从CView派生的、用于处理网页的视类CHtmlView,由于该类是以Internet Explorer为后台支持,因此在创建工程时只需在最后一步指定视类从CHtmlView派生就可以使程序不编一行代码而具备IE浏览器的网页显示能力。程序刚生成的时候缺省的连接主页是为微软公司的主页,需要对此修改,使程序在执行时立即显示刚才提取出来的Flash临时文件Temp。显示缺省主页的代码是在视类的初始化函数中进行的:void CEmbedModuleVi

24、ew:OnInitialUpdate() CHtmlView:OnInitialUpdate(); Navigate2(_T(xxmicrosoftx),NULL,NULL); 显然要将Navigate2()函数的第一个参数改成Temp的存放路径。刚才在释放资源到文件时并没有指定绝对路径,因此释放出来的资源文件应当和应用程序处于同一目录。但是在此处如果不写明绝对路径是无法显示该临时文件的。获取该临时文件的绝对路径可用如下方法实现:先获取应用程序本身的绝对路径,然后去处应用程序全名(程序名和扩展名)此时得到的是应用程序和临时文件所处文件夹的路径,最后只需在此基础上加上临时文件的文件名Temp即可

25、得到临时文件的全路径。下面是实现的主要代码:/获取应用程序的全路径char exeFullPathMAX_PATH; GetModuleFileName(NULL,exeFullPath,MAX_PATH); /将其格式化为字符串m_TempFile.Format(%s,exeFullPath); /去掉应用程序的全名(一五为应用程序文件全名的长度)exeFullPathm_TempFile.GetLength()-一五=/; /得到应用程序所在路径m_TempFile.Format(%s,exeFullPath); /得到临时文件的全路径m_TempFile+=Temp; 最后将得到的临时文

26、件的全路径m_TempFile作为参数传递给Navigate2()即可在程序运行时把Flash动画作为主页而显示(如上图所示)。由于临时文件Temp是在程序运行过程中从应用程序的资源中提取出来的,因此在程序退出之前需要将其删除。一般是在消息WM_DESTORY的响应函数里通过DeleteFile()函数来加以实现的。小结本文通过对CHtmlView和内嵌资源的动态释放实现了Flash动画在VC程序中的播放,并对资源的动态释放作了较为清晰的描述。通过类似的方法,可以将动态链接库、HTML文件等程序模块作为资源嵌入其中,在使用时再动态释放到临时文件,这样可有效避免文件模块过多时的杂乱以及程序模块丢

27、失导致程序非正常运行等情况的发生。本文所述程序在Windows 98下,由Microsoft Visual C+ 6.0编译通过。Flash动画由 Macromedia Flash 5.0制作,所需浏览器支持为Internet Explorer 6.0。-用RealPlayer控件制作的播放器本文介绍如何插入RealPlay控件实现媒体文件的播放,代码运行效果图如左:下面简要介绍一下具体实现步骤:一、建立基于对话框的程序二、在对话框内添加RealPlayer G2 control的ActiveX控件(工程-添加工程-compontent and controls-registed Active

28、X controls )。三、在对话框内添加源程序内所示的按钮和静态文本分别用于控制打开播放等控制及显示歌曲信息其ID号如源程序四、用MFC映射各按钮消息void CSunapplerealplayerDlg:OnOpen() char szFileFilter= RM File(*.rm)|*.rm| Mp3 File(*.mp3)|*.mp3| MPEG File(*.mpeg)|*.mpeg| Media File(*.asf)|*.asf| Video File(*.dat)|*.dat| MPGA File(*.mpga)|*.mpga| Wave File(*.wav)|*.wav

29、| AVI File(*.avi)|*.avi| Movie File(*.mov)|*.mov| Mid File(*.mid;*,rmi)|*.mid;*.rmi| Wma File(*.wma)|*.wma| All File(*.*)|*.*|; CFileDialog dlg(TRUE,NULL,NULL,OFN_HIDEREADONLY,szFileFilter); if(dlg.DoModal()=IDOK) CString PathName=dlg.GetPathName(); PathName.MakeUpper(); m_player-SetSource(PathName)

30、; m_player-DoPlay(); SetDlgItemText(IDC_STATIC1,m_player-GetAuthor(); SetDlgItemText(IDC_STATIC2,m_player-GetTitle(); SetDlgItemText(IDC_x,m_player-Getx(); SetDlgItemText(IDC_SOURCE,m_player-GetSource(); void CSunapplerealplayerDlg:OnPlay() SetDlgItemText(IDC_STATIC1,m_player-GetAuthor(); SetDlgItem

31、Text(IDC_STATIC2,m_player-GetTitle(); SetDlgItemText(IDC_x,m_player-Getx(); SetDlgItemText(IDC_SOURCE,m_player-GetSource(); m_player-DoPlay(); UpdateData(false); SetTimer(1,20,NULL); void CSunapplerealplayerDlg:OnTimer(UINT nIDEvent) if(0&isRepeat) m_player-DoPlay(); CDialog:OnTimer(nIDEvent); void

32、CSunapplerealplayerDlg:OnClose() /添加此代码时不要忘了在stdafx.h开头处添加前两行AnimateWindow(GetSafeHwnd(),1000,AW_HIDE|AW_BLEND); KillTimer(0); / /此处采用DestroyWindow关闭窗口/多谢杜修杏老师指点/ this-DestroyWindow(); void CSunapplerealplayerDlg:OnFullscreen() m_player-DoPause(); m_player-SetFullScreen(); m_player-DoPlay(); void CS

33、unapplerealplayerDlg:OnMp3down() ShellExecute(NULL,_T(open),NULL,NULL,TRUE); void CSunapplerealplayerDlg:OnPause() m_player-DoPause(); void CSunapplerealplayerDlg:OnStop() m_player-DoStop(); KillTimer(0); void CSunapplerealplayerDlg:OnRepeat() m_player-SetLoop(true); if(isRepeat) isRepeat=FALSE; Set

34、DlgItemText(IDC_REPEAT,循环); else isRepeat=TRUE; SetDlgItemText(IDC_REPEAT,正常); void CSunapplerealplayerDlg:OnLower() / TOD Add your control notification handler code here short volume=m_player-GetVolume(); m_player-DoPause(); m_player-SetVolume(volume-100); m_player-DoPlay(); void CSunapplerealplaye

35、rDlg:OnUpper() / TOD Add your control notification handler code here short volume=m_player-GetVolume(); m_player-DoPause(); m_player-SetVolume(volume+100); m_player-DoPlay(); void CSunapplerealplayerDlg:OnFloat() /TOD Add your command handler code here ShellExecute(NULL,_T(open),NULL,NULL,TRUE); voi

36、d CSunapplerealplayerDlg:OnPetroleum() / TOD Add your command handler code here ShellExecute(NULL,_T(open),x,NULL,NULL,TRUE); 五、映射WM_CTLCOLOR消息,用于控制文本显示的颜色HBRUSH CSunapplerealplayerDlg:OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) HBRUSH hbr = CDialog:OnCtlColor(pDC, pWnd, nCtlColor); if(nCtlColo

37、r=CTLCOLOR_STATIC) if(pWnd.GetDlgCtrlID()=IDC_VOLUME) pDC.SetTextColor(RGB(165,一八2,222); pDC.SetBkMode(TRANSPARENT); return (HBRUSH) m_brush.GetSafeHandle(); if(pWnd.GetDlgCtrlID()=IDC_STATIC1|pWnd.GetDlgCtrlID()=IDC_STATIC2 |pWnd.GetDlgCtrlID()=IDC_SOURCE|pWnd.GetDlgCtrlID()=IDC_x) pDC.SetTextColor

38、(RGB(0,0,255); pDC.SetBkMode(TRANSPARENT); return (HBRUSH) m_brush.GetSafeHandle(); if(pWnd.GetDlgCtrlID()=IDC_STATIC|pWnd.GetDlgCtrlID()=IDC_INFO) pDC.SetTextColor(RGB(255,0,0); pDC.SetBkMode(TRANSPARENT); return (HBRUSH) m_brush.GetSafeHandle(); / TOD Return a different brush if the default is not

39、 desired return hbr; 六、在APP类里的initInstance()里添加下面函数改变对话框背景。SetDialogBkColor(RGB(206,227,99); 七、为了美观我们的外形可引入CButtonXP类,将个按钮类型设置为CButtonXP 好了,应该大功告成了!调试一下吧!本程序在调试过程中要多谢杜修杏老师的指点-Visual C+编程控制鼠标鼠标是现在计算机的标准配置,很多软件都有控制鼠标的功能,比如,有的保密软件可以使鼠标移动限制在一定范围以内,有的可以模拟鼠标的点击,有的可以使鼠标自己移动。要实现以上的功能,必须使用Windows的API函数。我们以下面

40、的程序例子,来说明如何控制鼠标。我们使用Visual C+6.0来写这个程序。打开Visual C+6.0,使用MFC AppWizard新建1个基于对话框的工程,工程名为Mouse,在对话框上加上2个button控件,一个标题为控制鼠标移动范围,另外1个的标题是释放鼠标在MFC Clazard中添加两个当我们使用鼠标单击这两个控件时响应的函数,标题为控制鼠标移动范围的控件的响应函数代码为: /首先使用GetWindowRect获得这个程序窗口的范围CRect rect;this-GetWindowRect(&rect);/然后使用ClipCursor函数把鼠标控制在这个范围以内,这个函数的功

41、能就是控制鼠标的范围。ClipCursor(&rect);标题为释放鼠标的控件的响应函数代码为: ClipCursor(NULL); 这行代码非常简单,就是使鼠标可以自由移动,不受限制。把以上程序编译好了以后运行,点下控制鼠标移动范围按钮,鼠标就只能在这个窗口的范围以内活动,离不开这个窗口了,点下释放鼠标按钮,鼠标就恢复正常了。知道了如何控制鼠标范围,该讲讲如何移动鼠标了。移动鼠标非常简单,只需要一个API函数SetCursorPos,这个函数有2个参数,第1个参数是屏幕的x坐标,第2个参数是屏幕的y坐标,它可以把鼠标移动到指定的坐标上去。模拟鼠标的点击功能也非常简单,比如模拟点鼠标右键,可以

42、使用下面两行代码: mouse_event(MOUSEEVENTF_RIGHTDOWN,0,0,0,0); mouse_event(MOUSEEVENTF_RIGHTUP,0,0,0,0); mouse_event函数的功能就是模拟鼠标点击,第1行代码是模拟按下鼠标右键,第2行代码是模拟鼠标右键弹起,这两行代码就模拟了1次点击鼠标右键的操作,如果想模拟点鼠标左键的操作,只要以上两行代码中的MOUSEEVENTF_RIGHTDOWN和MOUSEEVENTF_RIGHTUP参数换成MOUSEEVENTF_LEFTDOWN和MOUSEEVENTF_LEFTUP就可以了。鼠标的模拟操作讲完了。以上的程

43、序在Windows98下,使用Visual V+6.0编译成功,调试正常。本期知识点:控制鼠标的API函数。-用VC实现图象渐显和渐隐摘要图象的渐显/渐隐被广泛运用与图象处理和多媒提娱乐软件。本文基于windows的调色板动画和时间码技术设计了通用的图象渐显和渐隐算法,并实现了其visual c+程序编码。关键词渐显、渐隐、调色板、调色板动画、时间码图象的渐显/渐隐是十分重要的图象效果,广泛运用于图象处理和多媒提娱乐软件。渐显/渐隐算法设计的最大困难是速度控制,包括定时和快速改变图象中各象素的颜色。如采用普通的全图扫描算法,则速度较慢,很难真正体现渐显/渐隐效果。利用windows(3.x.9

44、5/98/nt)操作系统特殊的调色板管理和时间码定时机制能设计出有效的图象渐显/渐隐算法。windows提供一种被称为调色板动画(palette animation)的颜色处理技术,它通过快速改变颜色调色板中所选取的表项中的颜色能模拟颜色的变化。设置时间码,定时调用该技术使图象颜色渐变就能实现图象的渐显和渐隐。一、调色板动画在visual c+中实现调色板动画依赖于mfc类库提供的cpalette类和cdc类中的若干成员函数,其基本步骤如下:调用cpalette:createpalette(lplogpalette lplogpalette)函数创建逻辑调色板,注意将参数lplogpalett

45、e所指向的各颜色表项结构的peflags域设置为pc_reserved,以防止其它窗口同该调色板匹配颜色。;调用cdc:selectpalette和cdc:realizepalette函数选择和实现所创建的逻辑调色板;调用cpalette:animatepalette函数改变颜色,实现调色板动画;动画完成后应恢复系统调色板。cpalette:animatepalette是其中最关键的函数,其原型如下:void animatepalette( uint nstartindex, / 起始的表项号uint nnumentries, / 变化的表项数lppaletteentry lppalettec

46、olors ); / 逻辑调色板表项指针lppalettecolors为指向paletteentry结构的指针,其中存储着逻辑调色板将要更新的颜色信息。paletteentry结构定义如下:typedef struct tagpaletteentry / pe byte pered; byte pegreen; byte peblue; byte peflags; paletteentry; pered、pegreen、peblue分别表示逻辑调色板项的r、g、b颜色分量值。peflags 应被置为pc_reserved 。nstartindex为lppalettecolors中将变化的起始表

47、项号,nnumentries 为lppalettecolors中将变化的表项数。二、时间码定时cwnd:settimer函数可设置一个系统时间码,并指定每经过一定的时间间隔使windows系统发送一个wm_timer消息到窗口的消息队列中。窗口在每当接收到相应的wm_timer消息时做一定的处理,便实现了定时处理。通常应在窗口的消息循环中接受和处理wm_timer消息,这样将很难编制通用的定时操作。通用的定时操作应将定时处理封装在一个函数中,而不与其它的代码纠缠在一起。笔者实现这一技术的技巧是,在循环操作中截获窗口消息,如消息为指定的时间码消息,则进行定时处理;否则分发消息给窗口消息处理机制。

48、如果定时操作已结束,则修改循环标志,退出循环。具体的代码如下: / 设置时间码,pwnd为处理定时操作的窗口对象指针pwnd-settimer(0 x100, utimeout, null); / 屏蔽鼠标操作,使定时操作不受影响pwnd-setcapture(); / 开始定时操作bool bdone = false; msg msg; while (! bdone) if (:peekmessage(&msg, null, 0, 0, pm_remove) if (msg.message = wm_timer & msg. wparam = 0 x100) . 定时操作代码. / 如定时操

49、作完成,则设置循环标志,结束操作if (定时操作完成) bdone = true; :translatemessage(&msg); :dispatchmessage(&msg); / 释放鼠标:releasecapture(); / 删除时间码pwnd-killtimer(0 x100); . 函数peekmessage截获窗口消息,translatemessage和dispatchmessage函数解释和分发除指定时间码消息之外的所有消息,以避免丢失消息。三、渐显渐显就是将显示颜色由黑色(rgb(0, 0, 0))逐渐变化为图象各象素的颜色的过程。开始时调用cpalette:getpale

50、tteentries函数保存图象调色板的各逻辑表项信息,然后调用cpalette:setpaletteentries函数将逻辑调色板中各逻辑表项的pered、pegreen、peblue置为0,定时调用cpalette:animatepalette,每次将各逻辑表项的pered、pegreen、peblue值增加一个变化量,直到它们分别等于图象逻辑调色板中各逻辑表项的pered、pegreen、peblue值。下面的函数fadein通过对调色板颜色表项中的各颜色分量值先设为0,然后进行递增,直到所有颜色值都恢复成原调色板中颜色值来实现渐显。/ 图象渐显效果/ 参数:/ pwnd 显示图象的窗口

51、/ ppal 调色板指针/ ndeta 各颜色分量的减小量/ utimeout 时间的变化量void fadein(cwnd *pwnd, cpalette *ppal, int ndeta, uint utimeout) / 保留原来的调色板颜色表项int ntotalcolors = ppal-getentrycount(); paletteentry palettecolors0256; ppal-getpaletteentries(0, ntotalcolors, palettecolors0); / 先将调色板表项中各颜色分量置为0 paletteentry palettecolor

52、s1256; for (int i=0; isetpaletteentries(0, ntotalcolors, palettecolors1);ppal-animatepalette(0, ntotalcolors, palettecolors1);/ 设置时间码pwnd-settimer(0 x100, utimeout, null); / 开始渐显pwnd-setcapture(); bool bdone = false; msg msg; while (! bdone) if (:peekmessage(&msg, null, 0, 0, pm_remove) if (msg.mess

53、age = wm_timer & msg.wparam = 0 x100) cclientdc dc(pwnd); cpalette *poldpal = dc.selectpalette(ppal, false); dc.realizepalette(); / 递增各颜色分量paletteentry palettecolors256; ppal-getpaletteentries(0, ntotalcolors, palettecolors); bool bredzero=false;bool bgreenzero=false; bool bbluezero=false; for (int

54、i=0; intotalcolors; +i) if (palettecolorsi.pered + ndeta palettecolors0i.pered) palettecolorsi.pered += ndeta; bredzero = false; else if (palettecolorsi.pered + 1 palettecolors0i.pered) palettecolorsi.pered+; bredzero = false; else bredzero = true; if (palettecolorsi.pegreen + ndeta palettecolors0i.

55、pegreen) palettecolorsi.pegreen += ndeta; bgreenzero = false; else if (palettecolorsi.pegreen + 1 palettecolors0i.pegreen) palettecolorsi.pegreen+; bgreenzero = false; else bgreenzero = true; if (palettecolorsi.peblue + ndeta palettecolors0i.peblue) palettecolorsi.peblue += ndeta; bbluezero = false;

56、 else if (palettecolorsi.peblue +1 animatepalette(0, ntotalcolors, palettecolors); :translatemessage(&msg); :dispatchmessage(&msg); :releasecapture(); pwnd-killtimer(0 x100); / 恢复原始调色板ppal-setpaletteentries(0, ntotalcolors, palettecolors0); ppal-animatepalette(0, ntotalcolors, palettecolors0); 四、渐隐渐

57、隐就是将显示颜色由图象各象素的颜色逐渐变化为黑色(rgb(0, 0, 0))的过程,即定时调用cpalette:animatepalette,每次将各逻辑表项的pered、pegreen、peblue值减小一个变化量,直到它们都为0。下面的函数fadeout通过对调色板颜色表项中的各颜色分量值进行递减,直到所有颜色值都变成0(即黑色)来实现渐隐。/ 图象渐隐效果/ 参数:/ pwnd 显示图象的窗口/ ppal 调色板指针/ ndeta 各颜色分量的减小量/ utimeout 时间的变化量void fadeout(cwnd *pwnd, cpalette *ppal, int ndeta, u

58、int utimeout) / 保留原来的调色板颜色表项int ntotalcolors = ppal-getentrycount(); paletteentry palettecolors0256; ppal-getpaletteentries(0, ntotalcolors, palettecolors0); / 设置时间码pwnd-settimer(0 x100, utimeout, null); / 开始渐隐pwnd-setcapture(); bool bdone = false; msg msg; while (! bdone) if (:peekmessage(&msg, nul

59、l, 0, 0, pm_remove) if (msg.message = wm_timer & msg.wparam = 0 x100) cclientdc dc(pwnd); cpalette *poldpal = dc.selectpalette(ppal, false); dc.realizepalette(); paletteentry palettecolors256;ppal-getpaletteentries(0, ntotalcolors, palettecolors); bool bredzero=false;bool bgreenzero=false; bool bblu

60、ezero=false; / 递减颜色分量for (int i=0; i ndeta) palettecolorsi.pered -= ndeta; bredzero = false; else if (palettecolorsi.pered 1) palettecolorsi.pered-; bredzero = false; else bredzero = true; if (palettecolorsi.pegreen ndeta) palettecolorsi.pegreen -= ndeta; bgreenzero = false; else if (palettecolorsi.

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论