图像的旋转

图像的选旋转,按照指定中心点逆时针旋转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;
}