图像的旋转
图像的选旋转,按照指定中心点逆时针旋转b角度,这个稍微有点麻烦
具体实现起来相比较而言有一点麻烦,不着急,一步一步来,首先需要将像素矩阵中第i行j列元素坐标(i,j)转化为坐标系坐标(x0,y0)
同理坐标系坐标转化为i,j坐标,可以定义两个函数来转换
//可以自己定义一个坐标结构体变量
# define PI 3.1415926//近似π
typedef struct _coor
{
float x;
float y;
}coor;
coor ijToxy(float i, float j,int w,int h)
{
coor c;
c.x = -0.5*w + i;
c.y = 0.5*h - j;
return c;
}
coor xyToij(float x, float y,int w,int h)
{
coor c;
c.x = 0.5*w + x;
c.y = 0.5*h - y;
return c;
}
有了(x0,y0),绕中心逆时针旋转,那么得到的新坐标(x1,y1)就容易了
float r = sqrt(x0*x0 + y0*y0);
/*
x0=r*cos(a),y0=r*sin(a)
旋转b角度
x1=r*cos(a+b)=r*(cos(a)cos(b)-sin(a)sin(b))
=r*(x0/r * cos(b)-y0/r *sin(b))
y1=r*sin(a+b)=r*(sin(a)cos(b)+cos(a)sin(b))
=r*(y0/r *cos(b)+x0/r * sin(b))
*/
得到了新坐标,再转化为像素矩阵坐标,注意如果新位图大小和原来一样,那么图片会旋转出去,所以我将新位图宽高都设置为原来的宽,高之和,方便计算,多余的像素点设置为255(即白色),当然,由于计算中浮点数四舍五入等等精度上的问题,所以很难保证图像旋转后和原来一模一样,效果如下:
45度
90度
135度
180度
再看看原书作者提供的代码实现的效果
90度
45度
学习中,还是保持质疑的态度来认真学习,才会有收获,请不要假装很努力,因为结果不会陪你演戏!!!!
下面是自己实现出来的算法
//===============函数定义=====================
//图像的旋转
//围绕图片中心点逆时针旋转
void rotate(HDC hdc, HDC hMemDC, HBITMAP hBitmap, int Width, int Heigh,int angle)
{
BITMAP bm;
GetObject(hBitmap, sizeof(bm), &bm);
int WidthRow = bm.bmWidthBytes;//原位图的字节宽(即原位图的每行字节数)
//获取原位图的像素位
BYTE *Pixel = new BYTE[WidthRow*Heigh];
GetBitmapBits(hBitmap, WidthRow*Heigh, (LPVOID)Pixel);
//绕中心旋转,新图片宽和高最大为:
int newWidth = Width + Heigh;
int newHeigh = newWidth;
BYTE *newPixel = new BYTE[newWidth*newHeigh * 4];//存放新的像素位
memset(newPixel, 255, newWidth*newHeigh * 4 * sizeof(BYTE));
//图像旋转
for (int j = 0; j <Heigh; j++)//行
for (int i = 0; i < Width; i++)//列
{
//(i,j)转化为坐标系坐标
float x0 = ijToxy(i,j,Width,Heigh).x;
float y0 = ijToxy(i, j, Width, Heigh).y;
float r = sqrt(x0*x0 + y0*y0);
/*
x0=r*cos(a),y0=r*sin(a)
旋转b角度
x1=r*cos(a+b)=r*(cos(a)cos(b)-sin(a)sin(b))
=r*(x0/r * cos(b)-y0/r *sin(b))
y1=r*sin(a+b)=r*(sin(a)cos(b)+cos(a)sin(b))
=r*(y0/r *cos(b)+x0/r * sin(b))
*/
//原坐标(x0,y0)->新坐标(x1,y1)
float x1 = r*(x0/r*cos(angle*PI/180)-y0/r*sin(angle*PI/180));
float y1 = r*(y0 / r*cos(angle*PI / 180) + x0 / r*sin(angle*PI / 180));
//坐标系坐标转化为(i,j)
float i1 = xyToij(x1, y1, Width, Heigh).x;
float j1= xyToij(x1, y1, Width, Heigh).y;
float i2 = i1+ 0.5*Heigh;
float j2 = j1+0.5*Width;
//每4个为一个像素位
for (int k = 0; k < 4; k++)
{
newPixel[int(j2)*newWidth *4 + 4 *int(i2) + k] = Pixel[j*Width * 4 + 4 * i + k];
}
}
//创建一个新的位图
HBITMAP hNewBitmap = CreateCompatibleBitmap(hdc, newWidth, newHeigh);
SelectObject(hMemDC, hNewBitmap);//选进内存DC
SetBitmapBits(hNewBitmap, newWidth*newHeigh * 4, newPixel);
BitBlt(hdc, 0, 0, newWidth, newHeigh, hMemDC, 0, 0, SRCCOPY);
DeleteObject(hNewBitmap);
delete[] Pixel;
delete[] newPixel;
}
coor ijToxy(float i, float j,int w,int h)
{
coor c;
c.x = -0.5*w + i;
c.y = 0.5*h - j;
return c;
}
coor xyToij(float x, float y,int w,int h)
{
coor c;
c.x = 0.5*w + x;
c.y = 0.5*h - y;
return c;
}