像特效显示,例如读者比较熟悉的 Windows 的屏幕保护程序就采用了各种各样的图像特效显示,使人感到眼花缭乱和耳目一新。
专业图像处理软件更是提供了丰富的显示方式供用户使用,可以方便的在程序中实现图像的特效显示,如PhotoShop 、Authorware 等。
本节主要介绍如何实现图像的浮雕、雕刻、百页窗、旋转、扫描、栅条、马赛克、和渐显渐隐显示等效果。
通过这期讲座的学习,读者朋友们也可以自己动手制作拥有特效显示效果的软件了。
图像的显示我们讲过主要有 BitBlt、SetDIBitsToDevice和StretchDIBits()等函数。
需要读者注意的是,在特效显示时,并不是每个显示函数都适宜,BitBlt函数主要是用来显示设备相关位图(DDB),SetDIBitsToDevice和 StretchDIBits()两个函数用来显示设备无关位图(DIB)。
由于我们讲座里处理的是设备无关位图,所以我们主要关心的是后两个函数的应用,其中 SetDIBitsToDevice使用起来较死板,远不如StretchDIBits()用的灵活,并且对大多数的特效显示无能为力,所以为了实现图像的特效显示效果,需要使用 StretchDIBits ()函数来显示图像,具体什么原因,我想可能是微软在实现这些函数时使用的方法不同吧。
这些函数如何使用,各个参数的含义,可以参考微软的 MSDN。
实现图像的特殊效果的显示的基本思路是要么是操作图像的像素, 要么是对图像分块按一定的方向或次序, 分阶段的显示或擦除对应的图像块。
对于第二种显示的思路,其中的要点是:1.划分图像块;2.确定图像块的操作次序;3.显示或清除对应的图像块; 4.在两个连续显示的图像块之间插入一个固定的延迟。
其中图像块的划分决定了图像的显示方式, 图像块的显示顺序决定了显示的方向和细分的依据。
不同的效果决定了不同的分块方法和显示次序, 我们将在后面的各种特效显示中介绍如何分块和决定次序。
为了使图像的显示过程明显的表现出来,实现显示的特效,就需要在图像块的依此显示中插入固定的延迟。
也许读者朋友会想到利用 sleep函数或用 Settime()来实现延迟,由于 Windows 是个基于消息的多任务操作系统, 这些方法所产生的延迟时间对于图像的显示来说是不精确的,为了实现与机器无关的更精确的时间延迟,可以采用 timeGetTime函数来产生微秒级的延迟。
使用这个函数时为了编译不产生错误,要在连接设置中引入 Winmm.lib 库,并要包含头文件 Mmsystem.h。
这里我们首先给出一个延迟函数,它用来实现固定时间的延迟:void DelayTimeDWORD timeDWORD BeginTime ,EndTimeBeginTimetimeGetTime//得到当前的系统时间、单位为微秒;doEndTimetimeGetTime//再次得到当前的系统时间;whileEndTime-BeginTime一、操作位图的像素实现显示的特效 我们首先介绍直接操作图像中的像素的灰度值来实现图像显示的特效、这里我们主要介绍如何实现图像的浮雕和雕刻效果。
经常看电视的朋友们不知注意到没有,有些电视连续剧在每集片头或片尾部分都有显示一些特殊效果的图像, 比如前一阵子中央一套放的《长征》和《康熙王朝》,这些特效称为图像的浮雕效果和图像的雕刻效果, 经过这些特效处理后的图像增强了观众们的视觉效果,它们看上去仿佛是使用 3D 技术作的,这也许就是为什么这种技术那么流行的原因吧。
其实, 我们完全可以用一些简单的数字图像处理算法来实现这些看似复杂高深的显示效果。
下面以一个标准的 Lena 灰度图像为原图,给出了处理后的效果图,同时给出了 VC 开发平台上的部分实现源代码。
1.浮雕图像 浮雕图象效果是指图像的前景前向凸出背景。
所谓的浮雕概念是指标绘图像上的一个像素和它左上方的那个像素之间差值的一种处理过程,为了使图像保持一定的亮度并呈现灰色,我在处理过程中为这个差值加了一个数值为 128 的常量。
需要读者注意的是,当设置一个像素值的时候,它和它左上方的像素都要被用到,为了避免用到已经设置过的像素,应该从图像的右下方的像素开始处理,下面是实现的源代码:void CDibView::OnFDImage //产生浮雕效果图函数 HANDLE data1handle//用来存放图像数据的句柄; LPBITMAPINFOHEADER lpBi//图像的信息头结构; CDibDoc pDocGetDocument//得到文挡指针; HDIB hdib//用来存放图像数据的句柄; unsigned char pData//指向原始图像数据的指针; unsigned char data//指向处理后图像数据的指针; hdibpDoc-gtm_hDIB//拷贝存放已经读取的图像文件数据句柄; lpBiLPBITMAPINFOHEADERGlobalLockHGLOBALhdib//获取图像信息头pDataunsigned charFindDIBBitsLPSTRlpBi//FindDIBBits 是我定义的一个函数、根据图像的结构得到位图的灰度值数据、pDoc-gtSetModifiedFlagTRUE//设置文档修改标志为真、为后续的修改存盘作准备;data1handleGlobalAllocGMEM_SHAREWIDTHBYTESlpBi-gtbiWidth8lpBi-gtbiHeight //声明一个缓冲区用来暂存处理后的图像数据;dataunsigned charGlobalLockHGLOBALdata1handle//得到该缓冲区的指针;AfxGetApp-gtBeginWaitCursorint ijbuffor ilpBi-gtbiHeight igt2 i //从图像右下角开始对图像的各个像素进行浮雕处理; for jlpBi-gtbiWidth jgt2 j //浮雕处理bufpDatalpBi-gtbiHeight-iWIDTHBYTESlpBi-gtbiWidth8j-pDatalpBi-gtbiHeight-i1WIDTHBYTESlpBi-gtbiWidth8j-1128ifbufgt255 buf255ifbuflt0buf0datalpBi-gtbiHeight-iWIDTHBYTESlpBi-gtbiWidth8jBYTEbuffor j0 jbiHeight jfor i0 ibiWidth i//重新写回原始图像的数据缓冲区pDataiWIDTHBYTESlpBi-gtbiWidth8jdataiWIDTHBYTESlpBi-gtbiWidth8j AfxGetApp-gtEndWaitCursorpDoc-gtm_hDIB hdib//将处理过的图像数据写回 pDoc 中的图像缓冲区;GlobalUnlockHGLOBALhdib//解锁、释放缓冲区;GlobalUnlockHGLOBALdata1handleGlobalFreeHGLOBALhdibGlobalFreeHGLOBALdata1handleInvalidateTRUE//显示图像2.雕刻图像 上面讲述了通过求一个像素和它左上方像素之间的差值并加上一个常数的方法生成浮雕效果的灰度图像,雕刻图像与之相反,它是通过取一个像素和它右下方的像素之间的差值并加上一个常数,这里我也取 128,经过这样处理,就可以得到雕刻图像,这时候图像的前景凹陷进背景之中。
同样需要读者注意的是为了避免重复使用处理过的图像像素,处理图像时要从图像的左上方的像素开始处理。
实现代码如下:void CDibView::OnDKImage // TOD Add your command handler code here HANDLE data1handle//这里的内部变量与前面的含义一致、这里不再赘述; LPBITMAPINFOHEADER lpBi CDibDoc pDocGetDocument HDIB hdib unsigned char pData unsigned char data hdibpDoc-gtm_hDIB//拷贝图像数据的句柄; lpBiLPBITMAPINFOHEADERGlobalLockHGLOBALhdib pDataunsigned charFindDIBBitsLPSTRlpBi pDoc-gtSetModifiedFlagTRUEdata1handleGlobalAllocGMEM_SHAREWIDTHBYTESlpBi-gtbiWidth8lpBi-gtbiHeight//申请缓冲区; dataunsigned charGlobalLockHGLOBALdata1handle//得到新的缓冲去的指针; AfxGetApp-gtBeginWaitCursor int ijbuf; for i0iltlpBi-gtbiHeight-2 i//对图像的各个像素循环进行雕刻处理; for j0jltlpBi-gtbiWidth-2 j bufpDatalpBi-gtbiHeight-iWIDTHBYTESlpBi-gtbiWidth8j-pDatalpBi-gtbiHeight-i-1WIDTHBYTESlpBi-gtbiWidth8j1128//雕刻处理; ifbufgt255 buf255 ifbuflt0buf0 datalpBi-gtbiHeight-iWIDTHBYTESlpBi-gtbiWidth8jBYTEbuf
上一篇:
解析Visual Studio 2005中QT配置使用
下一篇:
爱情只不过就是,爱与不爱