最新文章专题视频专题问答1问答10问答100问答1000问答2000关键字专题1关键字专题50关键字专题500关键字专题1500TAG最新视频文章推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37视频文章20视频文章30视频文章40视频文章50视频文章60 视频文章70视频文章80视频文章90视频文章100视频文章120视频文章140 视频2关键字专题关键字专题tag2tag3文章专题文章专题2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章专题3
当前位置: 首页 - 正文

图像旋转算法与实现

来源:动视网 责编:小OO 时间:2025-10-03 00:46:39
文档

图像旋转算法与实现

∙好吧,先下个定义,图像旋转是指图像以某一点为中心旋转一定的角度,形成一幅新的图像的过程。当然这个点通常就是图像的中心。既然是按照中心旋转,自然会有这样一个属性:旋转前和旋转后的点离中心的位置不变.根据这个属性,我们可以得到旋转后的点的坐标与原坐标的对应关系。由于原图像的坐标是以左上角为原点的,所以我们先把坐标转换为以图像中心为原点。假设原图像的宽为w,高为h,(x0,y0)为原坐标内的一点,转换坐标后的点为(x1,y1)。那么不难得到:x1=x0-w/2;y1=-y0+h/2;在新的坐标系下
推荐度:
导读∙好吧,先下个定义,图像旋转是指图像以某一点为中心旋转一定的角度,形成一幅新的图像的过程。当然这个点通常就是图像的中心。既然是按照中心旋转,自然会有这样一个属性:旋转前和旋转后的点离中心的位置不变.根据这个属性,我们可以得到旋转后的点的坐标与原坐标的对应关系。由于原图像的坐标是以左上角为原点的,所以我们先把坐标转换为以图像中心为原点。假设原图像的宽为w,高为h,(x0,y0)为原坐标内的一点,转换坐标后的点为(x1,y1)。那么不难得到:x1=x0-w/2;y1=-y0+h/2;在新的坐标系下
∙好吧,先下个定义,图像旋转是指图像以某一点为中心旋转一定的角度,形成一幅新的图像的过程。当然这个点通常就是图像的中心。既然是按照中心旋转,自然会有这样一个属性:旋转前和旋转后的点离中心的位置不变.

根据这个属性,我们可以得到旋转后的点的坐标与原坐标的对应关系。由于原图像的坐标是以左上角为原点的,所以我们先把坐标转换为以图像中心为原点。假设原图像的宽为w,高为h,(x0,y0)为原坐标内的一点,转换坐标后的点为(x1,y1)。那么不难得到:

x1 = x0 - w/2; y1 = -y0 + h/2;

