Этот ответ возвращает как смещение, на котором он должен быть нарисован, так и изображение, которое было повернуто. Он работает путем воссоздания нового изображения до размера, в котором оно должно быть, без ограничения углов. Первоначально написано Хисенбургом из чата # C # IRC и Bloodyaugust.
public static double NormalizeAngle(double angle)
{
double division = angle / (Math.PI / 2);
double fraction = Math.Ceiling(division) - division;
return (fraction * Math.PI / 2);
}
public static Tuple<Image,Size> RotateImage(Image img, double rotationAngle)
{
double normalizedRotationAngle = NormalizeAngle(rotationAngle);
double widthD = img.Width, heightD = img.Height;
double newWidthD, newHeightD;
newWidthD = Math.Cos(normalizedRotationAngle) * widthD + Math.Sin(normalizedRotationAngle) * heightD;
newHeightD = Math.Cos(normalizedRotationAngle) * heightD + Math.Sin(normalizedRotationAngle) * widthD;
int newWidth, newHeight;
newWidth = (int)Math.Ceiling(newWidthD);
newHeight = (int)Math.Ceiling(newHeightD);
Size offset = new Size((newWidth - img.Width) / 2,(newHeight - img.Height) / 2);
Bitmap bmp = new Bitmap(newWidth, newHeight);
Graphics gfx = Graphics.FromImage(bmp);
//gfx.Clear(Color.Blue);
gfx.TranslateTransform((float)bmp.Width / 2, (float)bmp.Height / 2);
gfx.RotateTransform((float)(rotationAngle / Math.PI * 180));
gfx.TranslateTransform(-(float)bmp.Width / 2, -(float)bmp.Height / 2);
gfx.InterpolationMode = InterpolationMode.HighQualityBicubic;
gfx.DrawImage(img, new PointF((bmp.Width / 2 - img.Width / 2), (bmp.Height / 2 - img.Height / 2)));
gfx.Dispose();
return new Tuple<Image,Size>(bmp,offset);
}