如何旋转图像然后移动到左上角0,0而不切断图像

时间:2011-03-04 21:00:48

标签: c# gdi+

如何旋转图像然后移动到左上角0,0而不切断图像。

请阅读代码中的注释。我陷入了第3步 我认为使用三角法应该能够解决这个问题。

感谢

private Bitmap RotateImage(Bitmap b, float angle)
{
    //create a new empty bitmap to hold rotated image
    Bitmap returnBitmap = new Bitmap(b.Width, b.Height);
    //make a graphics object from the empty bitmap
    Graphics g = Graphics.FromImage(returnBitmap);
    //STEP 1 move rotation point to top left
    g.TranslateTransform((float)0, (float)0);
    //STEP 2 rotate
    g.RotateTransform(angle);
    //STEP 3 move image back to top left without cutting off the image
    //SOME trigonometry calculation here
    int newY = b.Height;
    g.TranslateTransform(-(float)0, -newY);
    //draw passed in image onto graphics object
    g.DrawImage(b, new Point(0, 0));
    return returnBitmap;
}

1 个答案:

答案 0 :(得分:9)

这是否涵盖'三角法'?我已经迈出了第0步,因为我认为你需要先做。这样你就可以计算得到的位图的大小,这将更大 - 请参阅我在代码中的注释。

    private Bitmap RotateImage(Bitmap b, float Angle) {
        // The original bitmap needs to be drawn onto a new bitmap which will probably be bigger 
        // because the corners of the original will move outside the original rectangle.
        // An easy way (OK slightly 'brute force') is to calculate the new bounding box is to calculate the positions of the 
        // corners after rotation and get the difference between the maximum and minimum x and y coordinates.
        float wOver2 = b.Width / 2.0f;
        float hOver2 = b.Height / 2.0f;
        float radians = -(float)(Angle / 180.0 * Math.PI);
        // Get the coordinates of the corners, taking the origin to be the centre of the bitmap.
        PointF[] corners = new PointF[]{
            new PointF(-wOver2, -hOver2),
            new PointF(+wOver2, -hOver2),
            new PointF(+wOver2, +hOver2),
            new PointF(-wOver2, +hOver2)
        };

        for (int i = 0; i < 4; i++) {
            PointF p = corners[i];
            PointF newP = new PointF((float)(p.X * Math.Cos(radians) - p.Y * Math.Sin(radians)), (float)(p.X * Math.Sin(radians) + p.Y * Math.Cos(radians)));
            corners[i] = newP;
        }

        // Find the min and max x and y coordinates.
        float minX = corners[0].X;
        float maxX = minX;
        float minY = corners[0].Y;
        float maxY = minY;
        for (int i = 1; i < 4; i++) {
            PointF p = corners[i];
            minX = Math.Min(minX, p.X);
            maxX = Math.Max(maxX, p.X);
            minY = Math.Min(minY, p.Y);
            maxY = Math.Max(maxY, p.Y);
        }

        // Get the size of the new bitmap.
        SizeF newSize = new SizeF(maxX - minX, maxY - minY);
        // ...and create it.
        Bitmap returnBitmap = new Bitmap((int)Math.Ceiling(newSize.Width), (int)Math.Ceiling(newSize.Height));
        // Now draw the old bitmap on it.
        using (Graphics g = Graphics.FromImage(returnBitmap)) {
            g.TranslateTransform(newSize.Width / 2.0f, newSize.Height / 2.0f);
            g.RotateTransform(Angle);
            g.TranslateTransform(-b.Width / 2.0f, -b.Height / 2.0f);

            g.DrawImage(b, 0, 0);
        }

        return returnBitmap;
    }