前回はアフィン変換で画像を回転させました。そのままの大きさで回転させると角の部分がはみだしてしまいます。はみださないようにするには元の矩形のサイズを変更する必要があります。
とりあえず回転させて拡大・縮小する割合を調べる
実際に描画したい矩形の中心と画像の中心が一致するように平行移動させる
実際に回転させる
この方法で考えることにします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { Bitmap bitmap = new Bitmap(@"D:\neko.jpg"); int rotate = (int)numericUpDown1.Value; Bitmap newBitmap = RotateImage(bitmap, new Rectangle(new Point(0, 0), new Size(pictureBox2.Width, pictureBox2.Height)), rotate); pictureBox2.Image = newBitmap; } Bitmap RotateImage(Bitmap srcBitmap, Rectangle rect, int Rotate) { Bitmap newBitmap = new Bitmap(rect.Width, rect.Height); using(var g = Graphics.FromImage(newBitmap)) { g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor; var srcRect = new RectangleF(-0.5f, -0.5f, srcBitmap.Width, srcBitmap.Height); // 描画元のビットマップの座標 var pts0 = new PointF[] { new PointF(srcRect.Left, srcRect.Top), new PointF(srcRect.Right, srcRect.Top), new PointF(srcRect.Left, srcRect.Bottom), new PointF(srcRect.Right, srcRect.Bottom), }; // 回転させて矩形からどれくらいはみ出すか調べる System.Drawing.Drawing2D.Matrix matAffine0 = new System.Drawing.Drawing2D.Matrix(); matAffine0.RotateAt(Rotate, new PointF(0, 0), System.Drawing.Drawing2D.MatrixOrder.Append); matAffine0.TransformPoints(pts0); float minX = pts0.Min(x => x.X); float maxX = pts0.Max(x => x.X); float minY = pts0.Min(x => x.Y); float maxY = pts0.Max(x => x.Y); float afterWidth = maxX - minX; float afterHeight = maxY - minY; float extendWidth = afterWidth / rect.Width; float extendHeight = afterHeight / rect.Height; float extendSize = extendWidth > extendHeight ? extendWidth : extendHeight; // 描画元のビットマップの座標 var points = new PointF[] { new PointF(srcRect.Left, srcRect.Top), new PointF(srcRect.Right, srcRect.Top), new PointF(srcRect.Left, srcRect.Bottom), }; // 回転の中心座標を求める Point pt = new Point(rect.Width / 2, rect.Height / 2); // 回転の中心座標に平行移動させるための距離を求める float newWidth = srcBitmap.Width / extendSize; float newHeight = srcBitmap.Height / extendSize; float offsetX = (rect.Width - newWidth) / 2; float offsetY = (rect.Height - newHeight) / 2; System.Drawing.Drawing2D.Matrix matAffine = new System.Drawing.Drawing2D.Matrix(); // 拡大・縮小 matAffine.Scale(1/extendSize, 1 / extendSize, System.Drawing.Drawing2D.MatrixOrder.Append); // 回転の中心座標まで移動させる matAffine.Translate(offsetX, offsetY, System.Drawing.Drawing2D.MatrixOrder.Append); //中心を軸に回転 matAffine.RotateAt(Rotate, pt, System.Drawing.Drawing2D.MatrixOrder.Append); // 描画先の座標をアフィン変換で求める(変換後の座標は上書きされる) matAffine.TransformPoints(points); // 描画 g.DrawImage(srcBitmap, points, srcRect, GraphicsUnit.Pixel); } return newBitmap; } } |