2.4 图像调整
2.4.1 图像的缩放
2.4.1.1 图像缩放算法浅析
图像缩放算法有很多种,这里参考网友"lantianyu520"所著的"图像缩放算法"。
原理浅析
		要理解这个图像缩放算法的原理,最重要的是需要理解:对于图像上的每一个像素点,它缩放前后,相对于整个图像的比例应该是一样的。
比如:
		以一个长度和宽度分别为200,100的长方形为例,将其放大两倍,那么缩放后的长度和宽度为400,200。
为方便理解,我们建立一个笛卡尔坐标系,把这个长方形左下角的顶点放到坐标(0,0)位置,四个点的坐标分别为:(0,0),(0,100),(200,0),(200,100)。
		假设此时对长方形中的坐标点(40,50),它的x坐标相对于长的比值是40/200=0.2,y坐标相对于宽的比值是50/100=0.5,那么该点的变换后的坐标Dx,Dy则应满足:Dx/400 = 5;Dy/200 = 0.5,这样,缩放后的坐标就可以算出来了。
		根据上面的分析,设缩放前的像素点坐标为(Sx,Sy),对应的缩放后的像素点坐标为(Dx,Dy),缩放前的图像长宽分别为Sw,Sh,缩放后的图像长宽分别为Dw,Dh,则有:
Sx/Dx = Sw/Dw,Sy/Dy = Sh/Dh
故有Sx = Dx * Sw/Dw,Sy = Dy * Sh/Dh,
2.4.1.2源码编写:图像缩放算法
有了这个上面两条等式后,图像缩放算法的代码就好理解了。
下面的函数实现了基于上述原理实现的图像缩放算法:
代码清单2.4
1.	  
11.	int PicZoom(PT_PictureData ptPicData,float fSize)  
12.	{  
13.	    ptPicData->iZoomWidth = ptPicData->iWidth * fSize;  
14.	    ptPicData->iZoomHeight= ptPicData->iHeight* fSize;  
15.	    unsigned long* pdwSrcXTable;  
16.	    unsigned long x;  
17.	    unsigned long y;  
18.	    unsigned long dwSrcY;  
19.	    unsigned char *pucDest;  
20.	    unsigned char *pucSrc;  
21.	    unsigned long dwPixelBytes = ptPicData->iBpp/8;  
22.	    ptPicData->pucZoomData= malloc(sizeof(unsigned char) * ptPicData->iZoomWidth*ptPicData->iZoomHeight*ptPicData->iBpp/8);  
23.	    pdwSrcXTable = malloc(sizeof(unsigned long) * ptPicData->iZoomWidth);  
24.	    if (NULL == pdwSrcXTable){  
25.	        printf("malloc error!\n");  
26.	        return -1;  
27.	    }  
28.	  
29.	      
30.	    for (x = 0; x < ptPicData->iZoomWidth; x++){
31.	           
36.	        pdwSrcXTable[x]=(x*ptPicData->iWidth/ptPicData->iZoomWidth);  
37.	    }  
38.	  
39.	    for (y = 0; y < ptPicData->iZoomHeight; y++){  
40.	          
45.	        dwSrcY = (y * ptPicData->iHeight / ptPicData->iZoomHeight);  
46.	      
47.	        pucDest = ptPicData->pucZoomData + y*ptPicData->iZoomWidth*3;  
48.	        pucSrc  = ptPicData->pucRgbData + dwSrcY*ptPicData->iWidth*3;  
49.	  
50.	              
51.	        for (x = 0; x <ptPicData->iZoomWidth; x++){  
52.	             memcpy(pucDest+x*dwPixelBytes, pucSrc+pdwSrcXTable[x]*dwPixelBytes, dwPixelBytes);  
53.	        }  
54.	    }  
55.	  
56.	    free(pdwSrcXTable);  
57.	    return 0;  
58.	}
2.4.2 图像的旋转
2.4.2.1 图像旋转算法浅析
这里的图像旋转算法原理参考网友"落叶的思维"所著的"图像旋转算法与实现"
原理浅析
这个旋转算法的原理的关键点有两个:
- 原图像是以图像的左下角为原点建立笛卡尔坐标系的,而旋转一般是以图像的中心作为旋转点旋转的。
 
因此为了便于转换,我们先约定两个坐标系,一个是以图像左下角为原点建立的坐标系,称为坐标系A,这也是原图像的坐标系。一个是以图像中心为原点建立的坐标系,称为坐标系B。
由此,可以知道这个旋转算法的步骤:先将坐标系A下的坐标转换为坐标系B下的坐标,然后在坐标系B下进行图像的旋转。
在坐标系B下,我们假设点(x0,y0)距离原点的距离为r,点与原点之间的连线与x轴的夹角为b,旋转的角度为a,旋转后的点为(x1,y1), 如下图所示。

