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. /**********************************************************************
2. * 函数名称: PicZoom
3. * 功能描述: 近邻取样插值方法缩放图片
4. * 注意该函数会分配内存来存放缩放后的图片,用完后要用free函数释放掉
5. * "近邻取样插值"的原理请参考网友"lantianyu520"所著的"图像缩放算法"
6. * 输入参数: ptPicData - 内含缩放前后的图像数据
7. * fSize - 缩放倍数
8. * 输出参数: ptPicData->pucZoomData,内含缩放后的数据
9. * 返 回 值: 0 - 成功, 其他值 - 失败
10. ***********************************************************************/
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. /* 这几个for循环的本质是Sx = Dx * Sw/Dw,Sy = Dy * Sh/Dh*/
30. for (x = 0; x < ptPicData->iZoomWidth; x++){
//生成表 pdwSrcXTable
31. /* 第一个for循环对应x方向的坐标
32. * pdwSrcXTable[x] 对应Sx,
33. * x 对应Dx,
34. * ptPicData->iWidth 对应Sw
35. * ptPicData->iZoomWidth 对应 Dw*/
36. pdwSrcXTable[x]=(x*ptPicData->iWidth/ptPicData->iZoomWidth);