画像にモザイクをかけるアプリを作成します。
画像全体にモザイクをかける
まずは画像全体にモザイクをかけるプログラムを作成します。ボタンをクリックすると[ファイルを開く]ダイアログが出てきて選択したファイルが画像ファイルであれば、そこにoutputというフォルダを作成してそのなかにファイルを保存します。
自作メソッドであるPixelizationメソッドをつかって画像にモザイクをかけます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
public partial class Form1 : Form { private void button1_Click(object sender, EventArgs e) { OpenFileDialog dialog = new OpenFileDialog(); if(dialog.ShowDialog() == DialogResult.OK) { string filePath = dialog.FileName; FileInfo info = new FileInfo(filePath); string outputFolderPath = info.DirectoryName + "\\output"; if(!Directory.Exists(outputFolderPath)) Directory.CreateDirectory(outputFolderPath); string outputFilePath = outputFolderPath + "\\" + info.Name; Pixelization(filePath, outputFilePath); } } } |
Pixelizationメソッドはファイルが画像ファイルであればそれにモザイクをかけます。
イメージを10ピクセルで分割してそのなかから平均的な色を取得します。平均的な色とは赤、緑、青の要素の値の平均値から作り出される色のことです。取得した色で新しいビットマップを作成してこれをファイルとして保存しています。
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 |
public partial class Form1 : Form { const int PixelSize = 10; void Pixelization(string filePath, string outputFilePath) { Image image; try { image = Image.FromFile(filePath); } catch { return; } int width = image.Width; int height = image.Height; Bitmap bitmap = (Bitmap)image; Bitmap newBitmap = new Bitmap(width, height); for(int x =0; x< width/ PixelSize + 1; x++) { for(int y = 0; y < height/ PixelSize + 1; y++) { Color color = GetPixel(bitmap, x, y); SetPixel(newBitmap, x, y, color); } } newBitmap.Save(outputFilePath); newBitmap.Dispose(); image.Dispose(); } Color GetPixel(Bitmap bitmap, int colum, int row) { List<Color> colors = new List<Color>(); int width = bitmap.Width; int height = bitmap.Height; for(int x = colum * PixelSize; x < (colum + 1) * PixelSize; x++) { for(int y = row * PixelSize; y < (row + 1) * PixelSize; y++) { if(x < width && y < height) colors.Add(bitmap.GetPixel(x, y)); } } if(colors.Count == 0) return Color.White; int r = (int)colors.Average(x => x.R); int g = (int)colors.Average(x => x.G); int b = (int)colors.Average(x => x.B); return Color.FromArgb(r, g, b); } void SetPixel(Bitmap bitmap, int colum, int row, Color color) { int width = bitmap.Width; int height = bitmap.Height; for(int x = colum * PixelSize; x < (colum + 1) * PixelSize; x++) { for(int y = row * PixelSize; y < (row + 1) * PixelSize; y++) { if(x < width && y < height) bitmap.SetPixel(x, y, color); } } } } |
選択された範囲だけモザイクをかける
次に画像全体ではなく選択された範囲だけにモザイクをかける処理をするプログラムを作成します。
このようにフォームにピクチャーボックスを貼り付けたものを作成します。
コンストラクタではピクチャーボックスをフォーム内いっぱいに表示させる処理とマウスがクリックされたり移動したときのイベントハンドラを定義しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
public partial class Form1 : Form { public Form1() { InitializeComponent(); pictureBox1.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right; pictureBox1.MouseDown += PictureBox1_MouseDown; pictureBox1.MouseMove += PictureBox1_MouseMove; pictureBox1.MouseUp += PictureBox1_MouseUp; pictureBox1.Paint += PictureBox1_Paint; } } |
メニューの[ファイルを開く]が選択されたら画像ファイルのイメージをピクチャーボックスに表示します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
public partial class Form1 : Form { private void OpenFileMenuItem_Click(object sender, EventArgs e) { OpenFileDialog dialog = new OpenFileDialog(); if(dialog.ShowDialog() == DialogResult.OK) { string filePath = dialog.FileName; try { Image = Image.FromFile(filePath); pictureBox1.Image = Image; } catch { MessageBox.Show("これは画像ファイルではありません", "", MessageBoxButtons.OK, MessageBoxIcon.Error); } } dialog.Dispose(); } } |
ピクチャーボックスでマウスがクリックされたらisMouseDownフラグをセットしてドラッグが開始された点の座標を保存します。
1 2 3 4 5 6 7 8 9 10 11 12 |
public partial class Form1 : Form { bool isMouseDown = false; Point start = new Point(); Point end = new Point(); private void PictureBox1_MouseDown(object sender, MouseEventArgs e) { isMouseDown = true; start = new Point(e.X, e.Y); } } |
マウスがドラッグされたら(isMouseDownフラグがセットされている状態でマウスが移動したら)選択されている部分がわかるように長方形を描画します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
public partial class Form1 : Form { private void PictureBox1_MouseMove(object sender, MouseEventArgs e) { if(isMouseDown) { pictureBox1.Invalidate(); end = new Point(e.X, e.Y); } } private void PictureBox1_Paint(object sender, PaintEventArgs e) { Rectangle rect = GetRectangle(start, end); e.Graphics.DrawRectangle(new Pen(Color.Black), rect); } } |
GetRectangleメソッドは2点から矩形を取得するためのメソッドです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
public partial class Form1 : Form { Rectangle GetRectangle(Point pt1, Point pt2) { if(pt1.X < pt2.X) { if(pt1.Y < pt2.Y) return new Rectangle(pt1, new Size(pt2.X - pt1.X, pt2.Y - pt1.Y)); else return new Rectangle(new Point(pt1.X, pt2.Y), new Size(pt2.X - pt1.X, -(pt2.Y - pt1.Y))); } else { if(pt1.Y < pt2.Y) return new Rectangle(new Point(pt2.X, pt1.Y), new Size(pt1.X - pt2.X, pt2.Y - pt1.Y)); else return new Rectangle(pt2, new Size(pt1.X - pt2.X, pt1.Y - pt2.Y)); } } } |
マウスが離されたらフラグをクリアします。
1 2 3 4 5 6 7 8 9 |
public partial class Form1 : Form { private void PictureBox1_MouseUp(object sender, MouseEventArgs e) { isMouseDown = false; pictureBox1.Invalidate(); end = new Point(e.X, e.Y); } } |
[ファイルを保存する]が選択されたら矩形内の部分だけモザイクをかけて画像をファイルとして保存します。
矩形内をトリミングしてその部分だけモザイクをかけます。そして画像全体と合成してファイルとして保存します。
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 |
public partial class Form1 : Form { private void SaveFileMenuItem_Click(object sender, EventArgs e) { if(start.IsEmpty || end.IsEmpty) { MessageBox.Show("範囲選択されていません", "", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } if(Image == null) { MessageBox.Show("ファイルが選択されていません", "", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } //トリミングした部分にモザイクをかける Rectangle trimingRect = GetRectangle(start, end); Bitmap trimingBmp = new Bitmap(trimingRect.Width, trimingRect.Height); Graphics trimingGraphics = Graphics.FromImage(trimingBmp); trimingGraphics.DrawImage(Image, new Rectangle(0, 0, trimingRect.Width, trimingRect.Height), trimingRect, GraphicsUnit.Pixel); Bitmap newbmp = Pixelization(trimingBmp); trimingGraphics.Dispose(); trimingBmp.Dispose(); // 出力用のビットマップをつくる Bitmap outputBmp = new Bitmap(Image.Width, Image.Height); Graphics outputGraphics = Graphics.FromImage(outputBmp); outputGraphics.DrawImage(Image, new Rectangle(0, 0, Image.Width, Image.Height)); outputGraphics.DrawImage(newbmp, trimingRect); outputGraphics.Dispose(); newbmp.Dispose(); SaveFileDialog dialog = new SaveFileDialog(); if(dialog.ShowDialog() == DialogResult.OK) { outputBmp.Save(dialog.FileName); } outputBmp.Dispose(); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
public partial class Form1 : Form { Bitmap Pixelization(Bitmap bitmap) { int width = bitmap.Width; int height = bitmap.Height; Bitmap newBitmap = new Bitmap(width, height); for(int x = 0; x < width / PixelSize + 1; x++) { for(int y = 0; y < height / PixelSize + 1; y++) { Color color = GetPixel(bitmap, x, y); SetPixel(newBitmap, x, y, color); } } return newBitmap; } } |
メニューの[範囲選択をクリア]を選択するとstartとendのデータをクリアして範囲選択を解除します。
1 2 3 4 5 6 7 8 9 |
public partial class Form1 : Form { private void ClearSelectionMenuItem_Click(object sender, EventArgs e) { start = new Point(); end = new Point(); pictureBox1.Invalidate(); } } |