views:

865

answers:

6

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!

A: 

You can start with this for the second option.

Shoban
+1  A: 

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
A: 

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
A: 

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
    }
A: 

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?

A: 

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