■ はじめに
https://blogs.yahoo.co.jp/dk521123/37853430.htmlの続き。
画像を任意の角度で回転させる方法
画像を任意の角度で回転させるために、以下の方法がある [1] Graphics.RotateTransform()を使う => 以下の「■ サンプル」の「例1」を参照 [2] Matrix(アフィン変換)クラスを利用する => 以下の「■ サンプル」の「例2」を参照 [3] アフィン変換などで自作する => 以下の関連記事を参照のことhttps://blogs.yahoo.co.jp/dk521123/38093149.html
■ サンプル
例1:Graphics.RotateTransform()を使う方法
using System; using System.Drawing; using System.Drawing.Drawing2D; using System.Windows.Forms; namespace SampleForm { public partial class Form1 : Form { /// <summary> /// オリジナルのビットマップ /// </summary> private Bitmap originalBitmap = null; /// <summary> /// 現在の回転角度 /// </summary> private float currentAngle = 0f; public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { // 画像ファイルのImageオブジェクトを作成する this.originalBitmap = new Bitmap(@"20161215052204.gif"); this.pictureBox1.Image = this.originalBitmap; } private void button1_Click(object sender, EventArgs e) { var image = this.pictureBox1.Image; if (image != null && this.originalBitmap != null && this.originalBitmap != image) { Console.WriteLine("オリジナル以外の回転画像をDispose"); image.Dispose(); } // 角度決める if (this.checkBox1.Checked) { // 逆回転 this.currentAngle = this.currentAngle - 5.0f; } else { // 回転 this.currentAngle = this.currentAngle + 5.0f; } // 回転する this.pictureBox1.Image = this.Rotate( this.originalBitmap, this.currentAngle, this.originalBitmap.Width / 2, this.originalBitmap.Height / 2); } /// <summary> /// ビットマップ(Bitmap)を回転する /// </summary> /// <param name="targetBitmap">ビットマップ</param> /// <param name="angle">回転角度</param> /// <param name="x">中心点X</param> /// <param name="y">中心点Y</param> /// <returns></returns> public Bitmap Rotate(Bitmap targetBitmap, float angle, int x, int y) { Bitmap clonedBitmap = new Bitmap(targetBitmap.Width, targetBitmap.Height); using (var graphics = Graphics.FromImage(clonedBitmap)) { // まずは背景色を黒くする graphics.Clear(Color.Black); // ★回転させる★ graphics.TranslateTransform(-x, -y); // ★ここ★ graphics.RotateTransform(angle, MatrixOrder.Append); graphics.TranslateTransform(x, y, MatrixOrder.Append); // 高品質双三次補間を指定 graphics.InterpolationMode = InterpolationMode.HighQualityBilinear; // 描画(指定された位置に元の物理サイズで描画) graphics.DrawImageUnscaled(targetBitmap, 0, 0); } return clonedBitmap; } } }
例2:Matrix(アフィン変換)クラスを利用する
* 以下の関連記事で行ったサンプルに回転処理を追加するhttps://blogs.yahoo.co.jp/dk521123/37866101.html
using System.Drawing; using System.Drawing.Drawing2D; using System.Windows.Forms; namespace ImageViewer { public partial class Form1 : Form { // ★アフィン変換 ★ private Matrix affineTransformation = new Matrix(); private RectangleF sourceRectangle; private PointF[] sourcePoints = new PointF[3]; private Graphics graphics = null; private Image image = null; private Bitmap bitmap; private Point oldPoint = Point.Empty; private bool IsDragging { get { return !this.oldPoint.IsEmpty; } } public Form1() { InitializeComponent(); // ホイールイベントの追加 this.pictureBox1.MouseWheel += new MouseEventHandler(this.pictureBox1_MouseWheel); } private void Form1_Load(object sender, System.EventArgs e) { this.Resize(); this.OpenImageFile(@"20161215052204.gif"); } // マウスホイールイベント private void pictureBox1_MouseWheel(object sender, MouseEventArgs e) { this.affineTransformation.Translate(-e.X, -e.Y, MatrixOrder.Append); if (e.Delta > 0) { // 拡大 if (this.affineTransformation.Elements[0] < 100) { this.affineTransformation = this.GetAffineTransformationToScale( this.affineTransformation, 1.5f, e.Location); } } else { // 縮小 if (this.affineTransformation.Elements[0] > 0.01) { this.affineTransformation = this.GetAffineTransformationToScale( this.affineTransformation, 1.0f / 1.5f, e.Location); } } this.affineTransformation.Translate(e.X, e.Y, MatrixOrder.Append); } private Matrix GetAffineTransformationToScale( Matrix matrix, float scale, Point point) { // 原点へ移動 matrix.Translate(-point.X, -point.Y, MatrixOrder.Append); // 拡大縮小 matrix.Scale(scale, scale, MatrixOrder.Append); // 元へ戻す matrix.Translate(point.X, point.Y, MatrixOrder.Append); return matrix; } private void OpenImageFile(string fileName) { if (string.IsNullOrEmpty(fileName)) { return; } if (this.image != null) { this.image.Dispose(); } if (this.bitmap != null) { this.bitmap.Dispose(); } this.image = Image.FromFile(fileName); this.bitmap = new Bitmap(this.image); this.sourceRectangle = new RectangleF(-0.5f, -0.5f, this.image.Width, this.image.Height); this.sourcePoints[0] = new PointF(this.sourceRectangle.Left, this.sourceRectangle.Top); this.sourcePoints[1] = new PointF(this.sourceRectangle.Right, this.sourceRectangle.Top); this.sourcePoints[2] = new PointF(this.sourceRectangle.Left, this.sourceRectangle.Bottom); this.DrawImage(); } private void Resize() { if ((this.pictureBox1.Width == 0) || (this.pictureBox1.Height == 0)) { return; } var bmpPicBox = new Bitmap(this.pictureBox1.Width, this.pictureBox1.Height); this.pictureBox1.Image = bmpPicBox; this.graphics = Graphics.FromImage(this.pictureBox1.Image); this.graphics.InterpolationMode = InterpolationMode.NearestNeighbor; this.DrawImage(); } // ビットマップの描画 private void DrawImage() { if (this.image == null) { return; } if (this.bitmap == null) { return; } this.graphics.Clear(this.pictureBox1.BackColor); var destinationPoints = (PointF[])this.sourcePoints.Clone(); this.affineTransformation.TransformPoints(destinationPoints); this.graphics.DrawImage(this.bitmap, destinationPoints, this.sourceRectangle, GraphicsUnit.Pixel); this.pictureBox1.Refresh(); } private void pictureBox1_Resize(object sender, System.EventArgs e) { this.Resize(); } private void pictureBox1_MouseDown(object sender, MouseEventArgs e) { this.pictureBox1.Focus(); this.oldPoint.X = e.X; this.oldPoint.Y = e.Y; } private void pictureBox1_MouseMove(object sender, MouseEventArgs e) { if (!this.IsDragging) { return; } // 移動 this.affineTransformation.Translate( e.X - this.oldPoint.X, e.Y - this.oldPoint.Y, MatrixOrder.Append); this.DrawImage(); this.oldPoint.X = e.X; this.oldPoint.Y = e.Y; } private void pictureBox1_MouseUp(object sender, MouseEventArgs e) { this.oldPoint = Point.Empty; } // ★ここを追加★ private void button1_Click(object sender, System.EventArgs e) { this.graphics.RotateTransform( float.Parse(this.textBox1.Text), MatrixOrder.Append); this.DrawImage(); } } }
参考文献
https://imagingsolution.net/program/globaltransformations/https://imagingsolution.net/programming/csharp/csharp_for_image_processing/
例1
http://nonsoft.la.coocan.jp/SoftSample/CS.NET/SampleRotateBitmap.html例2
https://dobon.net/vb/dotnet/graphics/skewing.htmlhttps://dobon.net/vb/dotnet/graphics/transform.html
関連記事
Windows Form
Windows Form ~ 目次 ~https://blogs.yahoo.co.jp/dk521123/8054245.html
PictureBox [3] ~ マウスホイール で画像の拡大・縮小する ~
https://blogs.yahoo.co.jp/dk521123/37866101.html
PictureBox [10] ~ 画像をレイヤー構造で扱う ~
https://blogs.yahoo.co.jp/dk521123/38055633.html
画像処理
画像処理 ~ 回転 ~https://blogs.yahoo.co.jp/dk521123/37853430.html
画像処理 ~ アフィン変換・Matrixクラス ~
https://blogs.yahoo.co.jp/dk521123/38061211.html
画像処理 ~ アフィン変換で任意角度の回転を自作する ~
https://blogs.yahoo.co.jp/dk521123/38093149.html