VC数字图像处理编程讲座之一 联系客服

发布时间 : 星期日 文章VC数字图像处理编程讲座之一更新完毕开始阅读6a20e79951e79b8968022653

>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);

pDoc->m_hDIB =hdib//将处理过的图像数据写回pDoc中的图像缓冲区; GlobalUnlock((HGLOBAL)hdib);//解锁、释放缓冲区; GlobalUnlock((HGLOBAL)data1handle);

GlobalFree((HGLOBAL)hdib);

GlobalFree((HGLOBAL)data1handle); Invalidate(TRUE);//显示图像 }

3.图像的旋转

根据图像像素的位置来调节该位置的灰度可以实现许多显示的特效,例如图像的镜像、翻转等。灰度图像旋转就是根据这一个思想实现的,它是指把定义的图像绕某一点以逆时针或顺时针方向旋转一定的角度,通常是指绕图像的中心以逆时针方向旋转。首先根据旋转的角度、图像对角线的长度计算旋转后的图像的最大宽度、高度,根据旋转后图象最大的宽度、高度生成新的缓冲区,假设图像的左上角为(left, top),右下角为(right, bottom),则图像上任意点(x, y)绕其中心(xcenter, ycenter)逆时针旋转angle角度后,新的坐标位置(x1, y1)的计算公式为:

xcenter = (width+1)/2+left; ycenter = (height+1)/2+top;

x1 = (x-xcenter) cosθ - (y - ycenter) sinθ+xcenter; y1 = (x-xcenter) sinθ+ (y- ycenter) cosθ+ ycenter;

与图像的镜像变换相类似,下一步就是把原图中的(x,y)处象素的灰度值读入新缓冲区的(x1,y1)点处。注意在新缓冲区中与原图没有对应的象素点的值用白色或指定的灰度代替。

中国图象图形网 www.image2003.com

二、图像的分块显示和清除

1. 图像的扫描显示和清除

扫描显示图像是最基本的特效显示方法,它表现为图像一行行(或一列列)地显示出来或从屏幕上清除掉,有种大戏院种的拉幕效果。根据扫描的方向的不同,可以分为上、下、左、右、水平平分和垂直平分等六种扫描。这里以向下移动为例,分别介绍显示和清除的实现。其余的扫描效果可以依次类推。向下扫描显示的实现方法是:从图像的底部开始将图像一行一行的复制到目标区域的顶部。每复制一行后,复制的行数便要增加一行,并加上一些延迟;向下移动清除的实现方法是图像向下移动显示,并在显示区域的上部画不断增高的矩形。

1)扫描显示的代码:

CdibView::OnImageDownScan() {

CDibDoc *pDoc=GetDocument(); HDIB hdib;

CClientDC pDC(this);

hdib=pDoc->m_hDIB;//获取图像数据句柄;

BITMAPINFOHEADER *lpDIBHdr;//位图信息头结构指针; 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++)

{ //每次循环显示图象的\到\行数据;

SetDIBitsToDevice (hDC,0,0,lpDIBHdr->biWidth, lpDIBHdr->biHeight, 0, 0,0, i,

lpDIBBits,(LPBITMAPINFO)lpDIBHdr, DIB_RGB_COLORS );

中国图象图形网 www.image2003.com

DelayTime(50);//延迟; }

GlobalUnlock(hdib); return; }

2)清除代码:

.......................................//由于篇幅的限制,省略了与上面的相同代码 Cbrush brush(crWhite);//定义一个\白色\的刷子; Cbrush *oldbrush=pDC->SelectObject(&brush); for(int i=0;i < lpDIBHdr->biHeight ;i++)

{//每次循环将目标区域中的\到\行刷成\白色\;

pDC->Rectangle(0,0,lpDIBHdr->biWidth,lpDIBHdr->biHeight); DelayTime(50); }

.......................................

2. 百页窗效果

所谓百页窗显示效果,就如同关闭和开启百页窗一样,图像被分为一条条或一列列地分别显示或清除掉,根据显示时以行或列为单位可以将该效果分为垂直或水平两种方式。以垂直百页窗为例来说明如何实现这种特效显示。实现垂直百页窗显示时,需要将图像垂直等分为n部分由上向下扫描显示,其中每一部分包括m个条、这个n可以根据具体应用时的需要来决定、m既为图像的高度除n。扫描显示时,依照差值进行扫描显示,即第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;k

{ //每次循环依次显示图像中的k-1、k*m-1、...k*n-1行;

中国图象图形网 www.image2003.com

StretchDIBits (hDC,0,4*k+l-1,lpDIBHdr->biWidth,1, 0, lpDIBHdr->biHeight-4*k-l+1,lpDIBHdr->biWidth,1, lpDIBBits,(LPBITMAPINFO)lpDIBHdr, DIB_RGB_COLORS,

SRCCOPY);//juanlianxiaoguo

DelayTime(50); }

.......................................

3.栅条显示特效

栅条特效是移动特效的复杂组合,可以分为垂直栅条和水平栅条两类。它的基本思想是将图像分为垂直或水平的的小条,奇数条向上或向左显示/清除,偶数条向下或向右显示/清除。当然也可以规定进行相反的方向显示/清除。下面的代码是实现垂直栅条的例子:

....................................... int m=8;

for(int i=0;i<=lpDIBHdr->biHeight;i++) for(int j=0;j<=lpDIBHdr->biWidth;j+=m) {//向下显示偶数条;

StretchDIBits (hDC,j,0,m,i,j,lpDIBHdr->biHeight-i, m,i,

lpDIBBits,(LPBITMAPINFO)lpDIBHdr, DIB_RGB_COLORS,

SRCCOPY);//juanlianxiaoguo j=j+m;

//向上显示奇数条;

StretchDIBits (hDC,j,lpDIBHdr->biHeight-i,m,i,j,0, m,i,

lpDIBBits,(LPBITMAPINFO)lpDIBHdr, DIB_RGB_COLORS, SRCCOPY);// DelayTime(20);

}.......................................

中国图象图形网 www.image2003.com