簡體   English   中英

在C#中旋轉圖像時如何防止剪裁?

[英]How do I prevent clipping when rotating an image in 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;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM