Determining if 2 images are the same











up vote
18
down vote

favorite
6












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;
}









share|improve this question




















  • 1




    Note that Bitmap inherits from Image, which implements IDisposable. This means you very much better call Dispose() on those objects are you are done with them (way many paths here with UI event handlers), or put them into using blocks.
    – Jesse C. Slicer
    Jan 24 '14 at 18:45






  • 1




    Oh, and same goes for OpenFileDialog. I'll probably post an answer to show some of this.
    – Jesse C. Slicer
    Jan 24 '14 at 18:48






  • 1




    See ImageComparer.Compare method. Has overloads to specify tolerance. It is available since VS2102. msdn.microsoft.com/en-us/library/…
    – user3285954
    Jul 2 '15 at 20:06















up vote
18
down vote

favorite
6












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;
}









share|improve this question




















  • 1




    Note that Bitmap inherits from Image, which implements IDisposable. This means you very much better call Dispose() on those objects are you are done with them (way many paths here with UI event handlers), or put them into using blocks.
    – Jesse C. Slicer
    Jan 24 '14 at 18:45






  • 1




    Oh, and same goes for OpenFileDialog. I'll probably post an answer to show some of this.
    – Jesse C. Slicer
    Jan 24 '14 at 18:48






  • 1




    See ImageComparer.Compare method. Has overloads to specify tolerance. It is available since VS2102. msdn.microsoft.com/en-us/library/…
    – user3285954
    Jul 2 '15 at 20:06













up vote
18
down vote

favorite
6









up vote
18
down vote

favorite
6






6





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;
}









share|improve this question















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;
}






c# image






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Feb 22 '15 at 6:27









Jamal

30.2k11115226




30.2k11115226










asked Jan 24 '14 at 18:22









puretppc

2431212




2431212








  • 1




    Note that Bitmap inherits from Image, which implements IDisposable. This means you very much better call Dispose() on those objects are you are done with them (way many paths here with UI event handlers), or put them into using blocks.
    – Jesse C. Slicer
    Jan 24 '14 at 18:45






  • 1




    Oh, and same goes for OpenFileDialog. I'll probably post an answer to show some of this.
    – Jesse C. Slicer
    Jan 24 '14 at 18:48






  • 1




    See ImageComparer.Compare method. Has overloads to specify tolerance. It is available since VS2102. msdn.microsoft.com/en-us/library/…
    – user3285954
    Jul 2 '15 at 20:06














  • 1




    Note that Bitmap inherits from Image, which implements IDisposable. This means you very much better call Dispose() on those objects are you are done with them (way many paths here with UI event handlers), or put them into using blocks.
    – Jesse C. Slicer
    Jan 24 '14 at 18:45






  • 1




    Oh, and same goes for OpenFileDialog. I'll probably post an answer to show some of this.
    – Jesse C. Slicer
    Jan 24 '14 at 18:48






  • 1




    See ImageComparer.Compare method. Has overloads to specify tolerance. It is available since VS2102. msdn.microsoft.com/en-us/library/…
    – user3285954
    Jul 2 '15 at 20:06








1




1




Note that Bitmap inherits from Image, which implements IDisposable. This means you very much better call Dispose() on those objects are you are done with them (way many paths here with UI event handlers), or put them into using blocks.
– Jesse C. Slicer
Jan 24 '14 at 18:45




Note that Bitmap inherits from Image, which implements IDisposable. This means you very much better call Dispose() on those objects are you are done with them (way many paths here with UI event handlers), or put them into using blocks.
– Jesse C. Slicer
Jan 24 '14 at 18:45




1




1




Oh, and same goes for OpenFileDialog. I'll probably post an answer to show some of this.
– Jesse C. Slicer
Jan 24 '14 at 18:48




Oh, and same goes for OpenFileDialog. I'll probably post an answer to show some of this.
– Jesse C. Slicer
Jan 24 '14 at 18:48




1




1




See ImageComparer.Compare method. Has overloads to specify tolerance. It is available since VS2102. msdn.microsoft.com/en-us/library/…
– user3285954
Jul 2 '15 at 20:06




See ImageComparer.Compare method. Has overloads to specify tolerance. It is available since VS2102. msdn.microsoft.com/en-us/library/…
– user3285954
Jul 2 '15 at 20:06










6 Answers
6






active

oldest

votes

















up vote
13
down vote



accepted










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);





share|improve this answer























  • I assume I drag this in my compare() method?
    – puretppc
    Jan 24 '14 at 18:57










  • @puretppc: Yes, that is correct. After checking that the images have the same size and the correct pixel format.
    – Guffa
    Jan 24 '14 at 19:13










  • BitmapData doesn't exist for me. Also Unsafe code may only appear if compiling with /unsafe.
    – puretppc
    Jan 24 '14 at 19:16










  • @puretppc: Add using System.Drawing.Imaging; at the top, or use System.Drawing.Imaging.BitmapData. (If you right click on BitmapData both options can be done automatically under Resolve.) To use unsafe code you need to enable it in the project properties.
    – Guffa
    Jan 24 '14 at 19:24










  • Oh ok. But now I'm getting an error saying 'System.Drawing.Imaging.ImageLockMode' does not contain a definition for 'Read' At the very top of the program I put using System.Drawing.Imaging;
    – puretppc
    Jan 24 '14 at 19:31




















up vote
10
down vote













One thing I have done in the past is to convert the images to 64-bit encoded strings and just string compare. It won't be as fast as using pointers, naturally. However, it can be done entirely in managed code, it doesn't require you to know bits per pixel, and it works for the Image base class.



byte image1Bytes;
byte image2Bytes;

using(var mstream = new MemoryStream())
{
image1.Save(mstream, image1.RawFormat);
image1Bytes = mstream.ToArray();
}

using(var mstream = new MemoryStream())
{
image2.Save(mstream, image2.RawFormat);
image2Bytes = mstream.ToArray();
}

var image164 = Convert.ToBase64String(image1Bytes);
var image264 = Convert.ToBase64String(image2Bytes);

return string.Equals(image164, image264);





share|improve this answer























  • Thanks this worked :) So my old code was about comparing BPP (bits per pixel)? I don't really know this since I got this off the another site
    – puretppc
    Jan 24 '14 at 18:58






  • 3




    Note that this will also compare any meta data in the images. If they for example are identical but with different resolution settings, this will return false.
    – Guffa
    Jan 24 '14 at 19:14






  • 4




    What is the purpose of converting to a base64 string? Why not simple compare the elements of both arrays (or streams)?
    – NPSF3000
    May 5 '14 at 8:30


















