C#:按照给定任意角度旋转图片,旋转后图片大小保持不变

第一步:旋转照片

这里直接使用该博主分享的方法,本文使用的是第二种: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;
        }

至于旋转后,图片大小为什么会变,可以看这个图理解:
C#:按照给定任意角度旋转图片,旋转后图片大小保持不变_第1张图片
一般,我们建立的图片都是矩形的,即是矩阵数据构成的图像,所以旋转后仍然需要保存成矩形的,如上图,旋转后如果想保存成矩形的数据,就需要根据旋转的角度计算新矩形的维度。上面代码中就有根据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;
        }

你可能感兴趣的:(winform,c#,drawing,绘图)