C#で2枚の画像を表示する。【WinForms】

コンピュータ

2枚の画像の違いを目視で確認するため、画像を並べて表示するソフトを作成してみました。
ファイル名:Form1.cs

using System.Diagnostics;
using System.Windows.Forms.VisualStyles;

using System.Drawing.Drawing2D;

namespace DualViewer;

public partial class Form1 : Form
{
    public Form1()
    {
        // コンポーネント初期化
        InitializeComponent();
        // 定数
        const int _margin = 10;
        // コントロールの初期化
        var viewPanel = new Panel
        {
            BackColor = Color.Pink,
        };
        var leftPanel = new Panel
        {
            BackColor = Color.LightBlue,
        };
        var leftView = new MyPicbox
        {
            Dock = DockStyle.Fill,
            BackColor = Color.Blue,
            AllowDrop = true,
        };
        var rightPanel = new Panel
        {
            BackColor = Color.LightGreen,
        };
        var rightView = new MyPicbox
        {
            Dock = DockStyle.Fill,
            BackColor = Color.Green,
            AllowDrop = true,
        };

        // フォームのロードイベント
        this.Load += (s, e) =>
        {
            rightPanel.Controls.AddRange(new Control[] {rightView});
            leftPanel.Controls.AddRange(new Control[] {leftView});
            viewPanel.Controls.AddRange(new Control[] { leftPanel, rightPanel });
            this.Controls.AddRange(new Control[] {viewPanel});
            this.Size = new System.Drawing.Size(800, 600);
        };
        // フォームのリサイズイベント
        this.Resize += (s, e) =>
        {
            int width = this.ClientSize.Width;
            int height = this.ClientSize.Height;
            if (width == 0 || height == 0) return;
            viewPanel.Size = new System.Drawing.Size(width, height);

            leftPanel.Location = new System.Drawing.Point(_margin, _margin);
            int w = (width - (_margin * 4)) / 2;
            int h = (height - (_margin * 2));
            leftPanel.Size = new System.Drawing.Size(w, h);

            rightPanel.Location = new System.Drawing.Point(_margin*2 + w, _margin);
            rightPanel.Size = new System.Drawing.Size(w, h);
        };
        // 左ビュードラッグアンドドロップイベント
        leftView.DragEnter += (s, e) => {  e.Effect = DragDropEffects.All; };
        leftView.DragDrop += (s, e) =>
        {
            if (e.Data == null) return;
            Object? obj = e.Data.GetData(DataFormats.FileDrop, false);
            if (obj == null) return;
            var path = ((string[])obj)[0];
            leftView.LocalPath = path;
            rightView.Picbox_Reset();
        };
        // 左ビューホイール
        leftView.MouseWheel += (s, e) =>
        {
            rightView.Picbox_MouseWheel(s, e);
        };
        // 右ビュードラッグアンドドロップイベント
        rightView.DragEnter += (s, e) => {  e.Effect = DragDropEffects.All; };
        rightView.DragDrop += (s, e) =>
        {
            if (e.Data == null) return;
            Object? obj = e.Data.GetData(DataFormats.FileDrop, false);
            if (obj == null) return;
            var path = ((string[])obj)[0];
            rightView.LocalPath = path;
            leftView.Picbox_Reset();
        };
        // 右ビューホイール
        rightView.MouseWheel += (s, e) =>
        {
            leftView.Picbox_MouseWheel(s, e);
        };
    }
}

ファイル名:MyPicbox.cs

using System.Diagnostics;
using System.Drawing.Drawing2D;
public class MyPicbox : UserControl
{
    Bitmap? _bitmap = null;

    public Bitmap? Bitmap
    {
        get
        {
            return _bitmap;
        }
        set
        {
            _bitmap = value;
            MyPicbox_Resize(null, new EventArgs());
        }
    }

    Graphics? _graphics = null;
    Matrix? _matrix = null;

