版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、VC数字图像处理编程讲座之四 导读在这一讲中作者进一步深入讲解了图像特效的显示技术.BMP图像显示的特效操作上期讲座中我们主要讲述了BMP图像数据的存取、图像的显示和调色板的操作等内容,在上面的学习基础上,我们可以进一步深化,学习并掌握图像特效显示技术。有了这种技术,可以用来在今后的项目开发中美化我们的软件界面,提高软件的视觉效果。在如今的商业软件中,几乎每一幅图像的显示都采用了图像特效显示,例如读者比较熟悉的Windows的屏幕保护程序就采用了各种各样的图像特效显示,使人感到眼花缭乱和耳目一新。专业图像处理软件更是提供了丰富的显示方式供用户使用,可以方便的在程序中实现图像的特效显示,如Pho
2、toShop 、Authorware等。本节主要介绍如何实现图像的浮雕、雕刻、百页窗、旋转、扫描、栅条、马赛克、和渐显渐隐显示等效果。通过这期讲座的学习,读者朋友们也可以自己动手制作拥有特效显示效果的软件了。 图像的显示我们讲过主要有BitBlt()、SetDIBitsToDevice()和StretchDIBits()等函数。需要读者注意的是,在特效显示时,并不是每个显示函数都适宜,BitBlt()函数主要是用来显示设备无关位图(DDB),后两个函数用来显示设备无关位图(DIB)。由于我们讲座里处理的是设备无关位图,所以我们主要关心的是后两个函数的应用,其中SetDIBitsToDevice
3、()使用起来较死板,远不如StretchDIBits()用的灵活,并且对大多数的特效显示无能为力,所以为了实现图像的特效显示效果,需要使用StretchDIBits()函数来显示图像,具体什么原因,我想可能是微软在实现这些函数时使用的方法不同吧。这些函数如何使用,各个参数的含义,可以参考微软的MSDN。 实现图像的特殊效果的显示的基本思路是要么是操作图像的像素,要么是对图像分块按一定的方向或次序,分阶段的显示或擦除对应的图像块。对于第二种显示的思路,其中的要点是:1.划分图像块;2.确定图像块的操作次序;3.显示或清除对应的图像块;4.在两个连续显示的图像块之间插入一个固定的延迟。其中图像块的
4、划分决定了图像的显示方式,图像块的显示顺序决定了显示的方向和细分的依据。不同的效果决定了不同的分块方法和显示次序,我们将在后面的各种特效显示中介绍如何分块和决定次序。为了使图像的显示过程明显的表现出来,实现显示的特效,就需要在图像块的依此显示中插入固定的延迟。也许读者朋友会想到利用sleep()函数或用Settime()来实现延迟,由于Windows是个基于消息的多任务操作系统,这些方法所产生的延迟时间对于图像的显示来说是不精确的,为了实现与机器无关的更精确的时间延迟,可以采用timeGetTime()函数来产生微秒级的延迟。使用这个函数时为了编译不产生错误,要在连接设置中引入“Winmm.l
5、ib”库,并要包含头文件“Mmsystem.h”。这里我们首先给出一个延迟函数,它用来实现固定时间的延迟:void DelayTime(DWORD time)DWORD BeginTime ,EndTime;BeginTime=timeGetTime();/得到当前的系统时间、单位为微秒;doEndTime=TimeGetTime();/再次得到当前的系统时间;while(EndTime-BeginTime) m_hDIB;/拷贝存放已经读取的图像文件数据句柄; lpBi=(LPBITMAPINFOHEADER)GlobalLock(HGLOBAL)hdib);/获取图像信息头pData=(u
6、nsigned char*)FindDIBBits(LPSTR)lpBi);/FindDIBBits是我定义的一个函数、根据图像的结构得到位图的灰度值数据、pDoc-SetModifiedFlag(TRUE);/设置文档修改标志为“真”、为后续的修改存盘作准备;data1handle=GlobalAlloc(GMEM_SHARE,WIDTHBYTES(lpBi-biWidth*8)*lpBi-biHeight);/声明一个缓冲区用来暂存处理后的图像数据;data=(unsigned char*)GlobalLock(HGLOBAL)data1handle);/得到该缓冲区的指针;AfxGetA
7、pp()-BeginWaitCursor();int i,j,buf;for( i=lpBi-biHeight; i=2; i-)/从图像右下角开始对图像的各个像素进行“浮雕”处理; for( j=lpBi-biWidth; j=2; j-) /浮雕处理buf=*(pData+(lpBi-biHeight-i)*WIDTHBYTES(lpBi-biWidth*8)+j)-*(pData+(lpBi-biHeight-i+1)*WIDTHBYTES(lpBi-biWidth*8)+j-1)+128;if(buf255) buf=255;if(bufbiHeight-i)*WIDTHBYTES(l
8、pBi-biWidth*8)+j)=(BYTE)buf;for( j=0; jbiHeight; j+)for( i=0; ibiWidth; i+)/重新写回原始图像的数据缓冲区;*(pData+i*WIDTHBYTES(lpBi-biWidth*8)+j)=*(data+i*WIDTHBYTES(lpBi-biWidth*8)+j);AfxGetApp()-EndWaitCursor();pDoc-m_hDIB =hdib/将处理过的图像数据写回pDoc中的图像缓冲区;GlobalUnlock(HGLOBAL)hdib);/解锁、释放缓冲区;GlobalUnlock(HGLOBAL)dat
9、a1handle);GlobalFree(HGLOBAL)hdib);GlobalFree(HGLOBAL)data1handle);Invalidate(TRUE);/显示图像2雕刻图像 上面讲述了通过求一个像素和它左上方像素之间的差值并加上一个常数的方法生成浮雕效果的灰度图像,雕刻图像与之相反,它是通过取一个像素和它右下方的像素之间的差值并加上一个常数,这里我也取128,经过这样处理,就可以得到雕刻图像,这时候图像的前景凹陷进背景之中。同样需要读者注意的是为了避免重复使用处理过的图像像素,处理图像时要从图像的左上方的像素开始处理。实现代码如下:void CDibView:OnDKImage
10、() / TODO: Add your command handler code here HANDLE data1handle;/这里的内部变量与前面的含义一致、这里不再赘述; LPBITMAPINFOHEADER lpBi; CDibDoc *pDoc=GetDocument(); HDIB hdib; unsigned char *pData; unsigned char *data; hdib=pDoc-m_hDIB;/拷贝图像数据的句柄; lpBi=(LPBITMAPINFOHEADER)GlobalLock(HGLOBAL)hdib); pData=(unsigned char*)
11、FindDIBBits(LPSTR)lpBi); pDoc-SetModifiedFlag(TRUE); data1handle=GlobalAlloc(GMEM_SHARE,WIDTHBYTES(lpBi-biWidth*8)*lpBi-biHeight);/申请缓冲区; data=(unsigned char*)GlobalLock(HGLOBAL)data1handle);/得到新的缓冲去的指针;AfxGetApp()-BeginWaitCursor(); int i,j,buf; for( i=0;ibiHeight-2; i+)/对图像的各个像素循环进行雕刻处理; for( j=0;
12、jbiWidth-2; j+) buf=*(pData+(lpBi-biHeight-i)*WIDTHBYTES(lpBi-biWidth*8)+j)-*(pData+(lpBi-biHeight-i-1)*WIDTHBYTES(lpBi-biWidth*8)+j+1)+128;/“雕刻”处理; if(buf255) buf=255; if(bufbiHeight-i)*WIDTHBYTES(lpBi-biWidth*8)+j)=(BYTE)buf; for( j=0; jbiHeight; j+) for( i=0; ibiWidth; i+)/重新将处理后的图像数据写入原始的图像缓冲区内;
13、*(pData+i*WIDTHBYTES(lpBi-biWidth*8)+j)=*(data+i*WIDTHBYTES(lpBi-biWidth*8)+j);pDoc-m_hDIB =hdib/将处理过的图像数据写回pDoc中的图像缓冲区;GlobalUnlock(HGLOBAL)hdib);/解锁、释放缓冲区;GlobalUnlock(HGLOBAL)data1handle);GlobalFree(HGLOBAL)hdib);GlobalFree(HGLOBAL)data1handle);Invalidate(TRUE);/显示图像3图像的旋转根据图像像素的位置来调节该位置的灰度可以实现许多
14、显示的特效,例如图像的镜像、翻转等。灰度图像旋转就是根据这一个思想实现的,它是指把定义的图像绕某一点以逆时针或顺时针方向旋转一定的角度,通常是指绕图像的中心以逆时针方向旋转。首先根据旋转的角度、图像对角线的长度计算旋转后的图像的最大宽度、高度,根据旋转后图象最大的宽度、高度生成新的缓冲区,假设图像的左上角为(left, top),右下角为(right, bottom),则图像上任意点(x, y)绕其中心(xcenter, ycenter)逆时针旋转angle角度后,新的坐标位置(x1, y1)的计算公式为:xcenter = (width+1)/2+left; ycenter = (heigh
15、t+1)/2+top; x1 = (x-xcenter) cos - (y - ycenter) sin+xcenter; y1 = (x-xcenter) sin+ (y- ycenter) cos+ ycenter;与图像的镜像变换相类似,下一步就是把原图中的(x,y)处象素的灰度值读入新缓冲区的(x1,y1)点处。注意在新缓冲区中与原图没有对应的象素点的值用白色或指定的灰度代替。二、图像的分块显示和清除1 图像的扫描显示和清除 扫描显示图像是最基本的特效显示方法,它表现为图像一行行(或一列列)地显示出来或从屏幕上清除掉,有种大戏院种的拉幕效果。根据扫描的方向的不同,可以分为上、下、左、右
16、、水平平分和垂直平分等六种扫描。这里以向下移动为例,分别介绍显示和清除的实现。其余的扫描效果可以依次类推。向下扫描显示的实现方法是:从图像的底部开始将图像一行一行的复制到目标区域的顶部。每复制一行后,复制的行数便要增加一行,并加上一些延迟;向下移动清除的实现方法是图像向下移动显示,并在显示区域的上部画不断增高的矩形。 1)扫描显示的代码:CdibView:OnImageDownScan()CDibDoc *pDoc=GetDocument();HDIB hdib;CClientDC pDC(this);hdib=pDoc-m_hDIB;/获取图像数据句柄;BITMAPINFOHEADER *l
17、pDIBHdr;/位图信息头结构指针;BYTE *lpDIBBits;/指向位图像素灰度值的指针;HDC hDC=pDC.GetSafeHdc();/获取当前设备上下文的句柄;lpDIBHdr=( BITMAPINFOHEADER *)GlobalLock(hdib);/得到图像的位图头信息;lpDIBBits=(BYTE*)lpDIBHdr+sizeof(BITMAPINFOHEADER)+256*sizeof(RGBQUAD);/获取指向图像像素值;SetStretchBltMode(hDC,COLORONCOLOR);/显示图像;for(int i=0;ibiHeight;i+) /每次
18、循环显示图象的“0”到“i”行数据;SetDIBitsToDevice (hDC,0,0,lpDIBHdr-biWidth, lpDIBHdr-biHeight,0, 0,0, i,lpDIBBits,(LPBITMAPINFO)lpDIBHdr,DIB_RGB_COLORS);DelayTime(50);/延迟;GlobalUnlock(hdib);return;2)清除代码:/由于篇幅的限制,省略了与上面的相同代码Cbrush brush(crWhite);/定义一个“白色”的刷子;Cbrush *oldbrush=pDC-SelectObject(&brush);for(int i=0;
19、i biHeight ;i+)/每次循环将目标区域中的“0”到“i”行刷成“白色”;pDC-Rectangle(0,0,lpDIBHdr-biWidth,lpDIBHdr-biHeight);DelayTime(50);2 百页窗效果所谓百页窗显示效果,就如同关闭和开启百页窗一样,图像被分为一条条或一列列地分别显示或清除掉,根据显示时以行或列为单位可以将该效果分为垂直或水平两种方式。以垂直百页窗为例来说明如何实现这种特效显示。实现垂直百页窗显示时,需要将图像垂直等分为n部分由上向下扫描显示,其中每一部分包括m个条、这个n可以根据具体应用时的需要来决定、m既为图像的高度除n。扫描显示时,依照差值
20、进行扫描显示,即第k次显示k-1、k*m-1、k*n-1条扫描线。同样,垂直百页窗清除的实现与垂直百页窗的显示相似,不同的是将绘制位图换成画矩形而已。在下面的例子中,我将图像的分成8份。int m=8;int n=lpDIBHdr-biHeight/m;/图像的高度能够整除8;for(int l=1;l=m;l+)for(int k=0;kbiWidth,1,0, lpDIBHdr-biHeight-4*k-l+1,lpDIBHdr-biWidth,1,lpDIBBits,(LPBITMAPINFO)lpDIBHdr,DIB_RGB_COLORS,SRCCOPY);/juanlianxiaog
21、uoDelayTime(50); 3.栅条显示特效 栅条特效是移动特效的复杂组合,可以分为垂直栅条和水平栅条两类。它的基本思想是将图像分为垂直或水平的的小条,奇数条向上或向左显示/清除,偶数条向下或向右显示/清除。当然也可以规定进行相反的方向显示/清除。下面的代码是实现垂直栅条的例子:int m=8;for(int i=0;ibiHeight;i+)for(int j=0;jbiWidth;j+=m)/向下显示偶数条;StretchDIBits (hDC,j,0,m,i,j,lpDIBHdr-biHeight-i,m,i,lpDIBBits,(LPBITMAPINFO)lpDIBHdr,DIB
22、_RGB_COLORS,SRCCOPY);/juanlianxiaoguoj=j+m;/向上显示奇数条;StretchDIBits (hDC,j,lpDIBHdr-biHeight-i,m,i,j,0,m,i,lpDIBBits,(LPBITMAPINFO)lpDIBHdr,DIB_RGB_COLORS,SRCCOPY);/DelayTime(20);4.马赛克效果马赛克显示是指图像被分成许多的小块,它们以随机的次序显示出来,直到图像显示完毕。实现马赛克的效果主要解决的问题是如何定义显示随机序列的小方块,这个问题的解决可以在定义过小方块的基础上,用一个数组来记录各个方块的左上角的坐标的位置。显
23、示图像过程中,产生一个随机数来挑选即将显示的小方块,显示后将该方块的位置坐标从数组中剔除。清除过程与之相仿。剔除显示过的方块的位置坐标的方法是将该数组中的最后的一个点的坐标拷贝到当前位置,然后删除数组中的最后点的坐标,经过实现发现这样处理有时显示的图像是不完整的,分析其原因是生成随机数的过程有舍入溢出误差。读者可以采用其它的办法解决这个问题,例如可以生成固定的随机数组或采用一个动态的数组来跟踪未显示的图像方块的坐标等方法。int m,n;int RectSize=60;/方块的宽、高尺寸为60个像素;if(lpDIBHdr-biWidth%RectSize!=0)/得到图像水平方块的个数;m=
24、 lpDIBHdr-biWidth/RectSize+1;elsem= lpDIBHdr-biWidth/RectSize;if(lpDIBHdr-biHeight%RectSize!=0)/得到图像垂直方块的个数;n= lpDIBHdr-biHeight/RectSize+1;elsen=lpDIBHdr-biHeight/RectSize;POINT *point=new POINTn*m;/申请一个数组用来记录各个方块的左上角的坐标;POINT point1;for(int a=0;am;a+)/将各个方块的左上角的坐标记录到数组中;for(int b=0;b=0;k-)int c=(i
25、nt)(double)(m*n)*rand()/fMax);int mx=pointc.x;int my=pointc.y;/显示对应的图像的小块;StretchDIBits (hDC,mx,my,RectSize,RectSize,mx,lpDIBHdr-biHeight-my,RectSize,RectSize,lpDIBBits,(LPBITMAPINFO)lpDIBHdr,DIB_RGB_COLORS,SRCCOPY);pointc.x=pointk.x;pointc.y=pointk.y;DelayTime(50);5图像的淡入淡出效果图像的淡入淡出的显示效果被广泛的应用在多媒体娱乐软件中,是一种特别重要的特效显示方法。淡入就是将显示图像的目标区域由本色逐渐过度的图像中的各个像素点的颜色;淡出就是由显示的图像逐渐过度到目标区域的本色。实现图像的淡入淡出有两种办法:一是均匀的改变图像的调色板中的颜色索引值;另一种方法是改变图像像素的灰度值。第一种方法实现起来比较繁琐,第二种方法就比较简单。下面是我们采用第二种方法实现图像淡入效果的代码:/申请
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年灯湖第三小学面向社会招聘语文、数学临聘教师备考题库及答案详解1套
- 2025年兰州新区石化集团社会招聘15人备考题库参考答案详解
- 数字安徽有限责任公司2026年校园招聘备考题库及1套参考答案详解
- 2025年恒丰银行武汉分行大堂助理岗(劳务派遣制)招聘备考题库有答案详解
- 2025年岑溪市公开招聘专任教师备考题库及一套完整答案详解
- 2025年陇西县马河镇卫生院招聘乡村医生备考题库及一套答案详解
- 2025年黔南州统一面向社会公开招聘乡村医生59人备考题库及答案详解一套
- 2025年苏州深时数字地球研究中心新研项目组招聘科研助理与财务助理备考题库及答案详解1套
- 2025年黄石本地国企招聘工作人员备考题库及一套答案详解
- 理发店门口圆筒原理课件
- 西南名校联盟2026届高三12月“3+3+3”高考备考诊断性联考(一)英语试卷(含答案详解)
- 黄埔区2025年第二次招聘社区专职工作人员备考题库有答案详解
- 2025贵州锦麟化工有限责任公司第三次招聘7人备考笔试题库及答案解析
- 2025广东广州琶洲街道招聘雇员(协管员)5人笔试考试参考试题及答案解析
- 2025国家统计局齐齐哈尔调查队招聘公益性岗位5人笔试考试备考试题及答案解析
- 2025年中医健康管理服务合同模板
- 《红军重走长征路》课件
- 机械加工工艺过程卡片
- 2企业安全生产标准化建设咨询服务方案
- 腰椎骨折课件教学课件
- 大学与青年发展智慧树知到期末考试答案章节答案2024年华侨大学
评论
0/150
提交评论