C#2つの画像の違いを表示する。

C# コンピュータ
C#

単純に左右の画像をピクセル単位で比較しています。

同一フォーマットかつ縦横のピクセル数が同じ画像のみ対応します。

使い方
左右の枠に画像をドラックアンドドロップし「差分」ボタンを押します。

異なる部分はそのまま、同じ部分が赤くなります。

再度「オリジナル」ボタンを押すと元の画像に戻ります。

 

using System;
using System.Windows.Forms;
using System.Drawing;
using System.Text.RegularExpressions;
using System.IO;
using System.Drawing.Imaging;

// 
// 画像の差分を表示
// 

// コンパイル
// csc /t:winexe PictureDiff.cs

class Form1 : Form
{

    Bitmap lBmp = null;
    Bitmap rBmp = null;

    PictureBox picbox1 = new PictureBox
    {
        Size = new Size(380,500),
        Location = new Point(10,10),
        SizeMode = PictureBoxSizeMode.Zoom,
        AllowDrop = true,
        BorderStyle = BorderStyle.FixedSingle,
    };

    PictureBox picbox2 = new PictureBox
    {
        Size = new Size(380,500),
        Location = new Point(390,10),
        SizeMode = PictureBoxSizeMode.Zoom,
        AllowDrop = true,
        BorderStyle = BorderStyle.FixedSingle,
    };

    Button diffButton = new Button
    {
        Size = new Size(100,30),
        Location = new Point(350,520),
        Enabled = false,
        Text = "差分",
    };

    void DiffButton_Click(Object sender, EventArgs e)
    {
        if (diffButton.Text == "オリジナル")
        {
            if (picbox1.Image != null)
            {
                picbox1.Image.Dispose();
                picbox1.Image = null;
            }
            picbox1.Image = new Bitmap(lBmp);
            if (picbox2.Image != null)
            {
                picbox2.Image.Dispose();
                picbox2.Image = null;
            }
            picbox2.Image = new Bitmap(rBmp);
            
            diffButton.Text = "差分";
            return;
        }


        var l = (Bitmap)picbox1.Image;
        var r = (Bitmap)picbox2.Image;

        var ld = l.LockBits(
            new Rectangle(0, 0, l.Width, l.Height),
            ImageLockMode.ReadWrite,
            l.PixelFormat
        );

        var rd = r.LockBits(
            new Rectangle(0, 0, r.Width, r.Height),
            ImageLockMode.ReadWrite,
            r.PixelFormat
        );

        int byteWidth = (int)(ld.Stride / l.Width);

        if (byteWidth < 3) return;

        byte[] lPixels = new byte[ld.Stride * l.Height];
        byte[] rPixels = new byte[rd.Stride * r.Height];

        System.Runtime.InteropServices.Marshal.Copy(ld.Scan0, lPixels, 0, lPixels.Length);
        System.Runtime.InteropServices.Marshal.Copy(rd.Scan0, rPixels, 0, rPixels.Length);

        // 先頭からループ
        for (int y = 0; y < l.Height; y++)
        {
            for (int x = 0; x < ld.Width; x++)
            {
                int pos = y * ld.Stride + x * byteWidth;
                

                if (lPixels[pos+0] == rPixels[pos+0] && 
                    lPixels[pos+1] == rPixels[pos+1] &&
                    lPixels[pos+2] == rPixels[pos+2])
                {
                    var bb = (lPixels[pos+0] / 2);
                    var gg = (lPixels[pos+0] / 2);
                    var rr = (lPixels[pos+0] * 2);
                    if (bb < 0) bb = 0;
                    if (gg < 0) gg = 0;
                    if (rr < 0) rr = 0;
                    if (bb > 255) bb = 255;
                    if (gg > 255) gg = 255;
                    if (rr > 255) rr = 255;

                    lPixels[pos+0] = rPixels[pos+0] = (byte)bb;
                    lPixels[pos+1] = rPixels[pos+1] = (byte)gg;
                    lPixels[pos+2] = rPixels[pos+2] = (byte)rr;
                }
            }
        }                     

        System.Runtime.InteropServices.Marshal.Copy(lPixels,0,ld.Scan0,lPixels.Length);
        System.Runtime.InteropServices.Marshal.Copy(rPixels,0,rd.Scan0,rPixels.Length);

        l.UnlockBits(ld);
        r.UnlockBits(rd);

        picbox1.Refresh();
        picbox2.Refresh();

        diffButton.Text = "オリジナル";
    }

    void checkDiffEnabled()
    {

        if (lBmp != null && rBmp != null)
        {
            if (lBmp.Width == rBmp.Width && 
                lBmp.Height == rBmp.Height &&
                lBmp.PixelFormat == rBmp.PixelFormat)
            {
                diffButton.Enabled = true;
                return;
            }
        }
        diffButton.Enabled = false;
    }

    void Picbox1_DragDrop(object sender, DragEventArgs e)
    {
        string[] files = e.Data.GetData(DataFormats.FileDrop, false) as string[];

        string file = files[0];
        
        // 対応以外排除
        if (!File.Exists(file) || Regex.IsMatch(file,@".\[png|jp(e)?g|gif|bmp]$", RegexOptions.IgnoreCase)) return;

        if (lBmp != null)
        {
            lBmp.Dispose();
            lBmp = null;
        }
        using(var fs = new FileStream(file, FileMode.Open, FileAccess.Read))
        {
            lBmp = new Bitmap(fs);
        }

        if (picbox1.Image != null)
        {
            picbox1.Image.Dispose();
            picbox1.Image = null;
        }
        picbox1.Image = new Bitmap(lBmp);

        checkDiffEnabled();
    }

    void Picbox2_DragDrop(object sender, DragEventArgs e)
    {
        string[] files = e.Data.GetData(DataFormats.FileDrop, false) as string[];

        string file = files[0];
        
        // 対応以外排除
        if (!File.Exists(file) || Regex.IsMatch(file,@".\[png|jp(e)?g|gif|bmp]$", RegexOptions.IgnoreCase)) return;

        if (rBmp != null)
        {
            rBmp.Dispose();
            rBmp = null;
        }
        using(var fs = new FileStream(file, FileMode.Open, FileAccess.Read))
        {
            rBmp = new Bitmap(fs);
        }

        if (picbox2.Image != null)
        {
            picbox2.Image.Dispose();
            picbox2.Image = null;
        }
        picbox2.Image = new Bitmap(rBmp);

        checkDiffEnabled();
    }

    void Form1_Load(Object sender, EventArgs e)
    {
        Size = new Size(800,600);
    }

    Form1()
    {
        Controls.Add(picbox1);
        Controls.Add(picbox2);
        Controls.Add(diffButton);

        Load += Form1_Load;
        picbox1.DragEnter += (sender, e) =>
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                e.Effect = DragDropEffects.Copy;
            }
            else
            {
                e.Effect = DragDropEffects.None;
            }

        };
        picbox2.DragEnter += (sender, e) =>
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                e.Effect = DragDropEffects.Copy;
            }
            else
            {
                e.Effect = DragDropEffects.None;
            }

        };
        picbox1.DragDrop += Picbox1_DragDrop;
        picbox2.DragDrop += Picbox2_DragDrop;

        diffButton.Click += DiffButton_Click;
    }

    [STAThread]
    static void Main()
    {
        Application.Run(new Form1());
    }
}

コメント