I've got the following code for rotating an image in C#:
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);
//move rotation point to center of image
g.TranslateTransform((float)returnBitmap.Width / 2, (float)returnBitmap.Height / 2);
//rotate
g.RotateTransform(angle);
//move image back
g.TranslateTransform(-(float)b.Width / 2, -(float)b.Height / 2);
//draw passed in image onto graphics object
g.DrawImage(b, new Rectangle(new Point(0, 0), new Size(b.Width, b.Height)));
return returnBitmap;
}
It works very well, except that it clips the result when it exceeds original bounds.
As I understood, I have to set returnBitmap's size to the size of image after rotation. But how do I find how big the result will be, to set size of the new bitmap accordingly?
You need to rotate the four corners of your original image and calculate the bounding box for the new coordinates:
private static Bitmap RotateImage(Image b, float angle)
{
var corners = new[]
{new PointF(0, 0), new Point(b.Width, 0), new PointF(0, b.Height), new PointF(b.Width, b.Height)};
var xc = corners.Select(p => Rotate(p, angle).X);
var yc = corners.Select(p => Rotate(p, angle).Y);
//create a new empty bitmap to hold rotated image
Bitmap returnBitmap = new Bitmap((int)Math.Abs(xc.Max() - xc.Min()), (int)Math.Abs(yc.Max() - yc.Min()));
...
}
/// <summary>
/// Rotates a point around the origin (0,0)
/// </summary>
private static PointF Rotate(PointF p, float angle)
{
// convert from angle to radians
var theta = Math.PI*angle/180;
return new PointF(
(float) (Math.Cos(theta)*(p.X) - Math.Sin(theta)*(p.Y)),
(float) (Math.Sin(theta)*(p.X) + Math.Cos(theta)*(p.Y)));
}