在C#中旋转图像时如何防止剪裁?

我刚刚经历了一些试图找出如何使图像均匀旋转的东西。 这有效,但现在它正在削减,我不确定如何让它停止…我正在使用这个rotateImage方法:

public static Image RotateImage(Image img, float rotationAngle) { //create an empty Bitmap image Bitmap bmp = new Bitmap(img.Width, img.Height); //turn the Bitmap into a Graphics object Graphics gfx = Graphics.FromImage(bmp); //now we set the rotation point to the center of our image gfx.TranslateTransform((float)bmp.Width / 2, (float)bmp.Height / 2); //now rotate the image gfx.RotateTransform(rotationAngle); gfx.TranslateTransform(-(float)bmp.Width / 2, -(float)bmp.Height / 2); //set the InterpolationMode to HighQualityBicubic so to ensure a high //quality image once it is transformed to the specified size gfx.InterpolationMode = InterpolationMode.HighQualityBicubic; //now draw our new image onto the graphics object gfx.DrawImage(img, new System.Drawing.Point(0, 0)); //dispose of our Graphics object gfx.Dispose(); //return the image return bmp; } 

我尝试将空位图放大,但仅适用于一侧,因为图像固定在位图的左上角。 任何想法,将不胜感激!

我在其他网站上找到了一些帮助。 以下是我最终为那些想要了解的人做的事情:

 // Rotates the input image by theta degrees around center. public static Bitmap RotateImage(Bitmap bmpSrc, float theta) { Matrix mRotate = new Matrix(); mRotate.Translate(bmpSrc.Width / -2, bmpSrc.Height / -2, MatrixOrder.Append); mRotate.RotateAt(theta, new System.Drawing.Point(0, 0), MatrixOrder.Append); using (GraphicsPath gp = new GraphicsPath()) { // transform image points by rotation matrix gp.AddPolygon(new System.Drawing.Point[] { new System.Drawing.Point(0, 0), new System.Drawing.Point(bmpSrc.Width, 0), new System.Drawing.Point(0, bmpSrc.Height) }); gp.Transform(mRotate); System.Drawing.PointF[] pts = gp.PathPoints; // create destination bitmap sized to contain rotated source image Rectangle bbox = boundingBox(bmpSrc, mRotate); Bitmap bmpDest = new Bitmap(bbox.Width, bbox.Height); using (Graphics gDest = Graphics.FromImage(bmpDest)) { // draw source into dest Matrix mDest = new Matrix(); mDest.Translate(bmpDest.Width / 2, bmpDest.Height / 2, MatrixOrder.Append); gDest.Transform = mDest; gDest.DrawImage(bmpSrc, pts); return bmpDest; } } } private static Rectangle boundingBox(Image img, Matrix matrix) { GraphicsUnit gu = new GraphicsUnit(); Rectangle rImg = Rectangle.Round(img.GetBounds(ref gu)); // Transform the four points of the image, to get the resized bounding box. System.Drawing.Point topLeft = new System.Drawing.Point(rImg.Left, rImg.Top); System.Drawing.Point topRight = new System.Drawing.Point(rImg.Right, rImg.Top); System.Drawing.Point bottomRight = new System.Drawing.Point(rImg.Right, rImg.Bottom); System.Drawing.Point bottomLeft = new System.Drawing.Point(rImg.Left, rImg.Bottom); System.Drawing.Point[] points = new System.Drawing.Point[] { topLeft, topRight, bottomRight, bottomLeft }; GraphicsPath gp = new GraphicsPath(points, new byte[] { (byte)PathPointType.Start, (byte)PathPointType.Line, (byte)PathPointType.Line, (byte)PathPointType.Line }); gp.Transform(matrix); return Rectangle.Round(gp.GetBounds()); } 

跟着这些步骤:

  1. 创建空目标图像,其宽度和高度=旋转图像的边界框
  2. 将源图像绘制到目标图像上。 源(0,0)将映射到目的地的(ox,oy)
  3. 现在执行旋转目标图像的步骤。

完成上述步骤的详细信息:

W,H =目的地的宽度和高度

w,h =源的宽度和高度

C = | cos(THETA)|

S = | SIN(THETA)|

w * c + h * s = W.

w * s + h * c = H.

ox =(W – w)/ 2

oy =(H – h)/ 2

 public Bitmap rotateImage(Bitmap b, float angle) { if (angle > 0) { int l = b.Width; int h = b.Height; double an = angle * Math.PI / 180; double cos = Math.Abs(Math.Cos(an)); double sin = Math.Abs(Math.Sin(an)); int nl = (int)(l * cos + h * sin); int nh = (int)(l * sin + h * cos); Bitmap returnBitmap = new Bitmap(nl, nh); Graphics g = Graphics.FromImage(returnBitmap); g.TranslateTransform((float)(nl-l) / 2, (float)(nh-h) / 2); g.TranslateTransform((float)b.Width / 2, (float)b.Height / 2); g.RotateTransform(angle); g.TranslateTransform(-(float)b.Width / 2, -(float)b.Height / 2); g.DrawImage(b, new Point(0, 0)); return returnBitmap; } else return b; } 

旋转的图像可能需要包含更大的位图而不进行裁剪。 计算边界的一种相当简单的方法是将变换矩阵应用于原始边界矩形的角。 由于新位图较大,因此必须绘制原始图像使其居中,而不是(0,0)。

在您的代码的以下修订版中对此进行了演示:

 public static Image RotateImage(Image img, float rotationAngle) { int minx = int.MaxValue, maxx = int.MinValue, miny = int.MaxValue, maxy = int.MinValue; using (Bitmap bmp = new Bitmap(1, 1)) // Dummy bitmap, so we can use TransformPoints to figure out the correct size. { using (Graphics g = Graphics.FromImage(bmp)) { g.TranslateTransform((float)img.Width / 2, (float)img.Height / 2); g.RotateTransform(rotationAngle); g.TranslateTransform(-(float)img.Width / 2, -(float)img.Height / 2); Point[] pts = new Point[4]; pts[0] = new Point(0, 0); pts[1] = new Point(img.Width, 0); pts[2] = new Point(img.Width, img.Height); pts[3] = new Point(0, img.Height); g.TransformPoints(CoordinateSpace.Device, CoordinateSpace.World, pts); foreach (Point pt in pts) { minx = Math.Min(minx, pt.X); maxx = Math.Max(maxx, pt.X); miny = Math.Min(miny, pt.Y); maxy = Math.Max(maxy, pt.Y); } } } Bitmap bmp2 = new Bitmap(maxx - minx, maxy - miny); using (Graphics g = Graphics.FromImage(bmp2)) { g.TranslateTransform((float)bmp2.Width / 2, (float)bmp2.Height / 2); g.RotateTransform(rotationAngle); g.TranslateTransform(-(float)bmp2.Width / 2, -(float)bmp2.Height / 2); g.InterpolationMode = InterpolationMode.HighQualityBicubic; g.DrawImage(img, bmp2.Width / 2 - img.Width / 2, bmp2.Height / 2 - img.Height / 2); } return bmp2; }