3

I want to compare two bmp files. I thought of two approaches:

  1. to compare the header as well as the information header of the two files
  2. convert the bmp file to binary and then do the above comparison

But, I don't know how to start and which will be a better approach. I would be glad if someone could please help me!

nickf
  • 537,072
  • 198
  • 649
  • 721
  • What type of comparison are you doing? Do you want to check whether they are identical copies? or do you want to check if they are similar images? The The first one is simple to do and the second one is a bit more tricky. – Niyaz Mar 16 '09 at 09:18
  • I have a code in ANSI C to normalize both files to 32bpp before comparison. I am not posting it because you seem to be satisfied with C# code already – George Robinson May 20 '19 at 23:11

5 Answers5

1

I don't know on which platform you want to implement this, but here are some code snippets which could be useful:

Compare two images with C#

This is a snippet to compare 2 images to see if they are the same. This method first converts each Bitmap to a byte array, then gets the hash of each array. We then loop through each in the hash to see if they match.

/// <summary>
/// method for comparing 2 images to see if they are the same. First
/// we convert both images to a byte array, we then get their hash (their
/// hash should match if the images are the same), we then loop through
/// each item in the hash comparing with the 2nd Bitmap
/// </summary>
/// <param name="bmp1"></param>
/// <param name="bmp2"></param>
/// <returns></returns>
public bool doImagesMatch(ref Bitmap bmp1, ref Bitmap bmp2)
{
  ...
}
splattne
  • 102,760
  • 52
  • 202
  • 249
0

Well, you have at least two options here:

  • The images are mostly the same
    In this case, I'd recommend a compare using splattne's solution

  • The images are usually different, and only sometimes the same
    In this case, it might be that you can dismiss any similarity between the two images with a quick comparison of the information header (think "is the size the same?), and only do the full comparison if the information is ambiguous (i.e. the size is the same)

winsmith
  • 20,791
  • 9
  • 39
  • 49
0

You may want to use an extension method in .NET 3.0+ for this to expose the compare method on all the Bitmaps:

    public static bool Compare(this Bitmap bmp1, Bitmap bmp2)
    {
        //put your comparison logic here
    }
0

What are you comparing for? Are you looking to see if 2 images are exactly the same? Or do you need degrees of difference? For exact matches how about creating and comparing hashes of both files?

0

The above solutions didn't work for me when I had two images that only differed in color depth--one was 32bpp and the other was 8bpp. The solution I arrived at used LockBits to convert all images to 32bpp, Marshal.Copy() to get the data into an array and then just compare the arrays.

/// <summary>
/// Compares two images for pixel equality
/// </summary>
/// <param name="fname1">first image file</param>
/// <param name="fname2">second image file</param>
/// <returns>true if images are identical</returns>
public static string PageCompare(string fname1, string fname2) {
    try {
        using (Bitmap bmp1 = new Bitmap(fname1))
        using (Bitmap bmp2 = new Bitmap(fname2)) {
            if (bmp1.Height != bmp2.Height || bmp1.Width != bmp2.Width)
                return false;

            // Convert image to int32 array with each int being one pixel
            int cnt = bmp1.Width * bmp1.Height * 4 / 4;
            BitmapData bmData1 = bmp1.LockBits(new Rectangle(0, 0, bmp1.Width, bmp1.Height),
                ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
            BitmapData bmData2 = bmp2.LockBits(new Rectangle(0, 0, bmp2.Width, bmp2.Height),
                ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);

            Int32[] rgbValues1 = new Int32[cnt];
            Int32[] rgbValues2 = new Int32[cnt];

            // Copy the ARGB values into the array.
            System.Runtime.InteropServices.Marshal.Copy(bmData1.Scan0, rgbValues1, 0, cnt);
            System.Runtime.InteropServices.Marshal.Copy(bmData2.Scan0, rgbValues2, 0, cnt);

            bmp1.UnlockBits(bmData1);
            bmp2.UnlockBits(bmData2);
            for (int i = 0; i < cnt; ++i) {
                if (rgbValues1[i] != rgbValues2[i])
                    return false;
            }
        }
    }
    catch (Exception ex) {
        return false;
    }
    // We made it this far so the images must match
    return true;
}
Keith
  • 543
  • 3
  • 8