在新的坐标系下,假设点(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;

得到了转换后的坐标,我们只需要把这些坐标再转换为原坐标系即可。这里还有一点要注意,旋转后的图像的长和宽会发生变化,因此要计算新图像的长和宽。

以下为源程序:

  1 #include "stdafx.h"

2 #include

3 #include

4 #include

5 #include

  6  using namespace std;

  7 

  8  #define PI 3.1415926535

  9 //角度到弧度转化

 10 #define RADIAN(angle) ((angle)*PI/180.0)

 11 

 12 void Rotation(const string& srcFile,const string& desFile,int angle)

 13 {

 14     BITMAPFILEHEADER bmfHeader;

 15     BITMAPINFOHEADER bmiHeader;

 16     

 17     FILE *pFile;

 18     if ((pFile = fopen(srcFile.cstr(),"rb")) == NULL)

 19     {

 20         printf("open bmp file error.");

 21         exit(-1);

 22     }

 23     //读取文件和Bitmap头信息

 24     fseek(pFile,0,SEEKSET);

 25     fread(&bmfHeader,sizeof(BITMAPFILEHEADER),1,pFile);

 26     fread(&bmiHeader,sizeof(BITMAPINFOHEADER),1,pFile);

 27     //先不支持小于16位的位图

 28     int bitCount = bmiHeader.biBitCount;

29 if (bitCount < 16)

 30     {        

 31         exit(-1);

 32     }

 33     int srcW = bmiHeader.biWidth;

 34     int srcH = bmiHeader.biHeight;

 35     //原图像每一行去除偏移量的字节数

 36     int lineSize = bitCount * srcW / 8;

 37     //偏移量,windows系统要求每个扫描行按四字节对齐

 38     int alignBytes = ((bmiHeader.biWidth * bitCount + 31) & ~31) / 8L

 39         - bmiHeader.biWidth * bitCount / 8L;

 40     //原图像缓存

 41     int srcBufSize = lineSize * srcH;

 42     BYTE* srcBuf = new BYTE[srcBufSize];

 43     int i,j;

 44     //读取文件中数据

45 for (i = 0; i < srcH; i++)

 46     {        

 47         fread(&srcBuf[lineSize * i],lineSize,1,pFile);

 48         fseek(pFile,alignBytes,SEEKCUR);

 49     }

 50     //以图像中心为原点左上角,右上角,左下角和右下角的坐标,用于计算旋转后的图像的宽和高

 51     POINT pLT,pRT,pLB,pRB;

 52     pLT.x = -srcW/2;pLT.y = srcH/2;

 53     pRT.x = srcW/2;pRT.y = srcH/2;

 54     pLB.x = -srcW/2;pLB.y = -srcH/2;

 55     pRB.x = srcW/2; pRB.y = -srcH/2;

 56     //旋转之后的坐标

 57     POINT pLTN,pRTN,pLBN,pRBN;

 58     double sina = sin(RADIAN(angle));

 59     double cosa = cos(RADIAN(angle));

 60     pLTN.x = pLT.x*cosa + pLT.y*sina;    

 61     pLTN.y = -pLT.x*sina + pLT.y*cosa;

 62     pRTN.x = pRT.x*cosa + pRT.y*sina;

 63     pRTN.y = -pRT.x*sina + pRT.y*cosa;

      pLBN.x = pLB.x*cosa + pLB.y*sina;

 65     pLBN.y = -pLB.x*sina + pLB.y*cosa;

 66     pRBN.x = pRB.x*cosa + pRB.y*sina;

 67     pRBN.y = -pRB.x*sina + pRB.y*cosa;

 68     //旋转后图像宽和高

 69     int desWidth = max(abs(pRBN.x - pLTN.x),abs(pRTN.x - pLBN.x));

 70     int desHeight = max(abs(pRBN.y - pLTN.y),abs(pRTN.y - pLBN.y));

 71     //分配旋转后图像的缓存

 72     int desBufSize = ((desWidth * bitCount + 31) / 32) * 4 * desHeight;

 73     BYTE *desBuf = new BYTE[desBufSize];

 74     //将所有像素都预置为白色

 75     memset(desBuf,255,desBufSize);

 76     //新图像每一行字节数,带有偏移量

 77     int desLineSize = ((desWidth * bitCount + 31) / 32) * 4;        

 78     //通过新图像的坐标,计算对应的原图像的坐标

79 for (i = 0; i < desHeight; i++)

 80     {        

81 for (j = 0; j < desWidth; j++)

 82         {

 83             //转换到以图像为中心的坐标系,并进行逆旋转

 84             int tX = (j - desWidth / 2)*cos(RADIAN(360 - angle)) + (-i + desHeight / 2)*sin(RADIAN(360 - angle));

 85             int tY = -(j - desWidth / 2)*sin(RADIAN(360 - angle)) + (-i + desHeight / 2)*cos(RADIAN(360 - angle));

 86             //如果这个坐标不在原图像内,则不赋值

87 if (tX > srcW / 2 || tX < -srcW / 2 || tY > srcH / 2 || tY < -srcH / 2)

 88             {

                  continue;

 90             }

 91             //再转换到原坐标系下

 92             int tXN = tX + srcW / 2; int tYN = abs(tY - srcH / 2);

 93             //值拷贝

 94             memcpy(&desBuf[i * desLineSize + j * bitCount / 8],&srcBuf[tYN * lineSize + tXN * bitCount / 8],3);            

 95         }

 96     }

 97 

 98     //创建目标文件

 99     HFILE hfile = lcreat(desFile.cstr(),0);    

100     //文件头信息

101     BITMAPFILEHEADER nbmfHeader;    

102     nbmfHeader.bfType = 0x4D42;

103     nbmfHeader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)

104         + desWidth * desHeight * bitCount / 8;

105     nbmfHeader.bfReserved1 = 0;

106     nbmfHeader.bfReserved2 = 0;

107     nbmfHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

108     //Bitmap头信息

109     BITMAPINFOHEADER   bmi; 

110     bmi.biSize=sizeof(BITMAPINFOHEADER); 

111     bmi.biWidth=desWidth; 

112     bmi.biHeight=desHeight; 

113     bmi.biPlanes=1; 

114     bmi.biBitCount=bitCount; 

115     bmi.biCompression=BIRGB; 

116     bmi.biSizeImage=0; 

117     bmi.biXPelsPerMeter=0; 

118     bmi.biYPelsPerMeter=0; 

119     bmi.biClrUsed=0; 

120     bmi.biClrImportant=0; 

121     

122     //写入文件头信息

123     lwrite(hfile,(LPCSTR)&nbmfHeader,sizeof(BITMAPFILEHEADER));

124     //写入Bitmap头信息

125     lwrite(hfile,(LPCSTR)&bmi,sizeof(BITMAPINFOHEADER));

126     //写入图像数据

127     lwrite(hfile,(LPCSTR)desBuf,desBufSize);

128     lclose(hfile);

129 }

130 

131 int main(int argc, char* argv[])

132 {

133     FILE *pFile;

135     {

136         printf("open bmp file error.");

137         return -1;

138     }

141     Rotation(srcFile,desFile,150);

142     system("pause");

143     return 0;

144 }

测试效果如下,旋转前:

旋转后:

文档

图像旋转算法与实现

∙好吧,先下个定义,图像旋转是指图像以某一点为中心旋转一定的角度,形成一幅新的图像的过程。当然这个点通常就是图像的中心。既然是按照中心旋转,自然会有这样一个属性:旋转前和旋转后的点离中心的位置不变.根据这个属性,我们可以得到旋转后的点的坐标与原坐标的对应关系。由于原图像的坐标是以左上角为原点的,所以我们先把坐标转换为以图像中心为原点。假设原图像的宽为w,高为h,(x0,y0)为原坐标内的一点,转换坐标后的点为(x1,y1)。那么不难得到:x1=x0-w/2;y1=-y0+h/2;在新的坐标系下
推荐度:
  • 热门焦点

最新推荐

猜你喜欢

热门推荐

专题
Top