単純に左右の画像をピクセル単位で比較しています。
同一フォーマットかつ縦横のピクセル数が同じ画像のみ対応します。
使い方
左右の枠に画像をドラックアンドドロップし「差分」ボタンを押します。
異なる部分はそのまま、同じ部分が赤くなります。
再度「オリジナル」ボタンを押すと元の画像に戻ります。
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());
}
}
コメント