这里直接使用该博主分享的方法,本文使用的是第二种:https://blog.csdn.net/jiayp004/article/details/50518232
代码如下(已重新对代码进行注释,方便理解):
public Bitmap RotateImg2(Bitmap b, float angle)
{
angle = angle % 360; //弧度转换
double radian = angle * Math.PI / 180.0;
double cos = Math.Cos(radian);
double sin = Math.Sin(radian);
//原图的宽和高
int w = b.Width;
int h = b.Height;
//计算旋转后图片的大小
int W = (int)(Math.Max(Math.Abs(w * cos - h * sin), Math.Abs(w * cos + h * sin)));
int H = (int)(Math.Max(Math.Abs(w * sin - h * cos), Math.Abs(w * sin + h * cos)));
//目标位图,也是在该图片上进行绘制
Bitmap dsImage = new Bitmap(W, H);
Graphics g = Graphics.FromImage(dsImage);
g.InterpolationMode = InterpolationMode.Bilinear;
g.SmoothingMode = SmoothingMode.HighQuality;
//计算偏移量
Point Offset = new Point((W - w) / 2, (H - h) / 2);
//构造图像显示区域:让图像的中心与窗口的中心点一致
Rectangle rect = new Rectangle(Offset.X, Offset.Y, w, h);
Point center = new Point(rect.X + rect.Width / 2, rect.Y + rect.Height / 2);
//参考系原点从图像左上角平移到中心,以实现图片绕中心旋转
g.TranslateTransform(center.X, center.Y);
//旋转参考系,相当于旋转图片
g.RotateTransform(360 - angle);
//恢复图像在水平和垂直方向的平移,坐标系原点恢复至旋转后坐标系的左上角
g.TranslateTransform(-center.X, -center.Y);
g.DrawImage(b, rect);
//重至绘图的所有变换
g.ResetTransform();
g.Save();
g.Dispose();
//dsImage.Save("yuancd.png", System.Drawing.Imaging.ImageFormat.Png);
return dsImage;
}
至于旋转后,图片大小为什么会变,可以看这个图理解:
一般,我们建立的图片都是矩形的,即是矩阵数据构成的图像,所以旋转后仍然需要保存成矩形的,如上图,旋转后如果想保存成矩形的数据,就需要根据旋转的角度计算新矩形的维度。上面代码中就有根据cos sin 计算旋转后边长的步骤。
第一步中,执行旋转多个角度后分别生成的图片大小是不一样的,其中根据sin cos 函数性质,当图片旋转45°、135°…时,是图片最大的时候。
旋转前图片大小:p×q
旋转 后图片为:w×h
旋转后图片最大为:W×H
而其他角度图片的大小都介于W×H和p×q之间,因此旋转后的图片,即“第一步”中 RotateImg2(Bitmap b, float angle)函数的返回结果,都在维度为W*H的空白图像上进行绘制,而后裁剪边框留白区域,保持旋转后所有图片的大小都一致。
代码如下:
public Bitmap DrawPic(Bitmap b, float angle)
{
//调用旋转函数
Bitmap bb = RotateImg2(b,angle);
int W = ****; //最大值
int H = ****;//最大值
//旋转后图片大小
int w = bb.Width;
int h = bb.Height;
//W×H图像大小背景图像坐标系到图像本身坐标系(旋转后图像)
int move_x = (W - w) / 2 ;
int move_y = (H - h) / 2 ;
Bitmap aa = new Bitmap(W , H);//建立背景图片,在此基础上绘制
for (int ii = 0; ii < W; ii++)
{
for (int jj = 0; jj < H; jj++)
{
aa.SetPixel(ii, jj, Color.FromArgb(255, 255, 255));
}
};
Graphics g01 = Graphics.FromImage(aa);
g01.TranslateTransform(move_x, move_y);//坐标系平移
g01.DrawImage(bb, new PointF(0, 0));//坐标系平移后绘制图片
int x = (W-p)/2;
int y = (H-q)/2;
//裁剪图片外围空白区域
Rectangle cropRegion = new Rectangle(x,y, p, q);
Bitmap cc = CropImage(aa, cropRegion); //最终的图像数据
return cc
}
//裁剪图像
public Bitmap CropImage(Bitmap originImage, Rectangle region)
{
Bitmap result = new Bitmap(region.Width, region.Height);
Graphics graphics = Graphics.FromImage(result);
graphics.DrawImage(originImage, new Rectangle(0, 0, region.Width, region.Height), region, GraphicsUnit.Pixel);
return result;
}