【C#】ドラッグで短形選択し、画像を切り取って表示する

7月 26, 2022

C#に触れる機会があり、マウスドラッグでの短形選択→画像切り取りで少し悩んだので覚えとして記録しておきます。

ドラッグで短形選択し、画像を切り取って表示

今回使用した環境

インターネット接続可能のオンラインの環境

64 ビット オペレーティング システム

Windows 10 21H1

Visual Studio 2022 C# .NET Framework 4.8

フォームデザイン

フォームの中にPictureBoxを2つ配置し、「pictureBox1」には切り取りを行う元の画像、「pictureBox2」には切り取り後の画像を表示することとします。

動作イメージ

マウスドラッグで短形選択することで、選択された領域を画面右側に表示します。

ソースコード

using System;
using System.Drawing;
using System.Windows.Forms;

namespace ImageCut
{
    public partial class Form1 : Form
    {

        // ドラッグ開始位置 ( 短形選択開始点 )
        private Point _startPoint;

        // ドロップ位置 ( 短形選択終了点 )
        private Point _endPoint;

        // 切り取り前のオリジナル画像
        private Image _srcImage;

        // 切り取り前のオリジナル画像 ( バックアップ )
        private Image _srcImageBk;
        
        public Form1()
        {
            InitializeComponent();
        }

        // フォームロード時
        private void Form1_Load(object sender, EventArgs e)
        {
            _srcImage = Image.FromFile("D:\\image\\bike.jpeg");
            _srcImageBk = (Image)_srcImage.Clone();
            pictureBox1.Image = _srcImage;
        }

        // マウスダウン時
        private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
        {
            // ドラッグ開始位置を取得
            _startPoint.X = e.X;
            _startPoint.Y = e.Y;
        }

        private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                // 切り取り中の幅、高さを取得
                int cuttingWidth = Math.Abs(e.X - _startPoint.X);
                int cuttingHeight = Math.Abs(e.Y - _startPoint.Y);

                // バックアップして置いたオリジナルのイメージで描画してから選択中の短形を描画
                using (Graphics g = Graphics.FromImage(_srcImage))
                {
                    g.DrawImage(_srcImageBk, 0, 0);
                    g.DrawRectangle(Pens.Black, (e.X - _startPoint.X >= 0) ? _startPoint.X : _startPoint.X - cuttingWidth,
                                                (e.Y - _startPoint.Y >= 0) ? _startPoint.Y : _startPoint.Y - cuttingHeight,
                                                cuttingWidth, cuttingHeight);
                }

                // pictureBox1に選択中の短形を表示
                pictureBox1.Refresh();
            }
        }

        // マウスアップ時
        private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
        {
            // pictureBox1の短形選択を消去
            using (Graphics g = Graphics.FromImage(_srcImage))
            {
                g.DrawImage(_srcImageBk, 0, 0);
            }
            pictureBox1.Refresh();
            
            // ドロップ位置を取得
            _endPoint.X = e.X;
            _endPoint.Y = e.Y;

            // 切り取り後の幅、高さを取得
            int cuttingWidth = Math.Abs(_endPoint.X - _startPoint.X);
            int cuttingHeight = Math.Abs(_endPoint.Y - _startPoint.Y);

            // 描画位置
            Rectangle destRect = new Rectangle(0, 0, cuttingWidth, cuttingHeight);

            // 切り取る短形
            Rectangle srcRect = new Rectangle((_endPoint.X - _startPoint.X >= 0) ? _startPoint.X : _startPoint.X - cuttingWidth,
                                              (_endPoint.Y - _startPoint.Y >= 0) ? _startPoint.Y : _startPoint.Y - cuttingHeight,
                                              cuttingWidth, cuttingHeight);

            // 切り取り後の幅、高さでBitmapインスタンスを生成
            Bitmap cuttingImage = new Bitmap(cuttingWidth, cuttingHeight);

            // 描画
            using (Graphics g = Graphics.FromImage(cuttingImage))
            {
                g.DrawImage(_srcImage, destRect, srcRect, GraphicsUnit.Pixel);
            }

            // pictureBox2に切り取り後の画像を表示
            pictureBox2.Image = cuttingImage;
            pictureBox2.Refresh();
        }
    }
}

※上記ソースは左上→右下のドラッグ方向だけではなく、あらゆる方向へのドラッグに対応させた結果、申し訳ありませんが、若干ソースとして見にくくなっています。55行目や87行目の三項演算子がそれにあたります。

動作確認

短形選択した画像が切り取られ、画面右側に表示されました。

以上となります。

ここまでお読みいただきありがとうございました。

C#

Posted by だゆう