1、Visual C+实践与提高数字图像处理与工程应用篇第五章学习笔记第五章 图像的几何变换数字图像平移图像平移函数/* * 函数名称:Translation(LPSTR lpSrcStartBits, long lWidth, long lHeight, long lXOffset, long lYOffset,long lLineBytes,long lDstLineBytes) * 函数参数: * LPSTR lpSrcStartBits,指向源DIB起始像素的指针 * long lWidth,DIB图象的宽度 * long lHeight,DIB图象的高度 * long lXOffset,
2、X方向偏移量 * long lYOffset,Y方向偏移量 * long lLineBytes,DIB图象的行字节数,为4的倍数 * long lDstLineBytes,临时DIB图象的行字节数,为4的倍数 * 函数类型:BOOL * 函数功能:该函数用来平移DIB图象 */BOOL Translation(LPSTR lpSrcStartBits, long lWidth, long lHeight, long lXOffset, long lYOffset,long lLineBytes,long lDstLineBytes) long i; /行循环变量 long j; /列循环变量
3、LPSTR lpSrcDIBBits; /指向源像素的指针 LPSTR lpDstDIBBits; /指向临时图象对应像素的指针 LPSTR lpDstStartBits; /指向临时图象对应像素的指针 HLOCAL hDstDIBBits; /临时图象句柄 hDstDIBBits= LocalAlloc(LHND, lWidth * lDstLineBytes);/ 分配临时内存 lpDstStartBits= (char * )LocalLock(hDstDIBBits);/ 锁定内存 if (hDstDIBBits= NULL)/ 判断是否内存分配 return FALSE;/ 分配内存
4、失败 for(i = 0; i lHeight; i+)/ 行 for(j = 0; j = 0) & (j-lYOffset= 0) & (i-lXOffset GetHObject();/ 锁定DIB if (pDoc-m_dib.GetColorNum(lpSrcDib) != 256)/ 判断是否是8-bpp位图 AfxMessageBox(对不起,不是256色位图!);/ 警告 :GlobalUnlock(HGLOBAL) pDoc-GetHObject();/ 解除锁定 return; /返回 /判断是否是8-bpp位图,不是则返回 lpSrcStartBits=pDoc-m_di
5、b.GetBits(lpSrcDib); / 找到DIB图象像素起始位置 lSrcWidth= pDoc-m_dib.GetWidth(lpSrcDib); / 获取图象的宽度 lSrcHeight= pDoc-m_dib.GetHeight(lpSrcDib); / 获取图象的高度 lSrcLineBytes=pDoc-m_dib.GetReqByteWidth(lSrcWidth * 8); / 计算图象每行的字节数/ lDstLineBytes=pDoc-m_dib.GetReqByteWidth(lSrcHeight * 8); / 计算新图象每行的字节数 CDlgTran TranP
6、ara;/ 创建对话框 if (TranPara.DoModal() != IDOK)/ 显示对话框,提示用户设定量 return; int temver=TranPara.m_verOff; int temhor=TranPara.m_horOff; if (Translation(lpSrcStartBits, lSrcWidth,lSrcHeight,/ 调用Translation()函数平移DIB temver,temhor,lSrcLineBytes,lDstLineBytes) pDoc-SetModifiedFlag(TRUE); / 设置脏标记 pDoc-UpdateAllVi
7、ews(NULL); / 更新视图 :GlobalUnlock(HGLOBAL) pDoc-GetHObject(); / 解除锁定 else AfxMessageBox(_T(分配内存失败!); /警告 数字图像旋转图像旋转函数/* * 函数名称:Rotate(LPSTR lpSrcDib, LPSTR lpSrcStartBits,long lWidth, long lHeight, long lLineBytes, WORD palSize, long lDstWidth, long lDstHeight,long lDstLineBytes,float fSina, float fCo
8、sa) * 函数参数: * LPSTR lpSrcDib,指向源DIB的指针 * LPSTR lpSrcStartBits,指向源DIB的起始像素的指针 * long lWidth,源DIB图象宽度 * long lHeight,源DIB图象高度 * long lLineBytes,源DIB图象字节宽度(4的倍数) * WORD palSize,源DIB图象调色板大小 * long lDstWidth,目标图象宽度 * long lDstHeight,目标DIB图象高度 * long lDstLineBytes,目标DIB图象行字节数(4的倍数) * float fSina,旋转角的余弦,说明
9、:为了避免两次求取正余弦,这里作为两个函数参数来用 * float fCosa,旋转角的正弦 * 函数类型:HGLOBAL * 函数功能:用来旋转DIB图象 */HGLOBAL Rotate(LPSTR lpSrcDib, LPSTR lpSrcStartBits,long lWidth, long lHeight, long lLineBytes, WORD palSize, long lDstWidth, long lDstHeight,long lDstLineBytes,float fSina, float fCosa) float varFloat1; /浮点参数变量1 float
10、varFloat2; /浮点参数变量2 LPSTR lpDstDib; /指向临时图象的指针 long i; /行循环变量 long j; /列循环变量 long i1; /行循环变量 long j1; /列循环变量 LPSTR lpSrcDIBBits; /指向源像素的指针 LPSTR lpDstDIBBits; /指向临时图象对应像素的指针 LPSTR lpDstStartBits; /指向临时图象对应像素的指针 LPBITMAPINFOHEADER lpbmi;/ 指向BITMAPINFOHEADER结构的指针 varFloat1= (float) (-0.5 * (lDstWidth
11、- 1) * fCosa - 0.5 * (lDstHeight - 1) * fSina/ 将经常用到的两个常数事先求出,以便作为常数使用 + 0.5 * (lDstWidth - 1); varFloat2= (float) ( 0.5 * (lDstWidth - 1) * fSina - 0.5 * (lDstHeight - 1) * fCosa + 0.5 * (lDstHeight - 1); HGLOBAL hDIB = (HGLOBAL) :GlobalAlloc(GHND, lDstLineBytes * lDstHeight + *(LPDWORD)lpSrcDib +p
12、alSize);/ 分配内存,以保存新DIB if (hDIB = NULL)/ 判断是否是有效的DIB对象 return FALSE;/ 不是,则返回 lpDstDib= (char * ):GlobalLock(HGLOBAL) hDIB);/ 锁定内存 memcpy(lpDstDib,lpSrcDib, *(LPDWORD)lpSrcDib +palSize);/ 复制DIB信息头和调色板 lpbmi = (LPBITMAPINFOHEADER)lpDstDib;/ 获取指针 lpbmi-biHeight=lDstHeight;/ 更新DIB中图象的高度和宽度 lpbmi-biWidth
13、 =lDstWidth; lpDstStartBits=lpDstDib+ *(LPDWORD)lpDstDib +palSize;/ 求像素起始位置,作用如同:FindDIBBits(gCo.lpSrcDib),这里尝试使用了这种方法,以避免对全局函数的调用 for(i = 0; i lDstHeight; i+)/ 行操作 for(j = 0; j = 0) & (j1= 0) & (i1GetHObject();/ 锁定DIB if (pDoc-m_dib.GetColorNum(lpSrcDib) != 256)/ 判断是否是8-bpp位图 AfxMessageBox(对不起,不是25
14、6色位图!);/ 警告 :GlobalUnlock(HGLOBAL) pDoc-GetHObject();/ 解除锁定 return; /返回 /判断是否是8-bpp位图,不是则返回 lpSrcStartBits=pDoc-m_dib.GetBits(lpSrcDib); / 找到DIB图象像素起始位置 lSrcWidth= pDoc-m_dib.GetWidth(lpSrcDib); / 获取图象的宽度 lSrcHeight= pDoc-m_dib.GetHeight(lpSrcDib); / 获取图象的高度 lSrcLineBytes=pDoc-m_dib.GetReqByteWidth(
15、lSrcWidth * 8); / 计算图象每行的字节数 long lDstLineBytes;/ CDlgRot RotPara;/ 创建对话框 if(RotPara.DoModal() != IDOK)/ 显示对话框,设定旋转角度 return; DWORD palSize=pDoc-m_dib.GetPalSize(lpSrcDib); float fRotateAngle = (float) AngleToRadian(RotPara.m_rotAngle);/ 将旋转角度从度转换到弧度 float fSina = (float) sin(double)fRotateAngle);/
16、计算旋转角度的正余弦 float fCosa = (float) cos(double)fRotateAngle); float fSrcX1,fSrcY1,fSrcX2,fSrcY2,fSrcX3,fSrcY3,fSrcX4,fSrcY4;/ 旋转前四个角的坐标(以图象中心为坐标系原点) float fDstX1,fDstY1,fDstX2,fDstY2,fDstX3,fDstY3,fDstX4,fDstY4;/ 旋转后四个角的坐标(以图象中心为坐标系原点) fSrcX1 = (float) (- (lSrcWidth - 1) / 2);/ 计算原图的四个角的坐标 fSrcY1 = (fl
17、oat) ( (lSrcHeight - 1) / 2); fSrcX2 = (float) ( (lSrcWidth - 1) / 2); fSrcY2 = (float) ( (lSrcHeight - 1) / 2); fSrcX3 = (float) (- (lSrcWidth - 1) / 2); fSrcY3 = (float) (- (lSrcHeight - 1) / 2); fSrcX4 = (float) ( (lSrcWidth - 1) / 2); fSrcY4 = (float) (- (lSrcHeight - 1) / 2); fDstX1 = fCosa * f
18、SrcX1 + 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 =
19、-fSina * fSrcX4 + fCosa * fSrcY4; lDstWidth= (long) ( max( fabs(fDstX4 - fDstX1), fabs(fDstX3 - fDstX2) ) + 0.5);/ 计算旋转后的图象实际宽度 lDstLineBytes=pDoc-m_dib.GetReqByteWidth(lDstWidth * 8);/ 计算新图象每行的字节数 lDstHeight= (long) ( max( fabs(fDstY4 - fDstY1), fabs(fDstY3 - fDstY2) ) + 0.5);/ 计算旋转后的图象高度 HGLOBAL h
20、DstDIB = NULL;/ 创建新DIB hDstDIB = (HGLOBAL) Rotate(lpSrcDib,lpSrcStartBits,lSrcWidth,lSrcHeight,lSrcLineBytes, palSize,lDstWidth,lDstHeight,lDstLineBytes,fSina,fCosa);/ 调用Rotate()函数旋转DIB if(hDstDIB != NULL)/ 判断旋转是否成功 pDoc-UpdateObject(hDstDIB);/ 替换DIB,同时释放旧DIB对象 pDoc-SetDib();/ 更新DIB大小和调色板 pDoc-SetModifiedFlag(TRUE); / 设置脏标记 pDoc-UpdateAllViews(NULL); / 更新视图 :GlobalUnlock(HGLOBAL) pDoc-GetHObject(); / 解除锁定 else AfxMessageBox(_T(分配内存失败!); / 警告 数字图像缩放图像缩放函数/* * 函数名称:Zoom(LPSTR lpSrcDib, LPSTR lpSrcStartBits,long lWidth, long lHeight, long lLin