拡大・縮小・トリミング・回転の処理ができる自作ライブラリです。
Contents
自作メソッドについて
Image GetExtendBitmap(Image image, double extend)
画像を拡大・縮小する
Image GetTrimingBitmap(Image image, Rectangle rect)
画像をトリミングする
Image GetCutOffImage(Image image, int top, int right, int bottom, int left)
画像の上下左右を切り捨てる
Image GetRotateImage(Image image, int Rotate)
画像を回転させる(第二引数は度数法)
Image GetRotateImageInSize(Image image, int rotate, int width, int height)
回転させた画像で指定した幅・高さに収まる大きさの画像を取得する
Image GetInscribedRotateImage(Image image, int rotate, int width, int height)
回転させた画像で指定した幅・高さの矩形に内接する画像を取得する
簡単な説明
画像の回転はアフィン変換を用いています。左上、右上、左下の座標に対して回転の変換をしたあと、領域内におさまるように平行移動させています。
GetRotateImage(Image image, int Rotate)メソッドは画像を回転させることで画像のサイズが変更されます。GetRotateImageInSize(Image image, int rotate, int width, int height)メソッドは縦横の比は維持された状態で中央に表示されます。そのため指定されたサイズいっぱいには表示されません。
GetInscribedRotateImage(Image image, int rotate, int width, int height)メソッドは指定されたサイズの矩形に内接する画像なのでサイズいっぱいに表示されますが、画像の縦横の比は維持されず、画像の形状も平行四辺形になります。
作成したコード
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 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 |
using System.Linq; using System.Drawing; public class ImageEx { public static Image GetExtendImage(Image image, double extend) { int newWidth = (int)(image.Width * extend); int newHeight = (int)(image.Height * extend); return new Bitmap(image, new Size(newWidth, newHeight)); } public static Image GetTrimingImage(Image image, Rectangle rect) { if(rect.Width == 0 || rect.Height == 0) return null; Rectangle srcRect = rect; Rectangle destRect = new Rectangle(0, 0, rect.Width, rect.Height); Bitmap bitmap = new Bitmap(rect.Width, rect.Height); Graphics g = Graphics.FromImage(bitmap); g.DrawImage(image, destRect, srcRect, GraphicsUnit.Pixel); g.Dispose(); return bitmap; } public static Image GetCutOffImage(Image image, int top, int right, int bottom, int left) { int oldWidth = image.Width; int oldHeight = image.Height; Rectangle srcRect = new Rectangle(left, top, oldWidth - left - right, oldHeight - top - bottom); Rectangle destRect = new Rectangle(0, 0, oldWidth - left - right, oldHeight - top - bottom); if(oldWidth - left - right < 1 || oldHeight - top - bottom < 1) return null; Bitmap bitmap = new Bitmap(oldWidth - left - right, oldHeight - top - bottom); Graphics g = Graphics.FromImage(bitmap); g.DrawImage(image, destRect, srcRect, GraphicsUnit.Pixel); g.Dispose(); return bitmap; } public static Image GetRotateImage(Image image, int rotate) { var srcRect = new RectangleF(-0.5f, -0.5f, image.Width, image.Height); PointF center = new PointF(image.Width / 2F, image.Height / 2F); System.Drawing.Drawing2D.Matrix matAffine = new System.Drawing.Drawing2D.Matrix(); matAffine.RotateAt(rotate, center); // 描画先の座標(描画元に合わせる、左上、右上、左下の順) var points = 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), // 右下 }; // 描画先の座標をアフィン変換で求める(変換後の座標は上書きされる) matAffine.TransformPoints(points); matAffine.Reset(); // もう一回使うのでリセット // これでは座標が負数の部分は表示されないので全部表示されるように平行移動させる // 必要な平行移動量を計算 float minX = points.Min(x => x.X); float minY = points.Min(x => x.Y); matAffine.Translate(-minX, -minY); matAffine.TransformPoints(points); matAffine.Dispose(); Bitmap newBitmap = new Bitmap((int)points.Max(x=>x.X), (int)points.Max(x => x.Y)); Graphics g = Graphics.FromImage(newBitmap); // DrawImageメソッドの第二引数は3つの点(左上、右上、左下の順) g.DrawImage(image, points.Take(3).ToArray(), srcRect, GraphicsUnit.Pixel); g.Dispose(); return newBitmap; } public static Image GetRotateImageInSize(Image image, int rotate, int width, int height) { Image image1 = GetRotateImage(image, rotate); var srcRect = new RectangleF(-0.5f, -0.5f, image1.Width, image1.Height); int oldWidth = image1.Width; int oldHeight = image1.Height; float xRate = (float)width / oldWidth; float yRate = (float)height / oldHeight; float rate = xRate > yRate ? yRate : xRate; System.Drawing.Drawing2D.Matrix matAffine = new System.Drawing.Drawing2D.Matrix(); matAffine.Scale(rate, rate); // 描画先の座標(いまは描画元の座標) var points = new PointF[] { new PointF(srcRect.Left, srcRect.Top), new PointF(srcRect.Right, srcRect.Top), new PointF(srcRect.Left, srcRect.Bottom), }; // 描画先の座標をアフィン変換で求める matAffine.TransformPoints(points); matAffine.Reset(); // 中心になるように平行移動させる int maxX = (int)points.Max(x => x.X); int maxY = (int)points.Max(x => x.Y); int moveX = (width - maxX) / 2; int moveY = (height - maxY) / 2; matAffine.Translate(moveX, moveY); matAffine.TransformPoints(points); matAffine.Dispose(); Bitmap newBitmap = new Bitmap(width, height); Graphics g = Graphics.FromImage(newBitmap); g.DrawImage(image1, points, srcRect, GraphicsUnit.Pixel); g.Dispose(); image1.Dispose(); return newBitmap; } public static Image GetInscribedRotateImage(Image image, int rotate, int width, int height) { Image image1 = GetRotateImage(image, rotate); var srcRect = new RectangleF(-0.5f, -0.5f, image1.Width, image1.Height); int oldWidth = image1.Width; int oldHeight = image1.Height; float xRate = (float)width / oldWidth; float yRate = (float)height / oldHeight; System.Drawing.Drawing2D.Matrix matAffine = new System.Drawing.Drawing2D.Matrix(); matAffine.Scale(xRate, yRate); // 描画先の座標(いまは描画元の座標) var points = new PointF[] { new PointF(srcRect.Left, srcRect.Top), new PointF(srcRect.Right, srcRect.Top), new PointF(srcRect.Left, srcRect.Bottom), }; // 描画先の座標をアフィン変換で求める matAffine.TransformPoints(points); matAffine.Dispose(); Bitmap newBitmap = new Bitmap(width, height); Graphics g = Graphics.FromImage(newBitmap); g.DrawImage(image1, points, srcRect, GraphicsUnit.Pixel); g.Dispose(); image1.Dispose(); return newBitmap; } } |