HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpModerate

Determining if 2 images are the same

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
samedeterminingtheareimages

Problem

This is my program code for comparing if 2 images are the same. It basically uses the open dialog and opens 1 image at a time and puts it in 1 picture box.

I heard that GetPixel() method may be slow. Is there a more efficient and faster way to compare 2 if 2 images are the same?

Bitmap image1 = null;
Bitmap image2 = null;

public Form1()
{
    InitializeComponent();
}

private void button1_Click(object sender, EventArgs e) //first image open
{
    OpenFileDialog openDialog = new OpenFileDialog();
    if (openDialog.ShowDialog() == DialogResult.OK)
    {
        image1 = new Bitmap(openDialog.FileName);
        pictureBox1.Image = image1;
    }   
}

private void button2_Click(object sender, EventArgs e) //second image open
{

    OpenFileDialog openDialog = new OpenFileDialog();
    if (openDialog.ShowDialog() == DialogResult.OK)
    {
        image2 = new Bitmap(openDialog.FileName);
        pictureBox2.Image = image2;
    }  
}

private void button3_Click(object sender, EventArgs e) //compare button
{
    if (compare(image1, image2))
    {
        MessageBox.Show("Same Image.");
    }

    else
    {
        MessageBox.Show("Different Image.");
    }
}

private bool compare(Bitmap bmp1, Bitmap bmp2) 
{
    bool equals = true;
    bool flag = true;  //Inner loop isn't broken

    //Test to see if we have the same size of image
    if (bmp1.Size == bmp2.Size)
    {
        for (int x = 0; x < bmp1.Width; ++x)
        {
            for (int y = 0; y < bmp1.Height; ++y)
            {
                if (bmp1.GetPixel(x, y) != bmp2.GetPixel(x, y))
                {
                    equals = false;
                    flag = false;
                    break;
                }
            }
            if (!flag)
            {
                break;
            }
        }
    }
    else
    {
        equals = false;
    }
    return equals;
}

Solution

You can use the LockBits method and pointers to access the image data directly.

Example for 24 bpp images:

bool equals = true;
Rectangle rect = new Rectangle(0, 0, bmp1.Width, bmp1.Height);
BitmapData bmpData1 = bmp1.LockBits(rect, ImageLockMode.ReadOnly, bmp1.PixelFormat);
BitmapData bmpData2 = bmp2.LockBits(rect, ImageLockMode.ReadOnly, bmp2.PixelFormat);
unsafe {
  byte* ptr1 = (byte*)bmpData1.Scan0.ToPointer();
  byte* ptr2 = (byte*)bmpData2.Scan0.ToPointer();
  int width = rect.Width * 3; // for 24bpp pixel data
  for (int y = 0; equals && y < rect.Height; y++) {
    for (int x = 0; x < width; x++) {
      if (*ptr1 != *ptr2) {
        equals = false;
        break;
      }
      ptr1++;
      ptr2++;
    }
    ptr1 += bmpData1.Stride - width;
    ptr2 += bmpData2.Stride - width;
  }
}
bmp1.UnlockBits(bmpData1);
bmp2.UnlockBits(bmpData2);

Code Snippets

bool equals = true;
Rectangle rect = new Rectangle(0, 0, bmp1.Width, bmp1.Height);
BitmapData bmpData1 = bmp1.LockBits(rect, ImageLockMode.ReadOnly, bmp1.PixelFormat);
BitmapData bmpData2 = bmp2.LockBits(rect, ImageLockMode.ReadOnly, bmp2.PixelFormat);
unsafe {
  byte* ptr1 = (byte*)bmpData1.Scan0.ToPointer();
  byte* ptr2 = (byte*)bmpData2.Scan0.ToPointer();
  int width = rect.Width * 3; // for 24bpp pixel data
  for (int y = 0; equals && y < rect.Height; y++) {
    for (int x = 0; x < width; x++) {
      if (*ptr1 != *ptr2) {
        equals = false;
        break;
      }
      ptr1++;
      ptr2++;
    }
    ptr1 += bmpData1.Stride - width;
    ptr2 += bmpData2.Stride - width;
  }
}
bmp1.UnlockBits(bmpData1);
bmp2.UnlockBits(bmpData2);

Context

StackExchange Code Review Q#39980, answer score: 14

Revisions (0)

No revisions yet.