レイヤーを使った簡単な画像編集ソフトに矩形を挿入します。矩形は回転も可能で内部を塗りつぶすことも可能です。
矩形をつくるためには境界線の色、塗りつぶすのであれば内部の色、回転角、縦、横の長さを指定する必要があります。回転する場合は矩形そのものの縦横だけでなく、表示されるBitmapの縦横も考えないといけません。
まずレイヤーを管理するクラスを作成します。
矩形を描画するのであれば矩形の幅と高さがわかれば描画できます。ただこの矩形は回転することもあります。そこでRotateRectangle(Rectangle rect, Color color, Color innerColor, int angle, bool isHighQuality)メソッドで回転した状態の矩形が描画されたBitmapを取得するメソッドを作成します。
そしてその戻り値をフィールド変数_bitmapに格納します。Bitmapプロパティは_bitmap == nullでなければ_bitmapをそのまま返します。RectangleWidthプロパティ、RectangleHeightプロパティ、SelectColorArgbプロパティ、SelectInnerColorArgbプロパティ、Angleプロパティに値がセットされるとRotateRectangle(Rectangle rect, Color color, Color innerColor, int angle, bool isHighQuality)メソッドが実行されるため、Bitmapプロパティから矩形が描画されたBitmapを取得することができます。
RectangleLayer.Bitmapプロパティで得られたBitmapをそのまま表示することはできません。これとは別にフィールド変数 Widthや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 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 |
public class RectangleLayer : Layer { [System.Xml.Serialization.XmlIgnore] public override Bitmap Bitmap { get { if (_bitmap == null) { Rectangle rect = new Rectangle(0, 0, RectangleWidth, RectangleHeight); _bitmap = RotateRectangle(rect, Color.FromArgb(SelectColorArgb), Color.FromArgb(SelectInnerColorArgb), Angle, true); } return _bitmap; } } public void CopyLayer(RectangleLayer source) { _rectangleWidth = source.RectangleWidth; _rectangleHeight = source.RectangleHeight; _selectColorArgb = source.SelectColorArgb; _selectInnerColorArgb = source.SelectInnerColorArgb; _angle = source.Angle; Name = source.Name; Width = source.Width; Height = source.Height; X = source.X; Y = source.Y; Z = source.Z; } Bitmap _bitmap = null; public Bitmap RotateRectangle(Rectangle rect, Color color, Color innerColor, int angle, bool isHighQuality) { Bitmap sourceBitmap = new Bitmap(rect.Width+1, rect.Height + 1); Graphics g = Graphics.FromImage(sourceBitmap); g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; if(innerColor != Color.Empty) g.FillRectangle(new SolidBrush(innerColor), rect); g.DrawRectangle(new Pen(color), rect); g.Dispose(); // 矩形を描画するために必要な点をリストに格納する // 回転処理でDrawImageメソッドに渡す点はこのなかの3点である。 List<Point> points = new List<Point>(); points.Add(new Point(0, 0)); // DrawImageメソッドに渡す点 points.Add(new Point(rect.Width, 0)); // DrawImageメソッドに渡す点 points.Add(new Point(rect.Width, rect.Height)); points.Add(new Point(0, rect.Height)); // DrawImageメソッドに渡す点 points.Add(new Point(0, 0)); points = points.Select(x => new Point(x.X - rect.Width / 2, x.Y - rect.Height / 2)).ToList(); { double rad = Math.PI * angle / 180; List<Point> points2 = new List<Point>(); foreach (Point pt in points) { int x = (int)Math.Round(pt.X * Math.Cos(rad) + pt.Y * Math.Sin(rad)); int y = (int)Math.Round(-pt.X * Math.Sin(rad) + pt.Y * Math.Cos(rad)); points2.Add(new Point(x, y)); } points = points2; } int widthHalf = points.Max(x => Math.Abs(x.X)); int heightHalf = points.Max(x => Math.Abs(x.Y)); int newWidth = widthHalf * 2; int newHeight = heightHalf * 2; points = points.Select(x => new Point(x.X + widthHalf, x.Y + heightHalf)).ToList(); Bitmap bitmap = new Bitmap(newWidth+1, newHeight+1); Graphics g2 = Graphics.FromImage(bitmap); if (isHighQuality) g2.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; else g2.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor; List<Point> points1 = new List<Point>(points); if (innerColor != Color.Empty) { points.RemoveAt(4); points.RemoveAt(2); g2.DrawImage(sourceBitmap, points.ToArray(), new Rectangle(0, 0, sourceBitmap.Width, sourceBitmap.Height), GraphicsUnit.Pixel); } // 輪郭だけ描画する場合、Graphics.DrawImage(Bitmap, Point[],Rectangle, GraphicsUnit)では線が途切れてうまく描画できない場合があるので Graphics.DrawImage(Pen, Point[])メソッドを使う g2.DrawLines(new Pen(color), points1.ToArray()); g2.Dispose(); sourceBitmap.Dispose(); return bitmap; } int _rectangleWidth = 0; public int RectangleWidth { get { return _rectangleWidth; } set { _rectangleWidth = value; if (RectangleWidth > 0 && RectangleHeight > 0) { Rectangle rect = new Rectangle(0, 0, RectangleWidth, RectangleHeight); _bitmap = RotateRectangle(rect, Color.FromArgb(SelectColorArgb), Color.FromArgb(SelectInnerColorArgb), Angle, true); } else _bitmap = null; } } public int _rectangleHeight = 0; public int RectangleHeight { get { return _rectangleHeight; } set { _rectangleHeight = value; if (RectangleWidth > 0 && RectangleHeight > 0) { Rectangle rect = new Rectangle(0, 0, RectangleWidth, RectangleHeight); _bitmap = RotateRectangle(rect, Color.FromArgb(SelectColorArgb), Color.FromArgb(SelectInnerColorArgb), Angle, true); } else _bitmap = null; } } int _selectColorArgb = Color.Black.ToArgb(); public int SelectColorArgb { get { return _selectColorArgb; } set { _selectColorArgb = value; if (RectangleWidth > 0 && RectangleHeight > 0) { Rectangle rect = new Rectangle(0, 0, RectangleWidth, RectangleHeight); _bitmap = RotateRectangle(rect, Color.FromArgb(SelectColorArgb), Color.FromArgb(SelectInnerColorArgb), Angle, true); } else _bitmap = null; } } public int _selectInnerColorArgb = 0; public int SelectInnerColorArgb { get { return _selectInnerColorArgb; } set { _selectInnerColorArgb = value; if (RectangleWidth > 0 && RectangleHeight > 0) { Rectangle rect = new Rectangle(0, 0, RectangleWidth, RectangleHeight); _bitmap = RotateRectangle(rect, Color.FromArgb(SelectColorArgb), Color.FromArgb(SelectInnerColorArgb), Angle, true); } else _bitmap = null; } } int _angle = 0; public int Angle { get { return _angle; } set { _angle = value; if (RectangleWidth > 0 && RectangleHeight > 0) { Rectangle rect = new Rectangle(0, 0, RectangleWidth, RectangleHeight); _bitmap = RotateRectangle(rect, Color.FromArgb(SelectColorArgb), Color.FromArgb(SelectInnerColorArgb), Angle, true); } else _bitmap = null; } } } |
今回は矩形を挿入するために必要なレイヤーのクラスを作成しました。次回はダイアログを表示させて編集中の画像のなかに矩形を表示させる処理をおこないます。