1

How do I rotate image then move to the top left 0,0 without cutting off the image.

Please read the comments inside the code. I got stuck at STEP 3 I think using trigonometry should be able to solve this problem.

thanks

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;
}
NanoHead
  • 159
  • 3
  • 15
  • 1
    `TranslateTransform(0,0)` doesn't do what you think it does. You want `TranslateTransform(b.Width/2, b.Height/2)`. This will place the center of the image at the origin. The rest is beyond me, however. – Mike Caron Mar 04 '11 at 21:07
  • i though moving everything to the 0,0 coordinate would make it a lot more easier to do the sine, cosine, tangent thing. My example doesn't need to move to 0,0 since the image already at 0,0 – NanoHead Mar 04 '11 at 21:12

1 Answers1

9

Does this cover the 'trigonometry'? I have made it step 0 because I think you need to do it first. That way you can calculate the size of the resulting bitmap, which will be bigger - see my comments in the code.

    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;
    }
Richard Cox
  • 491
  • 2
  • 4