    string _localPath = "";
    public string LocalPath
    {
        get
        {
            return _localPath;
        }
        set
        {
            _localPath = value;

            loadImage(_localPath);
        }
    }
    PictureBox _picbox = new()
    {
        Dock = DockStyle.Fill,
    };
    public MyPicbox()
    {
        Controls.Add(_picbox);
        Load += MyPicbox_Load;
        Resize += MyPicbox_Resize;
        _picbox.MouseWheel += Picbox_MouseWheel;
        _picbox.MouseDown += Picbox_MouseDown;
    }
    async void loadImage(string LocalPath)
    {
        if (!File.Exists(LocalPath)) return;
        _picbox.Image?.Dispose();
        using var fs = new FileStream(LocalPath, FileMode.Open, FileAccess.Read);
        _bitmap?.Dispose();
        _bitmap = await Task.Run(()=>(Bitmap)Bitmap.FromStream(fs));

        MyPicbox_Resize(null, new EventArgs());
    }
    void MyPicbox_Load(Object? s, EventArgs e)
    {
        var bmp = new Bitmap(this.Width, this.Height);
        using var g = Graphics.FromImage(bmp);
        g.Clear(Color.Gray);
        _picbox.Image?.Dispose();
        _picbox.Image = bmp;
    }
    void MyPicbox_Resize(Object? s, EventArgs e)
    {
        if (_graphics != null)
        {
            _matrix = _graphics.Transform;
            _graphics.Dispose();
            _graphics = null;
        }
        else
        {
            _matrix = new Matrix();
        }
        _picbox.Image?.Dispose();
        _picbox.Image = new Bitmap(_picbox.Width, _picbox.Height);
        _graphics = Graphics.FromImage(_picbox.Image);
        _graphics.InterpolationMode = InterpolationMode.NearestNeighbor;
        DrawImage();
    }
    void DrawImage()
    {
        if (_bitmap == null || _graphics == null) return;
        if (_matrix != null) _graphics.Transform = _matrix;
        _graphics.Clear(_picbox.BackColor);
        _graphics.DrawImage(_bitmap, 0, 0);
        _picbox.Refresh();
    }
    public void Picbox_MouseWheel(Object? s, MouseEventArgs e)
    {
        if (_bitmap == null || _matrix == null) return;
        _matrix.Translate(-e.X, -e.Y, MatrixOrder.Append);

        if (e.Delta > 0)
        {
            if (_matrix.Elements[0] < 100)
            {
                _matrix.Scale(1.5f, 1.5f, MatrixOrder.Append);
            }
        }
        else
        {
            if (_matrix.Elements[0] > 0.05)
            {
                _matrix.Scale(1.0f / 1.5f, 1.0f / 1.5f, MatrixOrder.Append);
            }
        }
        _matrix.Translate(e.X, e.Y, MatrixOrder.Append);

        DrawImage();
    }
    public void Picbox_Reset()
    {
        if (_bitmap == null || _matrix == null) return;  
        // アフィン変換行列をリセット 
        _matrix.Reset();        
        // 画像の再描画
        DrawImage();
    }
    void Picbox_MouseDown(Object? s, MouseEventArgs e)
    {  
        // 右ボタンがクリックされたとき元に戻す 
        if (e.Button == MouseButtons.Right)
        {
            Picbox_Reset();
            return;
        }
    }
}

画像ファイルをドラッグアンドドロップすると画像が表示されます。

マウスをホイールすることで拡大縮小することが出来ます。


画像の移動機能は作成していませんが、ホイールで縮小し移動したい方向にマウスカーソルを移動、その後ホイールで拡大すると移動します。

マウスホイールに連動し左右二つの画像が拡大することで、2つの画像の細部を目視で比較することを目的として試作してみました。汎用的なソフトとしては色々と修正を必要な部分が目立ちますが、修正が難しそうなので、もう少しプログラミングスキルが向上したら再度チャレンジしたいと思います。

コメント