那么有以下结论:
x0=rcosb;y0=rsinb
x1 = rcos(b-a) = rcosbcosa+rsinbsina=x0cosa+y0sina;
y1=rsin(b-a)=rsinbcosa-rcosbsina=-x0sina+y0cosa;
最后,由于我们显示图像的RGB数据还是要在坐标系A下获取的,我们最后只需要将坐标系B下的x1,y1转换回坐标系A下的坐标就可以了。
旋转后的图像的长和宽会发生变化,因此要计算新图像的长和宽。
由几何关系可知,新图像的长和宽分别是旋转后,对角坐标相见后的最大值
2.4.2.2 源码编写:图像旋转算法
代码清单2.5
1.	 #define PI 3.1415926535  
2.	
3.	#define RADIAN(angle) ((angle)*PI/180.0)  
4.	  
5.	  
6.	  
7.	  
8.	  
9.	typedef struct ConcernCoor {  
10.	    int iLTx;
11.	    int iLTy;
12.	    int iLBx;
13.	    int iLBy;
14.	    int iRTx;
15.	    int iRTy;
16.	    int iRBx;
17.	    int iRBy;
18.	}T_ConcernCoor, *PT_ConcernCoor;  
19.	  
20.	  
21.	  
28.	static int max(int x,int y){  
29.	    return x>y?x:y;  
30.	}  
31.	  
41.	int PicRotate(PT_PictureData ptPicData,float fAngle)  
42.	{  
43.	    int i ,j;  
44.	    T_ConcernCoor tConCor,tRonCor;  
45.	    
46.	    
47.	    int iSrcLineSize = ptPicData->iBpp* ptPicData->iZoomWidth / 8;  
48.	    int iDesLineSize;  
49.	    int iX;
50.	    int iY; 
51.	  
52.	         
56.	       tConCor.iLTx = -ptPicData->iZoomWidth/2; tConCor.iLTy = ptPicData->iZoomHeight/2;  
57.	    tConCor.iRTx = ptPicData->iZoomWidth/2; tConCor.iRTy = ptPicData->iZoomHeight/2;  
58.	    tConCor.iLBx = -ptPicData->iZoomWidth/2;tConCor.iLBy = -ptPicData->iZoomHeight/2;  
59.	    tConCor.iRBx = ptPicData->iZoomWidth/2;tConCor.iRBy = -ptPicData->iZoomHeight/2;  
60.	  
61.	  
62.	      
63.	    double sina = sin(RADIAN(fAngle));  
64.	    double cosa = cos(RADIAN(fAngle));  
65.	    tRonCor.iLTx =tConCor.iLTx * cosa + tConCor.iLTy * sina;  
66.	    tRonCor.iLTy = -tConCor.iLTx * sina + tConCor.iLTy * cosa;  
67.	    tRonCor.iRTx =tConCor.iRTx * cosa + tConCor.iRTy * sina;  
68.	    tRonCor.iRTy = -tConCor.iRTx * sina + tConCor.iRTy * cosa;  
69.	    tRonCor.iLBx = tConCor.iLBx * cosa + tConCor.iLBy * sina;  
70.	    tRonCor.iLBy = -tConCor.iLBx * sina + tConCor.iLBy * cosa;  
71.	    tRonCor.iRBx = tConCor.iRBx * cosa + tConCor.iRBy * sina;  
72.	    tRonCor.iRBy = -tConCor.iRBx * sina + tConCor.iRBy * cosa;  
73.	  
74.	      
75.	      
76.	    ptPicData->iRotateWidth = max(abs(tRonCor.iRBx - tRonCor.iLTx),abs(tRonCor.iRTx - tRonCor.iLBx));  
77.	    ptPicData->iRotateHeight = max(abs(tRonCor.iRBy - tRonCor.iLTy),abs(tRonCor.iRTy - tRonCor.iLBy));  
78.	  
79.	      
80.	    iDesLineSize = ((ptPicData->iRotateWidth* ptPicData->iBpp+ 23) / 24) * 3 ;  
81.	      
82.	    ptPicData->pucRotateData = malloc(iDesLineSize * ptPicData->iRotateHeight);  
83.	    if(NULL == ptPicData->pucRotateData){  
84.	        printf("malloc error\n");  
85.	        return -1;  
86.	    }  
87.	  
88.	      
90.	    for (i = 0; i < ptPicData->iRotateHeight; i++){          
91.	        for (j = 0; j < ptPicData->iRotateWidth; j++){  
92.	              
93.	            iX = (j - ptPicData->iRotateWidth / 2)*cos(RADIAN(360 - fAngle)) + (-i + ptPicData->iRotateHeight / 2)*sin(RADIAN(360 - fAngle));  
94.	            iY = -(j - ptPicData->iRotateWidth / 2)*sin(RADIAN(360 - fAngle)) + (-i + ptPicData->iRotateHeight / 2)*cos(RADIAN(360 - fAngle));  
95.	              
96.	            if (iX > ptPicData->iZoomWidth / 2 || iX < -ptPicData->iZoomWidth / 2 || iY > ptPicData->iZoomHeight / 2 || iY < -ptPicData->iZoomHeight / 2){  
97.	                continue;  
98.	            }  
99.	              
100.	            int iXN = iX + ptPicData->iZoomWidth / 2;   
101.	         int iYN = abs(iY - ptPicData->iZoomHeight  / 2);  
102.	              
103.	            memcpy(&ptPicData->pucRotateData[i * iDesLineSize + j * 3],&ptPicData->pucZoomData[iYN * iSrcLineSize + iXN * 3],3);    
104.	        }  
105.	    }  
106.	  return 0;  
107.	}