up vote
9
down vote













I'll focus on problems in compare().



You're using the wrong equality comparison for the bitmap size. You need to compare the contents of the Size objects, not whether they are the same reference.



A variable named flag should be a… red flag! Not only is it vaguely named, its presence suggests that your code is ineffective. Avoid using variables for flow control; find more active ways to get to where you need to go.



In this case, the solution is an early return. As soon as you find a single difference between the two images, you're done! You don't even need the equals variable.



I would also rename compare() for clarity, and make it static because it is a pure function of its two parameters.



private static bool Equals(Bitmap bmp1, Bitmap bmp2) 
{
if (!bmp1.Size.Equals(bmp2.Size))
{
return false;
}
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))
{
return false;
}
}
}
return true;
}





share|improve this answer




























    up vote
    5
    down vote













    Note that Bitmap inherits from Image, which implements IDisposable. This means you very much better call Dispose() on those objects are you are done with them (way many paths here with UI event handlers), or put them into using blocks. Same goes for OpenFileDialog.



    As per my comments, some using usage (and try..finally usage, incorporating Guffa's answer):



    private Bitmap image1;

    private Bitmap image2;

    public Form1()
    {
    this.InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
    using (var openDialog = new OpenFileDialog())
    {
    if (openDialog.ShowDialog() != DialogResult.OK)
    {
    return;
    }

    this.DisposeImage1();
    this.image1 = new Bitmap(openDialog.FileName);
    }

    this.pictureBox1.Image = this.image1;
    }

    private void button2_Click(object sender, EventArgs e)
    {
    using (var openDialog = new OpenFileDialog())
    {
    if (openDialog.ShowDialog() != DialogResult.OK)
    {
    return;
    }

    this.DisposeImage2();
    this.image2 = new Bitmap(openDialog.FileName);
    }

    this.pictureBox2.Image = this.image2;
    }

    private void button3_Click(object sender, EventArgs e)
    {
    MessageBox.Show(Compare(this.image1, this.image2) ? "Same Image." : "Different Image.");
    }

    private void Form1_FormClosed(object sender, FormClosedEventArgs e)
    {
    this.DisposeImage2();
    this.DisposeImage1();
    }

    private static bool Compare(Bitmap bmp1, Bitmap bmp2)
    {
    // Test to see if we have the same size of image
    if (bmp1.Size != bmp2.Size)
    {
    return false;
    }

    var rect = new Rectangle(0, 0, bmp1.Width, bmp1.Height);
    var bmpData1 = bmp1.LockBits(rect, ImageLockMode.ReadOnly, bmp1.PixelFormat);

    try
    {
    var bmpData2 = bmp2.LockBits(rect, ImageLockMode.ReadOnly, bmp1.PixelFormat);

    try
    {
    unsafe
    {
    var ptr1 = (byte*)bmpData1.Scan0.ToPointer();
    var ptr2 = (byte*)bmpData2.Scan0.ToPointer();
    var width = 3 * rect.Width; // for 24bpp pixel data

    for (var y = 0; y < rect.Height; y++)
    {
    for (var x = 0; x < width; x++)
    {
    if (*ptr1 != *ptr2)
    {
    return false;
    }

    ptr1++;
    ptr2++;
    }

    ptr1 += bmpData1.Stride - width;
    ptr2 += bmpData2.Stride - width;
    }
    }
    }
    finally
    {
    bmp2.UnlockBits(bmpData2);
    }
    }
    finally
    {
    bmp1.UnlockBits(bmpData1);
    }

    return true;
    }

    private void DisposeImage1()
    {
    if (this.image1 == null)
    {
    return;
    }

    this.pictureBox1.Image = null;
    this.image1.Dispose();
    this.image1 = null;
    }

    private void DisposeImage2()
    {
    if (this.image2 == null)
    {
    return;
    }

    this.pictureBox2.Image = null;
    this.image2.Dispose();
    this.image2 = null;
    }





    share|improve this answer























    • ImageLockMode doesn't exist? Also, the unsafe I'm getting an error
      – puretppc
      Jan 24 '14 at 19:17






    • 1




      You'll need to check enable unsafe code on the Build page of your project's options. Also, add using System.Drawing.Imaging to your using directives at the top of the file to get access to ImageLockMode.
      – Jesse C. Slicer
      Jan 24 '14 at 20:53










    • in "var bmpData2 = bmp2.LockBits(rect, ImageLockMode.ReadOnly, bmp1.PixelFormat)" last parameter bmp1.PixelFormat or bmp2.PixelFormat?
      – Sajitha Rathnayake
      Aug 15 '14 at 5:26










    • I got error "Bitmap region is already locked." in code "var bmpData2 = bmp2.LockBits(rect, ImageLockMode.ReadOnly, bmp1.PixelFormat)"
      – Sajitha Rathnayake
      Aug 15 '14 at 5:30




















    up vote
    0
    down vote













    Why convert in base64 or compare every pixel if there's hash comparison?
    Do something like this:



    byte fileData = File.ReadAllBytes(filePath);
    byte hash = MD5.Create().ComputeHash(fileData);


    And simply compare the hashes.



    You'll need MD5CryptoServiceProvider for that.






    share|improve this answer








    New contributor




    F.H. is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.

























      up vote
      -1
      down vote













      Have a look at this SO question.



      https://stackoverflow.com/q/35151067/4062881



      It decreases the size of image, turns it B&W, and then uses GetPixel() to generate hash.



      It is much faster, efficient, and works! It is able to find equal images with:




      • different file formats (e.g. jpg, png, bmp)

      • rotation (90, 180, 270) - by changing the iteration order of i and j

      • different dimensions (same aspect is required)

      • different compression (tolerance is required in case of quality loss like jpeg artifacts) - you can accept a 99% equality to be the same image and 50% to be a different one.


      Cheers..!! ;)






      share|improve this answer




















        protected by Jamal 5 hours ago



        Thank you for your interest in this question.
        Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).



        Would you like to answer one of these unanswered questions instead?














        6 Answers
        6






        active

        oldest

        votes








        6 Answers
        6






        active

        oldest

        votes









        active

        oldest

        votes






        active

        oldest

        votes








        up vote
        13
        down vote



        accepted










        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);





        share|improve this answer























        • I assume I drag this in my compare() method?
          – puretppc
          Jan 24 '14 at 18:57










        • @puretppc: Yes, that is correct. After checking that the images have the same size and the correct pixel format.
          – Guffa
          Jan 24 '14 at 19:13










        • BitmapData doesn't exist for me. Also Unsafe code may only appear if compiling with /unsafe.
          – puretppc
          Jan 24 '14 at 19:16










        • @puretppc: Add using System.Drawing.Imaging; at the top, or use System.Drawing.Imaging.BitmapData. (If you right click on BitmapData both options can be done automatically under Resolve.) To use unsafe code you need to enable it in the project properties.
          – Guffa
          Jan 24 '14 at 19:24










        • Oh ok. But now I'm getting an error saying 'System.Drawing.Imaging.ImageLockMode' does not contain a definition for 'Read' At the very top of the program I put using System.Drawing.Imaging;
          – puretppc
          Jan 24 '14 at 19:31

















        up vote
        13
        down vote



        accepted










        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);





        share|improve this answer























        • I assume I drag this in my compare() method?
          – puretppc
          Jan 24 '14 at 18:57










        • @puretppc: Yes, that is correct. After checking that the images have the same size and the correct pixel format.
          – Guffa
          Jan 24 '14 at 19:13










        • BitmapData doesn't exist for me. Also Unsafe code may only appear if compiling with /unsafe.
          – puretppc
          Jan 24 '14 at 19:16










        • @puretppc: Add using System.Drawing.Imaging; at the top, or use System.Drawing.Imaging.BitmapData. (If you right click on BitmapData both options can be done automatically under Resolve.) To use unsafe code you need to enable it in the project properties.
          – Guffa
          Jan 24 '14 at 19:24










        • Oh ok. But now I'm getting an error saying 'System.Drawing.Imaging.ImageLockMode' does not contain a definition for 'Read' At the very top of the program I put using System.Drawing.Imaging;
          – puretppc
          Jan 24 '14 at 19:31















        up vote
        13
        down vote



        accepted







        up vote
        13
        down vote



        accepted






        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);





        share|improve this answer














        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);






        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Jan 24 '14 at 20:14

























        answered Jan 24 '14 at 18:38









        Guffa

        6,6621226




        6,6621226












        • I assume I drag this in my compare() method?
          – puretppc
          Jan 24 '14 at 18:57










        • @puretppc: Yes, that is correct. After checking that the images have the same size and the correct pixel format.
          – Guffa
          Jan 24 '14 at 19:13










        • BitmapData doesn't exist for me. Also Unsafe code may only appear if compiling with /unsafe.
          – puretppc
          Jan 24 '14 at 19:16










        • @puretppc: Add using System.Drawing.Imaging; at the top, or use System.Drawing.Imaging.BitmapData. (If you right click on BitmapData both options can be done automatically under Resolve.) To use unsafe code you need to enable it in the project properties.
          – Guffa
          Jan 24 '14 at 19:24










        • Oh ok. But now I'm getting an error saying 'System.Drawing.Imaging.ImageLockMode' does not contain a definition for 'Read' At the very top of the program I put using System.Drawing.Imaging;
          – puretppc
          Jan 24 '14 at 19:31




















        • I assume I drag this in my compare() method?
          – puretppc
          Jan 24 '14 at 18:57










        • @puretppc: Yes, that is correct. After checking that the images have the same size and the correct pixel format.
          – Guffa
          Jan 24 '14 at 19:13










        • BitmapData doesn't exist for me. Also Unsafe code may only appear if compiling with /unsafe.
          – puretppc
          Jan 24 '14 at 19:16










        • @puretppc: Add using System.Drawing.Imaging; at the top, or use System.Drawing.Imaging.BitmapData. (If you right click on BitmapData both options can be done automatically under Resolve.) To use unsafe code you need to enable it in the project properties.
          – Guffa
          Jan 24 '14 at 19:24










        • Oh ok. But now I'm getting an error saying 'System.Drawing.Imaging.ImageLockMode' does not contain a definition for 'Read' At the very top of the program I put using System.Drawing.Imaging;
          – puretppc
          Jan 24 '14 at 19:31


















        I assume I drag this in my compare() method?
        – puretppc
        Jan 24 '14 at 18:57




        I assume I drag this in my compare() method?
        – puretppc
        Jan 24 '14 at 18:57












        @puretppc: Yes, that is correct. After checking that the images have the same size and the correct pixel format.
        – Guffa
        Jan 24 '14 at 19:13




        @puretppc: Yes, that is correct. After checking that the images have the same size and the correct pixel format.
        – Guffa
        Jan 24 '14 at 19:13












        BitmapData doesn't exist for me. Also Unsafe code may only appear if compiling with /unsafe.
        – puretppc
        Jan 24 '14 at 19:16




        BitmapData doesn't exist for me. Also Unsafe code may only appear if compiling with /unsafe.
        – puretppc
        Jan 24 '14 at 19:16












        @puretppc: Add using System.Drawing.Imaging; at the top, or use System.Drawing.Imaging.BitmapData. (If you right click on BitmapData both options can be done automatically under Resolve.) To use unsafe code you need to enable it in the project properties.
        – Guffa
        Jan 24 '14 at 19:24




        @puretppc: Add using System.Drawing.Imaging; at the top, or use System.Drawing.Imaging.BitmapData. (If you right click on BitmapData both options can be done automatically under Resolve.) To use unsafe code you need to enable it in the project properties.
        – Guffa
        Jan 24 '14 at 19:24












        Oh ok. But now I'm getting an error saying 'System.Drawing.Imaging.ImageLockMode' does not contain a definition for 'Read' At the very top of the program I put using System.Drawing.Imaging;
        – puretppc
        Jan 24 '14 at 19:31






        Oh ok. But now I'm getting an error saying 'System.Drawing.Imaging.ImageLockMode' does not contain a definition for 'Read' At the very top of the program I put using System.Drawing.Imaging;
        – puretppc
        Jan 24 '14 at 19:31














        up vote
        10
        down vote













        One thing I have done in the past is to convert the images to 64-bit encoded strings and just string compare. It won't be as fast as using pointers, naturally. However, it can be done entirely in managed code, it doesn't require you to know bits per pixel, and it works for the Image base class.



        byte image1Bytes;
        byte image2Bytes;

        using(var mstream = new MemoryStream())
        {
        image1.Save(mstream, image1.RawFormat);
        image1Bytes = mstream.ToArray();
        }

        using(var mstream = new MemoryStream())
        {
        image2.Save(mstream, image2.RawFormat);
        image2Bytes = mstream.ToArray();
        }

        var image164 = Convert.ToBase64String(image1Bytes);
        var image264 = Convert.ToBase64String(image2Bytes);

        return string.Equals(image164, image264);





        share|improve this answer























        • Thanks this worked :) So my old code was about comparing BPP (bits per pixel)? I don't really know this since I got this off the another site
          – puretppc
          Jan 24 '14 at 18:58






        • 3




          Note that this will also compare any meta data in the images. If they for example are identical but with different resolution settings, this will return false.
          – Guffa
          Jan 24 '14 at 19:14






        • 4




          What is the purpose of converting to a base64 string? Why not simple compare the elements of both arrays (or streams)?
          – NPSF3000
          May 5 '14 at 8:30















        up vote
        10
        down vote













        One thing I have done in the past is to convert the images to 64-bit encoded strings and just string compare. It won't be as fast as using pointers, naturally. However, it can be done entirely in managed code, it doesn't require you to know bits per pixel, and it works for the Image base class.



        byte image1Bytes;
        byte image2Bytes;

        using(var mstream = new MemoryStream())
        {
        image1.Save(mstream, image1.RawFormat);
        image1Bytes = mstream.ToArray();
        }

        using(var mstream = new MemoryStream())
        {
        image2.Save(mstream, image2.RawFormat);
        image2Bytes = mstream.ToArray();
        }

        var image164 = Convert.ToBase64String(image1Bytes);
        var image264 = Convert.ToBase64String(image2Bytes);

        return string.Equals(image164, image264);





        share|improve this answer























        • Thanks this worked :) So my old code was about comparing BPP (bits per pixel)? I don't really know this since I got this off the another site
          – puretppc
          Jan 24 '14 at 18:58






        • 3




          Note that this will also compare any meta data in the images. If they for example are identical but with different resolution settings, this will return false.
          – Guffa
          Jan 24 '14 at 19:14






        • 4




          What is the purpose of converting to a base64 string? Why not simple compare the elements of both arrays (or streams)?
          – NPSF3000
          May 5 '14 at 8:30













        up vote
        10
        down vote










        up vote
        10
        down vote









        One thing I have done in the past is to convert the images to 64-bit encoded strings and just string compare. It won't be as fast as using pointers, naturally. However, it can be done entirely in managed code, it doesn't require you to know bits per pixel, and it works for the Image base class.



        byte image1Bytes;
        byte image2Bytes;

        using(var mstream = new MemoryStream())
        {
        image1.Save(mstream, image1.RawFormat);
        image1Bytes = mstream.ToArray();
        }

        using(var mstream = new MemoryStream())
        {
        image2.Save(mstream, image2.RawFormat);
        image2Bytes = mstream.ToArray();
        }

        var image164 = Convert.ToBase64String(image1Bytes);
        var image264 = Convert.ToBase64String(image2Bytes);

        return string.Equals(image164, image264);





        share|improve this answer














        One thing I have done in the past is to convert the images to 64-bit encoded strings and just string compare. It won't be as fast as using pointers, naturally. However, it can be done entirely in managed code, it doesn't require you to know bits per pixel, and it works for the Image base class.



        byte image1Bytes;
        byte image2Bytes;

        using(var mstream = new MemoryStream())
        {
        image1.Save(mstream, image1.RawFormat);
        image1Bytes = mstream.ToArray();
        }

        using(var mstream = new MemoryStream())
        {
        image2.Save(mstream, image2.RawFormat);
        image2Bytes = mstream.ToArray();
        }

        var image164 = Convert.ToBase64String(image1Bytes);
        var image264 = Convert.ToBase64String(image2Bytes);

        return string.Equals(image164, image264);






        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Oct 26 '17 at 15:32









        wonea

        1034




        1034










        answered Jan 24 '14 at 18:47









        Dan Lyons

        3,4881019




        3,4881019












        • Thanks this worked :) So my old code was about comparing BPP (bits per pixel)? I don't really know this since I got this off the another site
          – puretppc
          Jan 24 '14 at 18:58






        • 3




          Note that this will also compare any meta data in the images. If they for example are identical but with different resolution settings, this will return false.
          – Guffa
          Jan 24 '14 at 19:14






        • 4




          What is the purpose of converting to a base64 string? Why not simple compare the elements of both arrays (or streams)?
          – NPSF3000
          May 5 '14 at 8:30


















        • Thanks this worked :) So my old code was about comparing BPP (bits per pixel)? I don't really know this since I got this off the another site
          – puretppc
          Jan 24 '14 at 18:58






        • 3




          Note that this will also compare any meta data in the images. If they for example are identical but with different resolution settings, this will return false.
          – Guffa
          Jan 24 '14 at 19:14






        • 4




          What is the purpose of converting to a base64 string? Why not simple compare the elements of both arrays (or streams)?
          – NPSF3000
          May 5 '14 at 8:30
















        Thanks this worked :) So my old code was about comparing BPP (bits per pixel)? I don't really know this since I got this off the another site
        – puretppc
        Jan 24 '14 at 18:58




        Thanks this worked :) So my old code was about comparing BPP (bits per pixel)? I don't really know this since I got this off the another site
        – puretppc
        Jan 24 '14 at 18:58




        3




        3




        Note that this will also compare any meta data in the images. If they for example are identical but with different resolution settings, this will return false.
        – Guffa
        Jan 24 '14 at 19:14




        Note that this will also compare any meta data in the images. If they for example are identical but with different resolution settings, this will return false.
        – Guffa
        Jan 24 '14 at 19:14




        4




        4




        What is the purpose of converting to a base64 string? Why not simple compare the elements of both arrays (or streams)?
        – NPSF3000
        May 5 '14 at 8:30




        What is the purpose of converting to a base64 string? Why not simple compare the elements of both arrays (or streams)?
        – NPSF3000
        May 5 '14 at 8:30










        up vote
        9
        down vote













        I'll focus on problems in compare().



        You're using the wrong equality comparison for the bitmap size. You need to compare the contents of the Size objects, not whether they are the same reference.



        A variable named flag should be a… red flag! Not only is it vaguely named, its presence suggests that your code is ineffective. Avoid using variables for flow control; find more active ways to get to where you need to go.



        In this case, the solution is an early return. As soon as you find a single difference between the two images, you're done! You don't even need the equals variable.



        I would also rename compare() for clarity, and make it static because it is a pure function of its two parameters.



        private static bool Equals(Bitmap bmp1, Bitmap bmp2) 
        {
        if (!bmp1.Size.Equals(bmp2.Size))
        {
        return false;
        }
        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))
        {
        return false;
        }
        }
        }
        return true;
        }





        share|improve this answer

























          up vote
          9
          down vote













          I'll focus on problems in compare().



          You're using the wrong equality comparison for the bitmap size. You need to compare the contents of the Size objects, not whether they are the same reference.



          A variable named flag should be a… red flag! Not only is it vaguely named, its presence suggests that your code is ineffective. Avoid using variables for flow control; find more active ways to get to where you need to go.



          In this case, the solution is an early return. As soon as you find a single difference between the two images, you're done! You don't even need the equals variable.



          I would also rename compare() for clarity, and make it static because it is a pure function of its two parameters.



          private static bool Equals(Bitmap bmp1, Bitmap bmp2) 
          {
          if (!bmp1.Size.Equals(bmp2.Size))
          {
          return false;
          }
          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))
          {
          return false;
          }
          }
          }
          return true;
          }





          share|improve this answer























            up vote
            9
            down vote










            up vote
            9
            down vote









            I'll focus on problems in compare().



            You're using the wrong equality comparison for the bitmap size. You need to compare the contents of the Size objects, not whether they are the same reference.



            A variable named flag should be a… red flag! Not only is it vaguely named, its presence suggests that your code is ineffective. Avoid using variables for flow control; find more active ways to get to where you need to go.



            In this case, the solution is an early return. As soon as you find a single difference between the two images, you're done! You don't even need the equals variable.



            I would also rename compare() for clarity, and make it static because it is a pure function of its two parameters.



            private static bool Equals(Bitmap bmp1, Bitmap bmp2) 
            {
            if (!bmp1.Size.Equals(bmp2.Size))
            {
            return false;
            }
            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))
            {
            return false;
            }
            }
            }
            return true;
            }





            share|improve this answer












            I'll focus on problems in compare().



            You're using the wrong equality comparison for the bitmap size. You need to compare the contents of the Size objects, not whether they are the same reference.



            A variable named flag should be a… red flag! Not only is it vaguely named, its presence suggests that your code is ineffective. Avoid using variables for flow control; find more active ways to get to where you need to go.



            In this case, the solution is an early return. As soon as you find a single difference between the two images, you're done! You don't even need the equals variable.



            I would also rename compare() for clarity, and make it static because it is a pure function of its two parameters.



            private static bool Equals(Bitmap bmp1, Bitmap bmp2) 
            {
            if (!bmp1.Size.Equals(bmp2.Size))
            {
            return false;
            }
            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))
            {
            return false;
            }
            }
            }
            return true;
            }






            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Jan 25 '14 at 17:04









            200_success

            127k15148410




            127k15148410






















                up vote
                5
                down vote













                Note that Bitmap inherits from Image, which implements IDisposable. This means you very much better call Dispose() on those objects are you are done with them (way many paths here with UI event handlers), or put them into using blocks. Same goes for OpenFileDialog.



                As per my comments, some using usage (and try..finally usage, incorporating Guffa's answer):



                private Bitmap image1;

                private Bitmap image2;

                public Form1()
                {
                this.InitializeComponent();
                }

                private void button1_Click(object sender, EventArgs e)
                {
                using (var openDialog = new OpenFileDialog())
                {
                if (openDialog.ShowDialog() != DialogResult.OK)
                {
                return;
                }

                this.DisposeImage1();
                this.image1 = new Bitmap(openDialog.FileName);
                }

                this.pictureBox1.Image = this.image1;
                }

                private void button2_Click(object sender, EventArgs e)
                {
                using (var openDialog = new OpenFileDialog())
                {
                if (openDialog.ShowDialog() != DialogResult.OK)
                {
                return;
                }

                this.DisposeImage2();
                this.image2 = new Bitmap(openDialog.FileName);
                }

                this.pictureBox2.Image = this.image2;
                }

                private void button3_Click(object sender, EventArgs e)
                {
                MessageBox.Show(Compare(this.image1, this.image2) ? "Same Image." : "Different Image.");
                }

                private void Form1_FormClosed(object sender, FormClosedEventArgs e)
                {
                this.DisposeImage2();
                this.DisposeImage1();
                }

                private static bool Compare(Bitmap bmp1, Bitmap bmp2)
                {
                // Test to see if we have the same size of image
                if (bmp1.Size != bmp2.Size)
                {
                return false;
                }

                var rect = new Rectangle(0, 0, bmp1.Width, bmp1.Height);
                var bmpData1 = bmp1.LockBits(rect, ImageLockMode.ReadOnly, bmp1.PixelFormat);

                try
                {
                var bmpData2 = bmp2.LockBits(rect, ImageLockMode.ReadOnly, bmp1.PixelFormat);

                try
                {
                unsafe
                {
                var ptr1 = (byte*)bmpData1.Scan0.ToPointer();
                var ptr2 = (byte*)bmpData2.Scan0.ToPointer();
                var width = 3 * rect.Width; // for 24bpp pixel data

                for (var y = 0; y < rect.Height; y++)
                {
                for (var x = 0; x < width; x++)
                {
                if (*ptr1 != *ptr2)
                {
                return false;
                }

                ptr1++;
                ptr2++;
                }

                ptr1 += bmpData1.Stride - width;
                ptr2 += bmpData2.Stride - width;
                }
                }
                }
                finally
                {
                bmp2.UnlockBits(bmpData2);
                }
                }
                finally
                {
                bmp1.UnlockBits(bmpData1);
                }

                return true;
                }

                private void DisposeImage1()
                {
                if (this.image1 == null)
                {
                return;
                }

                this.pictureBox1.Image = null;
                this.image1.Dispose();
                this.image1 = null;
                }

                private void DisposeImage2()
                {
                if (this.image2 == null)
                {
                return;
                }

                this.pictureBox2.Image = null;
                this.image2.Dispose();
                this.image2 = null;
                }





                share|improve this answer























                • ImageLockMode doesn't exist? Also, the unsafe I'm getting an error
                  – puretppc
                  Jan 24 '14 at 19:17






                • 1




                  You'll need to check enable unsafe code on the Build page of your project's options. Also, add using System.Drawing.Imaging to your using directives at the top of the file to get access to ImageLockMode.
                  – Jesse C. Slicer
                  Jan 24 '14 at 20:53










                • in "var bmpData2 = bmp2.LockBits(rect, ImageLockMode.ReadOnly, bmp1.PixelFormat)" last parameter bmp1.PixelFormat or bmp2.PixelFormat?
                  – Sajitha Rathnayake
                  Aug 15 '14 at 5:26










                • I got error "Bitmap region is already locked." in code "var bmpData2 = bmp2.LockBits(rect, ImageLockMode.ReadOnly, bmp1.PixelFormat)"
                  – Sajitha Rathnayake
                  Aug 15 '14 at 5:30

















                up vote
                5
                down vote













                Note that Bitmap inherits from Image, which implements IDisposable. This means you very much better call Dispose() on those objects are you are done with them (way many paths here with UI event handlers), or put them into using blocks. Same goes for OpenFileDialog.



                As per my comments, some using usage (and try..finally usage, incorporating Guffa's answer):



                private Bitmap image1;

                private Bitmap image2;

                public Form1()
                {
                this.InitializeComponent();
                }

                private void button1_Click(object sender, EventArgs e)
                {
                using (var openDialog = new OpenFileDialog())
                {
                if (openDialog.ShowDialog() != DialogResult.OK)
                {
                return;
                }

                this.DisposeImage1();
                this.image1 = new Bitmap(openDialog.FileName);
                }

                this.pictureBox1.Image = this.image1;
                }

                private void button2_Click(object sender, EventArgs e)
                {
                using (var openDialog = new OpenFileDialog())
                {
                if (openDialog.ShowDialog() != DialogResult.OK)
                {
                return;
                }

                this.DisposeImage2();
                this.image2 = new Bitmap(openDialog.FileName);
                }

                this.pictureBox2.Image = this.image2;
                }

                private void button3_Click(object sender, EventArgs e)
                {
                MessageBox.Show(Compare(this.image1, this.image2) ? "Same Image." : "Different Image.");
                }

                private void Form1_FormClosed(object sender, FormClosedEventArgs e)
                {
                this.DisposeImage2();
                this.DisposeImage1();
                }

                private static bool Compare(Bitmap bmp1, Bitmap bmp2)
                {
                // Test to see if we have the same size of image
                if (bmp1.Size != bmp2.Size)
                {
                return false;
                }

                var rect = new Rectangle(0, 0, bmp1.Width, bmp1.Height);
                var bmpData1 = bmp1.LockBits(rect, ImageLockMode.ReadOnly, bmp1.PixelFormat);

                try
                {
                var bmpData2 = bmp2.LockBits(rect, ImageLockMode.ReadOnly, bmp1.PixelFormat);

                try
                {
                unsafe
                {
                var ptr1 = (byte*)bmpData1.Scan0.ToPointer();
                var ptr2 = (byte*)bmpData2.Scan0.ToPointer();
                var width = 3 * rect.Width; // for 24bpp pixel data

                for (var y = 0; y < rect.Height; y++)
                {
                for (var x = 0; x < width; x++)
                {
                if (*ptr1 != *ptr2)
                {
                return false;
                }

                ptr1++;
                ptr2++;
                }

                ptr1 += bmpData1.Stride - width;
                ptr2 += bmpData2.Stride - width;
                }
                }
                }
                finally
                {
                bmp2.UnlockBits(bmpData2);
                }
                }
                finally
                {
                bmp1.UnlockBits(bmpData1);
                }

                return true;
                }

                private void DisposeImage1()
                {
                if (this.image1 == null)
                {
                return;
                }

                this.pictureBox1.Image = null;
                this.image1.Dispose();
                this.image1 = null;
                }

                private void DisposeImage2()
                {
                if (this.image2 == null)
                {
                return;
                }

                this.pictureBox2.Image = null;
                this.image2.Dispose();
                this.image2 = null;
                }





                share|improve this answer























                • ImageLockMode doesn't exist? Also, the unsafe I'm getting an error
                  – puretppc
                  Jan 24 '14 at 19:17






                • 1




                  You'll need to check enable unsafe code on the Build page of your project's options. Also, add using System.Drawing.Imaging to your using directives at the top of the file to get access to ImageLockMode.
                  – Jesse C. Slicer
                  Jan 24 '14 at 20:53










                • in "var bmpData2 = bmp2.LockBits(rect, ImageLockMode.ReadOnly, bmp1.PixelFormat)" last parameter bmp1.PixelFormat or bmp2.PixelFormat?
                  – Sajitha Rathnayake
                  Aug 15 '14 at 5:26










                • I got error "Bitmap region is already locked." in code "var bmpData2 = bmp2.LockBits(rect, ImageLockMode.ReadOnly, bmp1.PixelFormat)"
                  – Sajitha Rathnayake
                  Aug 15 '14 at 5:30















                up vote
                5
                down vote










                up vote
                5
                down vote









                Note that Bitmap inherits from Image, which implements IDisposable. This means you very much better call Dispose() on those objects are you are done with them (way many paths here with UI event handlers), or put them into using blocks. Same goes for OpenFileDialog.



                As per my comments, some using usage (and try..finally usage, incorporating Guffa's answer):



                private Bitmap image1;

                private Bitmap image2;

                public Form1()
                {
                this.InitializeComponent();
                }

                private void button1_Click(object sender, EventArgs e)
                {
                using (var openDialog = new OpenFileDialog())
                {
                if (openDialog.ShowDialog() != DialogResult.OK)
                {
                return;
                }

                this.DisposeImage1();
                this.image1 = new Bitmap(openDialog.FileName);
                }

                this.pictureBox1.Image = this.image1;
                }

                private void button2_Click(object sender, EventArgs e)
                {
                using (var openDialog = new OpenFileDialog())
                {
                if (openDialog.ShowDialog() != DialogResult.OK)
                {
                return;
                }

                this.DisposeImage2();
                this.image2 = new Bitmap(openDialog.FileName);
                }

                this.pictureBox2.Image = this.image2;
                }

                private void button3_Click(object sender, EventArgs e)
                {
                MessageBox.Show(Compare(this.image1, this.image2) ? "Same Image." : "Different Image.");
                }

                private void Form1_FormClosed(object sender, FormClosedEventArgs e)
                {
                this.DisposeImage2();
                this.DisposeImage1();
                }

                private static bool Compare(Bitmap bmp1, Bitmap bmp2)
                {
                // Test to see if we have the same size of image
                if (bmp1.Size != bmp2.Size)
                {
                return false;
                }

                var rect = new Rectangle(0, 0, bmp1.Width, bmp1.Height);
                var bmpData1 = bmp1.LockBits(rect, ImageLockMode.ReadOnly, bmp1.PixelFormat);

                try
                {
                var bmpData2 = bmp2.LockBits(rect, ImageLockMode.ReadOnly, bmp1.PixelFormat);

                try
                {
                unsafe
                {
                var ptr1 = (byte*)bmpData1.Scan0.ToPointer();
                var ptr2 = (byte*)bmpData2.Scan0.ToPointer();
                var width = 3 * rect.Width; // for 24bpp pixel data

                for (var y = 0; y < rect.Height; y++)
                {
                for (var x = 0; x < width; x++)
                {
                if (*ptr1 != *ptr2)
                {
                return false;
                }

                ptr1++;
                ptr2++;
                }

                ptr1 += bmpData1.Stride - width;
                ptr2 += bmpData2.Stride - width;
                }
                }
                }
                finally
                {
                bmp2.UnlockBits(bmpData2);
                }
                }
                finally
                {
                bmp1.UnlockBits(bmpData1);
                }

                return true;
                }

                private void DisposeImage1()
                {
                if (this.image1 == null)
                {
                return;
                }

                this.pictureBox1.Image = null;
                this.image1.Dispose();
                this.image1 = null;
                }

                private void DisposeImage2()
                {
                if (this.image2 == null)
                {
                return;
                }

                this.pictureBox2.Image = null;
                this.image2.Dispose();
                this.image2 = null;
                }





                share|improve this answer














                Note that Bitmap inherits from Image, which implements IDisposable. This means you very much better call Dispose() on those objects are you are done with them (way many paths here with UI event handlers), or put them into using blocks. Same goes for OpenFileDialog.



                As per my comments, some using usage (and try..finally usage, incorporating Guffa's answer):



                private Bitmap image1;

                private Bitmap image2;

                public Form1()
                {
                this.InitializeComponent();
                }

                private void button1_Click(object sender, EventArgs e)
                {
                using (var openDialog = new OpenFileDialog())
                {
                if (openDialog.ShowDialog() != DialogResult.OK)
                {
                return;
                }

                this.DisposeImage1();
                this.image1 = new Bitmap(openDialog.FileName);
                }

                this.pictureBox1.Image = this.image1;
                }

                private void button2_Click(object sender, EventArgs e)
                {
                using (var openDialog = new OpenFileDialog())
                {
                if (openDialog.ShowDialog() != DialogResult.OK)
                {
                return;
                }

                this.DisposeImage2();
                this.image2 = new Bitmap(openDialog.FileName);
                }

                this.pictureBox2.Image = this.image2;
                }

                private void button3_Click(object sender, EventArgs e)
                {
                MessageBox.Show(Compare(this.image1, this.image2) ? "Same Image." : "Different Image.");
                }

                private void Form1_FormClosed(object sender, FormClosedEventArgs e)
                {
                this.DisposeImage2();
                this.DisposeImage1();
                }

                private static bool Compare(Bitmap bmp1, Bitmap bmp2)
                {
                // Test to see if we have the same size of image
                if (bmp1.Size != bmp2.Size)
                {
                return false;
                }

                var rect = new Rectangle(0, 0, bmp1.Width, bmp1.Height);
                var bmpData1 = bmp1.LockBits(rect, ImageLockMode.ReadOnly, bmp1.PixelFormat);

                try
                {
                var bmpData2 = bmp2.LockBits(rect, ImageLockMode.ReadOnly, bmp1.PixelFormat);

                try
                {
                unsafe
                {
                var ptr1 = (byte*)bmpData1.Scan0.ToPointer();
                var ptr2 = (byte*)bmpData2.Scan0.ToPointer();
                var width = 3 * rect.Width; // for 24bpp pixel data

                for (var y = 0; y < rect.Height; y++)
                {
                for (var x = 0; x < width; x++)
                {
                if (*ptr1 != *ptr2)
                {
                return false;
                }

                ptr1++;
                ptr2++;
                }

                ptr1 += bmpData1.Stride - width;
                ptr2 += bmpData2.Stride - width;
                }
                }
                }
                finally
                {
                bmp2.UnlockBits(bmpData2);
                }
                }
                finally
                {
                bmp1.UnlockBits(bmpData1);
                }

                return true;
                }

                private void DisposeImage1()
                {
                if (this.image1 == null)
                {
                return;
                }

                this.pictureBox1.Image = null;
                this.image1.Dispose();
                this.image1 = null;
                }

                private void DisposeImage2()
                {
                if (this.image2 == null)
                {
                return;
                }

                this.pictureBox2.Image = null;
                this.image2.Dispose();
                this.image2 = null;
                }






                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Apr 13 '17 at 12:40









                Community

                1




                1










                answered Jan 24 '14 at 19:05









                Jesse C. Slicer

                11.3k2740




                11.3k2740












                • ImageLockMode doesn't exist? Also, the unsafe I'm getting an error
                  – puretppc
                  Jan 24 '14 at 19:17






                • 1




                  You'll need to check enable unsafe code on the Build page of your project's options. Also, add using System.Drawing.Imaging to your using directives at the top of the file to get access to ImageLockMode.
                  – Jesse C. Slicer
                  Jan 24 '14 at 20:53










                • in "var bmpData2 = bmp2.LockBits(rect, ImageLockMode.ReadOnly, bmp1.PixelFormat)" last parameter bmp1.PixelFormat or bmp2.PixelFormat?
                  – Sajitha Rathnayake
                  Aug 15 '14 at 5:26










                • I got error "Bitmap region is already locked." in code "var bmpData2 = bmp2.LockBits(rect, ImageLockMode.ReadOnly, bmp1.PixelFormat)"
                  – Sajitha Rathnayake
                  Aug 15 '14 at 5:30




















                • ImageLockMode doesn't exist? Also, the unsafe I'm getting an error
                  – puretppc
                  Jan 24 '14 at 19:17






                • 1




                  You'll need to check enable unsafe code on the Build page of your project's options. Also, add using System.Drawing.Imaging to your using directives at the top of the file to get access to ImageLockMode.
                  – Jesse C. Slicer
                  Jan 24 '14 at 20:53










                • in "var bmpData2 = bmp2.LockBits(rect, ImageLockMode.ReadOnly, bmp1.PixelFormat)" last parameter bmp1.PixelFormat or bmp2.PixelFormat?
                  – Sajitha Rathnayake
                  Aug 15 '14 at 5:26










                • I got error "Bitmap region is already locked." in code "var bmpData2 = bmp2.LockBits(rect, ImageLockMode.ReadOnly, bmp1.PixelFormat)"
                  – Sajitha Rathnayake
                  Aug 15 '14 at 5:30


















                ImageLockMode doesn't exist? Also, the unsafe I'm getting an error
                – puretppc
                Jan 24 '14 at 19:17




                ImageLockMode doesn't exist? Also, the unsafe I'm getting an error
                – puretppc
                Jan 24 '14 at 19:17




                1




                1




                You'll need to check enable unsafe code on the Build page of your project's options. Also, add using System.Drawing.Imaging to your using directives at the top of the file to get access to ImageLockMode.
                – Jesse C. Slicer
                Jan 24 '14 at 20:53




                You'll need to check enable unsafe code on the Build page of your project's options. Also, add using System.Drawing.Imaging to your using directives at the top of the file to get access to ImageLockMode.
                – Jesse C. Slicer
                Jan 24 '14 at 20:53












                in "var bmpData2 = bmp2.LockBits(rect, ImageLockMode.ReadOnly, bmp1.PixelFormat)" last parameter bmp1.PixelFormat or bmp2.PixelFormat?
                – Sajitha Rathnayake
                Aug 15 '14 at 5:26




                in "var bmpData2 = bmp2.LockBits(rect, ImageLockMode.ReadOnly, bmp1.PixelFormat)" last parameter bmp1.PixelFormat or bmp2.PixelFormat?
                – Sajitha Rathnayake
                Aug 15 '14 at 5:26












                I got error "Bitmap region is already locked." in code "var bmpData2 = bmp2.LockBits(rect, ImageLockMode.ReadOnly, bmp1.PixelFormat)"
                – Sajitha Rathnayake
                Aug 15 '14 at 5:30






                I got error "Bitmap region is already locked." in code "var bmpData2 = bmp2.LockBits(rect, ImageLockMode.ReadOnly, bmp1.PixelFormat)"
                – Sajitha Rathnayake
                Aug 15 '14 at 5:30












                up vote
                0
                down vote













                Why convert in base64 or compare every pixel if there's hash comparison?
                Do something like this:



                byte fileData = File.ReadAllBytes(filePath);
                byte hash = MD5.Create().ComputeHash(fileData);


                And simply compare the hashes.



                You'll need MD5CryptoServiceProvider for that.






                share|improve this answer








                New contributor




                F.H. is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                Check out our Code of Conduct.






















                  up vote
                  0
                  down vote













                  Why convert in base64 or compare every pixel if there's hash comparison?
                  Do something like this:



                  byte fileData = File.ReadAllBytes(filePath);
                  byte hash = MD5.Create().ComputeHash(fileData);


                  And simply compare the hashes.



                  You'll need MD5CryptoServiceProvider for that.






                  share|improve this answer








                  New contributor




                  F.H. is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                  Check out our Code of Conduct.




















                    up vote
                    0
                    down vote










                    up vote
                    0
                    down vote









                    Why convert in base64 or compare every pixel if there's hash comparison?
                    Do something like this:



                    byte fileData = File.ReadAllBytes(filePath);
                    byte hash = MD5.Create().ComputeHash(fileData);


                    And simply compare the hashes.



                    You'll need MD5CryptoServiceProvider for that.






                    share|improve this answer








                    New contributor




                    F.H. is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                    Check out our Code of Conduct.









                    Why convert in base64 or compare every pixel if there's hash comparison?
                    Do something like this:



                    byte fileData = File.ReadAllBytes(filePath);
                    byte hash = MD5.Create().ComputeHash(fileData);


                    And simply compare the hashes.



                    You'll need MD5CryptoServiceProvider for that.







                    share|improve this answer








                    New contributor




                    F.H. is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                    Check out our Code of Conduct.









                    share|improve this answer



                    share|improve this answer






                    New contributor




                    F.H. is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                    Check out our Code of Conduct.









                    answered 7 hours ago









                    F.H.

                    11




                    11




                    New contributor




                    F.H. is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                    Check out our Code of Conduct.





                    New contributor





                    F.H. is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                    Check out our Code of Conduct.






                    F.H. is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                    Check out our Code of Conduct.






















                        up vote
                        -1
                        down vote













                        Have a look at this SO question.



                        https://stackoverflow.com/q/35151067/4062881



                        It decreases the size of image, turns it B&W, and then uses GetPixel() to generate hash.



                        It is much faster, efficient, and works! It is able to find equal images with:




                        • different file formats (e.g. jpg, png, bmp)

                        • rotation (90, 180, 270) - by changing the iteration order of i and j

                        • different dimensions (same aspect is required)

                        • different compression (tolerance is required in case of quality loss like jpeg artifacts) - you can accept a 99% equality to be the same image and 50% to be a different one.


                        Cheers..!! ;)






                        share|improve this answer

























                          up vote
                          -1
                          down vote













                          Have a look at this SO question.



                          https://stackoverflow.com/q/35151067/4062881



                          It decreases the size of image, turns it B&W, and then uses GetPixel() to generate hash.



                          It is much faster, efficient, and works! It is able to find equal images with:




                          • different file formats (e.g. jpg, png, bmp)

                          • rotation (90, 180, 270) - by changing the iteration order of i and j

                          • different dimensions (same aspect is required)

                          • different compression (tolerance is required in case of quality loss like jpeg artifacts) - you can accept a 99% equality to be the same image and 50% to be a different one.


                          Cheers..!! ;)






                          share|improve this answer























                            up vote
                            -1
                            down vote










                            up vote
                            -1
                            down vote









                            Have a look at this SO question.



                            https://stackoverflow.com/q/35151067/4062881



                            It decreases the size of image, turns it B&W, and then uses GetPixel() to generate hash.



                            It is much faster, efficient, and works! It is able to find equal images with:




                            • different file formats (e.g. jpg, png, bmp)

                            • rotation (90, 180, 270) - by changing the iteration order of i and j

                            • different dimensions (same aspect is required)

                            • different compression (tolerance is required in case of quality loss like jpeg artifacts) - you can accept a 99% equality to be the same image and 50% to be a different one.


                            Cheers..!! ;)






                            share|improve this answer












                            Have a look at this SO question.



                            https://stackoverflow.com/q/35151067/4062881



                            It decreases the size of image, turns it B&W, and then uses GetPixel() to generate hash.



                            It is much faster, efficient, and works! It is able to find equal images with:




                            • different file formats (e.g. jpg, png, bmp)

                            • rotation (90, 180, 270) - by changing the iteration order of i and j

                            • different dimensions (same aspect is required)

                            • different compression (tolerance is required in case of quality loss like jpeg artifacts) - you can accept a 99% equality to be the same image and 50% to be a different one.


                            Cheers..!! ;)







                            share|improve this answer












                            share|improve this answer



                            share|improve this answer










                            answered May 30 '17 at 9:43









                            Vijay Chavda

                            992




                            992

















                                protected by Jamal 5 hours ago



                                Thank you for your interest in this question.
                                Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).



                                Would you like to answer one of these unanswered questions instead?



                                Popular posts from this blog

                                404 Error Contact Form 7 ajax form submitting

                                How to know if a Active Directory user can login interactively

                                TypeError: fit_transform() missing 1 required positional argument: 'X'