数字图像处理领域的二十四个典型算法.doc_第1页
数字图像处理领域的二十四个典型算法.doc_第2页
数字图像处理领域的二十四个典型算法.doc_第3页
数字图像处理领域的二十四个典型算法.doc_第4页
数字图像处理领域的二十四个典型算法.doc_第5页
已阅读5页,还剩30页未读 继续免费阅读

下载本文档

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

文档简介

数字图像处理领域的二十四个典型算法 2数字图像处理领域的二十四个典型算法(2)2011-04-20 08:52前期回顾:在上一章,数字图像处理领域的二十四个典型算法及vc实现、第一章中,我们介绍和实现了256色转灰度图、Walsh变换、二值化变换、阈值变换、傅立叶变换、离散余弦变换等数字图像处理领域中的6个典型算法。这一篇接上一篇,继续阐述数字图像处理领域的典型算法。注,有兴趣具体深入研究的朋友可参考国内外有关此类图像处理算法的优秀论文。七、高斯平滑算法描述:在图像预处理中,对图像进行平滑,去除噪声,恢复原始图像是一个重要内容。本文设计了一个平滑尺度和模板大小均可以改变的高斯滤波器,用它对多幅加入各种噪声后的图像进行平滑,经过对各个结果图像的对比可知高斯滤波对服从正态分布的噪声去除效果比较好,并且相比各个不同参数,在平滑尺度为2,模板大小为7时效果最佳。程序实现:函数名称:Template:参数:HDIB hDIB-图像的句柄double*tem-指向模板的指针int tem_w-模板的宽度int tem_h-模板的高度double xishu-模板的系数功能:对图像进行模板操作说明:为处理方便起见,模板的宽度和高度都应为奇数HDIB Template(HDIB hDIB,double*tem,int tem_w,int tem_h,double xishu)/统计中间值double sum;/指向图像起始位置的指针BYTE*lpDIB=(BYTE*):GlobalLock(HGLOBAL)hDIB);/指向象素起始位置的指针BYTE*pScrBuff=(BYTE*):FindDIBBits(char*)lpDIB);/获取图像的颜色信息int numColors=(int):DIBNumColors(char*)lpDIB);/如果图像不是256色返回if(numColors!=256)/解除锁定:GlobalUnlock(HGLOBAL)hDIB);/返回return(hDIB);/将指向图像象素起始位置的指针,赋值给指针变量BYTE*oldbuf=pScrBuff;/循环变量int i,j,m,n;int w,h,dw;/获取图像的宽度w=(int):DIBWidth(char*)lpDIB);/获取图像的高度h=(int):DIBHeight(char*)lpDIB);/计算图像每行的字节数dw=(w+3)/4*4;/建立一个和原图像大小相同的25色灰度位图HDIB newhDIB=NewDIB(w,h,8);/指向新的位图的指针BYTE*newlpDIB=(BYTE*):GlobalLock(HGLOBAL)newhDIB);/指向新的位图的象素起始位置的指针BYTE*destBuf=(BYTE*)FindDIBBits(char*)newlpDIB);/将指向新图像象素起始位置的指针,赋值给指针变量BYTE*newbuf=destBuf;/对图像进行扫描/行for(i=0;i h;i+)/列for(j=0;j w;j+)/为统计变量赋初始值sum=0;/对于图像的4个边框的象素保持原灰度不变if(j(tem_w-1)/2)|j(w-(tem_w+1)/2)|i(tem_h-1)/2)|i(h-(tem_h+1)/2)*(newbuf+i*dw+j)=*(oldbuf+i*dw+j);/对于其他的象素进行模板操作else/将点(i,j)点作为模板的中心for(m=i-(tem_h-1)/2);m=i+(tem_h-1)/2);m+)for(n=j-(tem_w-1)/2);n=j+(tem_w-1)/2);n+)/将以点(i,j)为中心,与模板大小相同的范围内的象素与模板对用位置的系数/进行相乘并线形叠加sum+=*(oldbuf+m*dw+n)*tem(m-i+(tem_h-1)/2)*tem_w+n-j+(tem_w-1)/2);/将结果乘上总的模板系数sum=(int)sum*xishu;/计算绝对值sum=fabs(sum);/如果小于0,强制赋值为0 if(sum 0)sum=0;/如果大于255,强制赋值为255 if(sum 255)sum=255;/将计算的结果放到新的位图的相应位置*(newbuf+i*dw+j)=sum;/解除锁定:GlobalUnlock(HGLOBAL)hDIB);/返回新的位图的句柄return(newhDIB);变换效果(图像右边部分即为某一算法的变换效果,下同八、图像平移算法描述:我想,图像平移,就不必过多介绍了。无非就是通过坐标的增或减的变化,来达到图像在屏幕上的左移、右移、上移、下移的效果。程序实现:TranslationDIB-该函数用来水平移动DIB图像。函数不会改变图像的大小,移出的部分图像将截去,空白部分用白色填充。下面的左移,右移,上移,下移,各自都调用了此TranslationDIB函数。/图像平移函数。BOOL WINAPI TranslationDIB(LPSTR lpDIBBits,LONG lWidth,LONG lHeight,LONG lXOffset,LONG lYOffset)/指向源图像的指针LPSTRlpSrc;/指向要复制区域的指针LPSTRlpDst;/指向复制图像的指针LPSTRlpNewDIBBits;HLOCALhNewDIBBits;/象素在新DIB中的坐标LONGi;LONGj;/象素在源DIB中的坐标LONGi0;LONGj0;/图像每行的字节数LONG lLineBytes;/计算图像每行的字节数lLineBytes=WIDTHBYTES(lWidth*8);/暂时分配内存,以保存新图像hNewDIBBits=LocalAlloc(LHND,lLineBytes*lHeight);if(hNewDIBBits=NULL)/分配内存失败return FALSE;/锁定内存lpNewDIBBits=(char*)LocalLock(hNewDIBBits);/每行for(i=0;i lHeight;i+)/每列for(j=0;j lWidth;j+)/指向新DIB第i行,第j个象素的指针/注意由于DIB中图像第一行其实保存在最后一行的位置,因此lpDst/值不是(char*)lpNewDIBBits+lLineBytes*i+j,而是/(char*)lpNewDIBBits+lLineBytes*(lHeight-1-i)+j lpDst=(char*)lpNewDIBBits+lLineBytes*(lHeight-1-i)+j;/计算该象素在源DIB中的坐标i0=i-lXOffset;j0=j-lYOffset;/判断是否在源图范围内if(j0=0)&(j0 lWidth)&(i0=0)&(i0 lHeight)/指向源DIB第i0行,第j0个象素的指针/同样要注意DIB上下倒置的问题lpSrc=(char*)lpDIBBits+lLineBytes*(lHeight-1-i0)+j0;/复制象素*lpDst=*lpSrc;else/对于源图中没有的象素,直接赋值为255*(unsigned char*)lpDst)=255;/复制平移后的图像memcpy(lpDIBBits,lpNewDIBBits,lLineBytes*lHeight);/释放内存LocalUnlock(hNewDIBBits);LocalFree(hNewDIBBits);/返回return TRUE;/向左平移,注:在本程序中,移出去的部分,填充以白色。下同。void CMyDIPView:OnMenuitem32780()/平移位图/获取文档CMyDIPDoc*pDoc=GetDocument();/指向DIB的指针LPSTRlpDIB;/指向DIB象素指针LPSTR lpDIBBits;/锁定DIB lpDIB=(LPSTR):GlobalLock(HGLOBAL)pDoc-GetHDIB();/判断是否是8-bpp位图(这里为了方便,只处理8-bpp位图的平移,其它的可以类推)if(:DIBNumColors(lpDIB)!=256)/提示用户MessageBox(目前只支持256色位图的平移!,系统提示,MB_ICONINFORMATION|MB_OK);/解除锁定:GlobalUnlock(HGLOBAL)pDoc-GetHDIB();/返回return;LONG lXOffset;LONG lYOffset;/平移量lXOffset=-10;lYOffset=0;/更改光标形状BeginWaitCursor();/找到DIB图像象素起始位置lpDIBBits=:FindDIBBits(lpDIB);/调用TranslationDIB()函数平移DIB if(TranslationDIB(lpDIBBits,:DIBWidth(lpDIB),:DIBHeight(lpDIB),lXOffset,lYOffset)/设置脏标记pDoc-SetModifiedFlag(TRUE);/更新视图pDoc-UpdateAllViews(NULL);else/提示用户MessageBox(分配内存失败!,系统提示,MB_ICONINFORMATION|MB_OK);/解除锁定:GlobalUnlock(HGLOBAL)pDoc-GetHDIB();/恢复光标EndWaitCursor();/向右平移void CMyDIPView:OnMenuitem32781()/平移位图/获取文档CMyDIPDoc*pDoc=GetDocument();/指向DIB的指针LPSTRlpDIB;/指向DIB象素指针LPSTR lpDIBBits;/锁定DIB lpDIB=(LPSTR):GlobalLock(HGLOBAL)pDoc-GetHDIB();/判断是否是8-bpp位图(这里为了方便,只处理8-bpp位图的平移,其它的可以类推)if(:DIBNumColors(lpDIB)!=256)/提示用户MessageBox(目前只支持256色位图的平移!,系统提示,MB_ICONINFORMATION|MB_OK);/解除锁定:GlobalUnlock(HGLOBAL)pDoc-GetHDIB();/返回return;LONG lXOffset;LONG lYOffset;/平移量lXOffset=10;lYOffset=0;/更改光标形状BeginWaitCursor();/找到DIB图像象素起始位置lpDIBBits=:FindDIBBits(lpDIB);/调用TranslationDIB()函数平移DIB if(TranslationDIB(lpDIBBits,:DIBWidth(lpDIB),:DIBHeight(lpDIB),lXOffset,lYOffset)/设置脏标记pDoc-SetModifiedFlag(TRUE);/更新视图pDoc-UpdateAllViews(NULL);else/提示用户MessageBox(分配内存失败!,系统提示,MB_ICONINFORMATION|MB_OK);/解除锁定:GlobalUnlock(HGLOBAL)pDoc-GetHDIB();/恢复光标EndWaitCursor();/向上平移void CMyDIPView:OnMenuitem32779()/平移位图/获取文档CMyDIPDoc*pDoc=GetDocument();/指向DIB的指针LPSTRlpDIB;/指向DIB象素指针LPSTR lpDIBBits;/锁定DIB lpDIB=(LPSTR):GlobalLock(HGLOBAL)pDoc-GetHDIB();/判断是否是8-bpp位图(这里为了方便,只处理8-bpp位图的平移,其它的可以类推)if(:DIBNumColors(lpDIB)!=256)/提示用户MessageBox(目前只支持256色位图的平移!,系统提示,MB_ICONINFORMATION|MB_OK);/解除锁定:GlobalUnlock(HGLOBAL)pDoc-GetHDIB();/返回return;LONG lXOffset;LONG lYOffset;/平移量lXOffset=0;lYOffset=10;/更改光标形状BeginWaitCursor();/找到DIB图像象素起始位置lpDIBBits=:FindDIBBits(lpDIB);/调用TranslationDIB()函数平移DIB if(TranslationDIB(lpDIBBits,:DIBWidth(lpDIB),:DIBHeight(lpDIB),lXOffset,lYOffset)/设置脏标记pDoc-SetModifiedFlag(TRUE);/更新视图pDoc-UpdateAllViews(NULL);else/提示用户MessageBox(分配内存失败!,系统提示,MB_ICONINFORMATION|MB_OK);/解除锁定:GlobalUnlock(HGLOBAL)pDoc-GetHDIB();/恢复光标EndWaitCursor();/向下平移void CMyDIPView:OnMenuitem32778()/平移位图/获取文档CMyDIPDoc*pDoc=GetDocument();/指向DIB的指针LPSTRlpDIB;/指向DIB象素指针LPSTR lpDIBBits;/锁定DIB lpDIB=(LPSTR):GlobalLock(HGLOBAL)pDoc-GetHDIB();/判断是否是8-bpp位图(这里为了方便,只处理8-bpp位图的平移,其它的可以类推)if(:DIBNumColors(lpDIB)!=256)/提示用户MessageBox(目前只支持256色位图的平移!,系统提示,MB_ICONINFORMATION|MB_OK);/解除锁定:GlobalUnlock(HGLOBAL)pDoc-GetHDIB();/返回return;LONG lXOffset;LONG lYOffset;/平移量lXOffset=0;lYOffset=-10;/更改光标形状BeginWaitCursor();/找到DIB图像象素起始位置lpDIBBits=:FindDIBBits(lpDIB);/调用TranslationDIB()函数平移DIB if(TranslationDIB(lpDIBBits,:DIBWidth(lpDIB),:DIBHeight(lpDIB),lXOffset,lYOffset)/设置脏标记pDoc-SetModifiedFlag(TRUE);/更新视图pDoc-UpdateAllViews(NULL);else/提示用户MessageBox(分配内存失败!,系统提示,MB_ICONINFORMATION|MB_OK);/解除锁定:GlobalUnlock(HGLOBAL)pDoc-GetHDIB();/恢复光标EndWaitCursor();变化效果:九、图像缩放算法描述:I、最邻近插值(近邻取样法):最临近插值的的思想很简单,对于通过反向变换得到的的一个浮点坐标,对其进行简单的取整,得到一个整数型坐标,这个整数型坐标对应的像素值就是目的像素的像素值,也就是说,取浮点坐标最邻近的左上角点(对于DIB是右上角,因为它的扫描行是逆序存储的)对应的像素值。可见,最邻近插值简单且直观,但得到的图像质量不高。II、双线性内插值:对于一个目的像素,设置坐标通过反向变换得到的浮点坐标为(i+u,j+v),其中i、j均为非负整数,u、v为0,1)区间的浮点数,则这个像素得值f(i+u,j+v)可由原图像中坐标为(i,j)、(i+1,j)、(i,j+1)、(i+1,j+1)所对应的周围四个像素的值决定,即:f(i+u,j+v)=(1-u)(1-v)f(i,j)+(1-u)vf(i,j+1)+u(1-v)f(i+1,j)+uvf(i+1,j+1)其中f(i,j)表示源图像(i,j)处的的像素值,以此类推这就是双线性内插值法。双线性内插值法计算量大,但缩放后图像质量高,不会出现像素值不连续的的情况。由于双线性插值具有低通滤波器的性质,使高频分量受损,所以可能会使图像轮廓在一定程度上变得模糊。III、三次卷积法能够克服以上两种算法的不足,计算精度高,但计算量大,他考虑一个浮点坐标(i+u,j+v)周围的16个邻点,目的像素值f(i+u,j+v)可由如下插值公式得到:f(i+u,j+v)=A*B*CA=S(u+1)S(u+0)S(u-1)S(u-2)f(i-1,j-1)f(i-1,j+0)f(i-1,j+1)f(i-1,j+2)B=f(i+0,j-1)f(i+0,j+0)f(i+0,j+1)f(i+0,j+2)f(i+1,j-1)f(i+1,j+0)f(i+1,j+1)f(i+1,j+2)f(i+2,j-1)f(i+2,j+0)f(i+2,j+1)f(i+2,j+2)S(v+1)C=S(v+0)S(v-1)S(v-2)1-2*Abs(x)2+Abs(x)3,0=Abs(x)1 S(x)=4-8*Abs(x)+5*Abs(x)2-Abs(x)3,1=Abs(x)20,Abs(x)=2 S(x)是对Sin(x*Pi)/x的逼近(Pi是圆周率-)总结:最邻近插值(近邻取样法)、双线性内插值、三次卷积法等插值算法对于旋转变换、错切变换、一般线性变换和非线性变换都适用。程序实现:/该函数用来缩放DIB图像,返回新生成DIB的句柄。HGLOBAL WINAPI ZoomDIB(LPSTR lpDIB,float fXZoomRatio,float fYZoomRatio)/源图像的宽度和高度LONGlWidth;LONGlHeight;/缩放后图像的宽度和高度LONGlNewWidth;LONGlNewHeight;/缩放后图像的宽度(lNewWidth,必须是4的倍数)LONGlNewLineBytes;/指向源图像的指针LPSTRlpDIBBits;/指向源象素的指针LPSTRlpSrc;/缩放后新DIB句柄HDIBhDIB;/指向缩放图像对应象素的指针LPSTRlpDst;/指向缩放图像的指针LPSTRlpNewDIB;LPSTRlpNewDIBBits;/指向BITMAPINFO结构的指针(Win3.0)LPBITMAPINFOHEADER lpbmi;/指向BITMAPCOREINFO结构的指针LPBITMAPCOREHEADER lpbmc;/循环变量(象素在新DIB中的坐标)LONGi;LONGj;/象素在源DIB中的坐标LONGi0;LONGj0;/图像每行的字节数LONG lLineBytes;/找到源DIB图像象素起始位置lpDIBBits=:FindDIBBits(lpDIB);/获取图像的宽度lWidth=:DIBWidth(lpDIB);/计算图像每行的字节数lLineBytes=WIDTHBYTES(lWidth*8);/获取图像的高度lHeight=:DIBHeight(lpDIB);/计算缩放后的图像实际宽度/此处直接加0.5是由于强制类型转换时不四舍五入,而是直接截去小数部分lNewWidth=(LONG)(:DIBWidth(lpDIB)*fXZoomRatio+0.5);/计算新图像每行的字节数lNewLineBytes=WIDTHBYTES(lNewWidth*8);/计算缩放后的图像高度lNewHeight=(LONG)(lHeight*fYZoomRatio+0.5);/分配内存,以保存新DIB hDIB=(HDIB):GlobalAlloc(GHND,lNewLineBytes*lNewHeight+*(LPDWORD)lpDIB+:PaletteSize(lpDIB);/判断是否内存分配失败if(hDIB=NULL)/分配内存失败return NULL;/锁定内存lpNewDIB=(char*):GlobalLock(HGLOBAL)hDIB);/复制DIB信息头和调色板memcpy(lpNewDIB,lpDIB,*(LPDWORD)lpDIB+:PaletteSize(lpDIB);/找到新DIB象素起始位置lpNewDIBBits=:FindDIBBits(lpNewDIB);/获取指针lpbmi=(LPBITMAPINFOHEADER)lpNewDIB;lpbmc=(LPBITMAPCOREHEADER)lpNewDIB;/更新DIB中图像的高度和宽度if(IS_WIN30_DIB(lpNewDIB)/对于Windows 3.0 DIB lpbmi-biWidth=lNewWidth;lpbmi-biHeight=lNewHeight;else/对于其它格式的DIB lpbmc-bcWidth=(unsigned short)lNewWidth;lpbmc-bcHeight=(unsigned short)lNewHeight;/针对图像每行进行操作for(i=0;i lNewHeight;i+)/针对图像每列进行操作for(j=0;j lNewWidth;j+)/指向新DIB第i行,第j个象素的指针/注意此处宽度和高度是新DIB的宽度和高度lpDst=(char*)lpNewDIBBits+lNewLineBytes*(lNewHeight-1-i)+j;/计算该象素在源DIB中的坐标i0=(LONG)(i/fYZoomRatio+0.5);j0=(LONG)(j/fXZoomRatio+0.5);/判断是否在源图范围内if(j0=0)&(j0 lWidth)&(i0=0)&(i0 lHeight)/指向源DIB第i0行,第j0个象素的指针lpSrc=(char*)lpDIBBits+lLineBytes*(lHeight-1-i0)+j0;/复制象素*lpDst=*lpSrc;else/对于源图中没有的象素,直接赋值为255*(unsigned char*)lpDst)=255;/返回return hDIB;/缩小图像void CMyDIPView:OnMenuitem32778()/图像缩放/获取文档CMyDIPDoc*pDoc=GetDocument();/指向DIB的指针LPSTR lpDIB;/锁定DIB lpDIB=(LPSTR):GlobalLock(HGLOBAL)pDoc-GetHDIB();/判断是否是8-bpp位图(这里为了方便,只处理8-bpp位图的缩放,其它的可以类推)if(:DIBNumColors(lpDIB)!=256)/提示用户MessageBox(目前只支持256色位图的缩放!,系统提示,MB_ICONINFORMATION|MB_OK);/解除锁定:GlobalUnlock(HGLOBAL)pDoc-GetHDIB();/返回return;/缩放比率float fXZoomRatio;float fYZoomRatio;/缩放量fXZoomRatio=0.8;/缩小的比率fYZoomRatio=0.8;/创建新DIB HDIB hNewDIB=NULL;/更改光标形状BeginWaitCursor();/调用ZoomDIB()函数转置DIB hNewDIB=(HDIB)ZoomDIB(lpDIB,fXZoomRatio,fYZoomRatio);/判断缩放是否成功if(hNewDIB!=NULL)/替换DIB,同时释放旧DIB对象pDoc-ReplaceHDIB(hNewDIB);/更新DIB大小和调色板pDoc-InitDIBData();/设置脏标记pDoc-SetModifiedFlag(TRUE);/重新设置滚动视图大小SetScrollSizes(MM_TEXT,pDoc-GetDocSize();/更新视图pDoc-UpdateAllViews(NULL);else/提示用户MessageBox(分配内存失败!,系统提示,MB_ICONINFORMATION|MB_OK);/解除锁定:GlobalUnlock(HGLOBAL)pDoc-GetHDIB();/恢复光标EndWaitCursor();/放大图像void CMyDIPView:OnMenuitem32779()/图像缩放/获取文档CMyDIPDoc*pDoc=GetDocument();/指向DIB的指针LPSTR lpDIB;/锁定DIB lpDIB=(LPSTR):GlobalLock(HGLOBAL)pDoc-GetHDIB();/判断是否是8-bpp位图(这里为了方便,只处理8-bpp位图的缩放,其它的可以类推)if(:DIBNumColors(lpDIB)!=256)/提示用户MessageBox(目前只支持256色位图的缩放!,系统提示,MB_ICONINFORMATION|MB_OK);/解除锁定:GlobalUnlock(HGLOBAL)pDoc-GetHDIB();/返回return;/缩放比率float fXZoomRatio;float fYZoomRatio;/缩放量fXZoomRatio=1.25;/放大的比率fYZoomRatio=1.25;/创建新DIB HDIB hNewDIB=NULL;/更改光标形状BeginWaitCursor();/调用ZoomDIB()函数转置DIB hNewDIB=(HDIB)ZoomDIB(lpDIB,fXZoomRatio,fYZoomRatio);/判断缩放是否成功if(hNewDIB!=NULL)/替换DIB,同时释放旧DIB对象pDoc-ReplaceHDIB(hNewDIB);/更新DIB大小和调色板pDoc-InitDIBData();/设置脏标记pDoc-SetModifiedFlag(TRUE);/重新设置滚动视图大小SetScrollSizes(MM_TEXT,pDoc-GetDocSize();/更新视图pDoc-UpdateAllViews(NULL);else/提示用户MessageBox(分配内存失败!,系统提示,MB_ICONINFORMATION|MB_OK);/解除锁定:GlobalUnlock(HGLOBAL)pDoc-GetHDIB();/恢复光标EndWaitCursor();变换效果(找到参照物判断十、图像旋转程序实现:/角度到弧度转化的宏#define RADIAN(angle)(angle)*PI/180.0)函数名称:RotateDIB()参数:LPSTR lpDIB-指向源DIB的指针int iRotateAngle-旋转的角度(0-360度)返回值:HGLOBAL-旋转成功返回新DIB句柄,否则返回NULL。说明:该函数用来以图像中心为中心旋转DIB图像,返回新生成DIB的句柄。调用该函数会自动扩大图像以显示所有的象素。函数中采用最邻近插值算法进行插值。HGLOBAL WINAPI RotateDIB(LPSTR lpDIB,int iRotateAngle)/源图像的宽度和高度LONGlWidth;LONGlHeight;/旋转后图像的宽度和高度LONGlNewWidth;LONGlNewHeight;/图像每行的字节数LONGlLineBytes;/旋转后图像的宽度(lNewWidth,必须是4的倍数)LONGlNewLineBytes;/指向源图像的指针LPSTRlpDIBBits;/指向源象素的指针LPSTRlpSrc;/旋转后新DIB句柄HDIBhDIB;/指向旋转图像对应象素的指针LPSTRlpDst;/指向旋转图像的指针LPSTRlpNewDIB;LPSTRlpNewDIBBits;/指向BITMAPINFO结构的指针(Win3.0)LPBITMAPINFOHEADER lpbmi;/指向BITMAPCOREINFO结构的指针LPBITMAPCOREHEADER lpbmc;/循环变量(象素在新DIB中的坐标)LONGi;LONGj;/象素在源DIB中的坐标LONGi0;LONGj0;/旋转角度(弧度)floatfRotateAngle;/旋转角度的正弦和余弦floatfSina,fCosa;/源图四个角的坐标(以图像中心为坐标系原点)floatfSrcX1,fSrcY1,fSrcX2,fSrcY2,fSrcX3,fSrcY3,fSrcX4,fSrcY4;/旋转后四个角的坐标(以图像中心为坐标系原点)floatfDstX1,fDstY1,fDstX2,fDstY2,fDstX3,fDstY3,fDstX4,fDstY4;/两个中间常量floatf1,f2;/找到源DIB图像象素起始位置lpDIBBits=:FindDIBBits(lpDIB);/获取图像的宽度(4的倍数)lWidth=:DIBWidth(lpDIB);/计算图像每行的字节数lLineBytes=WIDTHBYTES(lWidth*8);/获取图像的高度lHeight=:DIBHeight(lpDIB);/将旋转角度从度转换到弧度fRotateAngle=(float)RADIAN(iRotateAngle);/计算旋转角度的正弦fSina=(float)sin(double)fRotateAngle);/计算旋转角度的余弦fCosa=(float)cos(double)fRotateAngle);/计算原图的四个角的坐标(以图像中心为坐标系原点)fSrcX1=(float)(-(lWidth-1)/2);fSrcY1=(float)(lHeight-1)/2);fSrcX2=(float)(lWidth-1)/2);fSrcY2=(float)(lHeight-1)/2);fSrcX3=(float)(-(lWidth-1)/2);fSrcY3=(float)(-(lHeight-1)/2);fSrcX4=(float)(lWidth-1)/2);fSrcY4=(float)(-(lHeight-1)/2);/计算新图四个角的坐标(以图像中心为坐标系原点)fDstX1=fCosa*fSrcX1+fSina*fSrcY1;fDstY1=-fSina*fSrcX1+fCosa*fSrcY1;fDstX2=fCosa*fSrcX2+fSina*fSrcY2;fDstY2=-fSina*fSrcX2+fCosa*fSrcY2;fDstX3=fCosa*fSrcX3+fSina*fSrcY3;fDstY3=-fSina*fSrcX3+fCosa*fSrcY3;fDstX4=fCosa*fSrcX4+fSina*fSrcY4;fDstY4=-fSina*fSrcX4+fCosa*fSrcY4;/计算旋转后的图像实际宽度lNewWidth=(LONG)(max(fabs(fDstX4-fDstX1),fabs(fDstX3-fDstX2)+0.5);/计算新图像每行的字节数lNewLineBytes=WIDTHBYTES(lNewWidth*8);/计算旋转后的图像高度lNewHeight=(LONG)(max(fabs(fDstY4-fDstY1),fabs(fDstY3-fDstY2)+0.5);/两个常数,这样不用以后每次都计算了f1=(float)(-0.5*(lNewWidth-1)*fCosa-0.5*(lNewHeight-1)*fSina+0.5*(lWidth-1);f2=(float)(0.5*(lNewWidth-1)*fSina-0.5*(lNewHeight-1)*fCosa+0.5*(lHeight-1);/分配内存,以保存新DIB hDIB=(HDIB):GlobalAlloc(GHND,lNewLineBytes*lNewHeight+*(LPDWORD)lpDIB+:PaletteSize(lpDIB);/判断是否内存分配失败if(hDIB=NULL)/分配内存失败return NULL;/锁定内存lpNewDIB=(char*):GlobalLock(HGLOBAL)hDIB);/复制DIB信息头和调色板memcpy(lpNewDIB,lpDIB,*(LPDWORD)lpDIB+:PaletteSize(lpDIB);/找到新DIB象素起始位置lpNewDIBBits=:FindDIBBits(lpNewDIB);/获取指针lpbmi=(LPBITMAPINFOHEADER)lpNewDIB;lpbmc=(LPBITMAPCOREHEADER)lpNewDIB;/更新DIB中图像的高度和宽度if(IS_WIN30_DIB(lpNewDIB)/对于Windows 3.0 DIB lpbmi-biWidth=lNewWidth;lpbmi-biHeight=lNewHeight;else/对于其它格式的DIB lpbmc-bcWidth=(unsigned short)lNewWidth;lpbmc-bcHeight=(unsigned short)lNewHeight;/针对图像每行进行操作for(i=0;i lNewHeight;i+)/针对图像每列进行操作for(j=0;j lNewWidth;j+)/指向新DIB第i行,第j个象素的指针/注意此处宽度和高度是新DIB的宽度和高度lpDst=(char*)lpNewDIBBits+lNewLineBytes*(lNewHeight-1-i)+j;/计算该象素在源DIB中的坐标i0=(LONG)(-(float)j)*fSina+(float)i)*fCosa+f2+0.5);j0=(LONG)(float)j)*fCosa+(float)i)*fSina+f1+0.5);/判断是否在源图范围内if(j0=0)&(j0 lWidth)&(i0=0)&(i0 lHeight)/指向源DIB第i0行,第j0个象素的指针lpSrc=(char*)lpDIBBits+lLineBytes*(lHeight-1-i0)+j0;/复制象素*lpDst=*lpSrc;else/对于源图中没有的象素,直接赋值为255*(unsigned char*)lpDst)=255;/返回return hDIB;/顺时针旋转void CMyDIPView:OnMenuitem32778()/图像旋转/获取文档CMyDIPDoc*pDoc=GetDocument();/指向DIB的指针LPSTR lpDIB;/锁定DIB lpDIB=(LPSTR):Glo

温馨提示

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

最新文档

评论

0/150

提交评论