21 Jun

C# Fast Bitmap Compare

This example controls that two bitmap object are same or not. In first method, we use the GetPixel method in Bitmap class. In second example, we use the memory comparison using BitmapData class. “Frog 1” and “Frog 2” files has 1024×768 pixel size. Their thumbnails are shown below. As result:

Total time in first example(Lazy Comparison): ~1644 ms
Total time in second example(Fast Comprasion): ~10 ms

Usage:

            Bitmap bmp1 = (Bitmap)Bitmap.FromFile(@"C:\test\Frog 1.bmp");
            Bitmap bmp2 = (Bitmap)Bitmap.FromFile(@"C:\test\Frog 2.bmp");

            Stopwatch sw = new Stopwatch();
            
            sw.Start();
            bool res1 = BitmapComprasion.CompareBitmapsLazy(bmp1, bmp2);
            sw.Stop();
            Console.WriteLine(string.Format("CompareBitmapsLazy Time: {0} ms", sw.ElapsedMilliseconds));

            sw.Restart();
            bool res2 = BitmapComprasion.CompareBitmapsFast(bmp1, bmp2);
            sw.Stop();
            Console.WriteLine(string.Format("CompareBitmapsFast Time: {0} ms", sw.ElapsedMilliseconds));

            //Output:
            //CompareBitmapsLazy Time: 1644 ms
            //CompareBitmapsFast Time: 10 ms
Frog 1 Thumbnail Frog 2 Thumbnail
Frog 1 Frog 2

Fast Bitmap Comparison Example:

        public static bool CompareBitmapsFast(Bitmap bmp1, Bitmap bmp2)
        {
            if (bmp1 == null || bmp2 == null)
                return false;
            if (object.Equals(bmp1, bmp2))
                return true;
            if (!bmp1.Size.Equals(bmp2.Size) || !bmp1.PixelFormat.Equals(bmp2.PixelFormat))
                return false;

            int bytes = bmp1.Width * bmp1.Height * (Image.GetPixelFormatSize(bmp1.PixelFormat) / 8);

            bool result = true;
            byte[] b1bytes = new byte[bytes];
            byte[] b2bytes = new byte[bytes];

            BitmapData bitmapData1 = bmp1.LockBits(new Rectangle(0, 0, bmp1.Width, bmp1.Height), ImageLockMode.ReadOnly, bmp1.PixelFormat);
            BitmapData bitmapData2 = bmp2.LockBits(new Rectangle(0, 0, bmp2.Width, bmp2.Height), ImageLockMode.ReadOnly, bmp2.PixelFormat);

            Marshal.Copy(bitmapData1.Scan0, b1bytes, 0, bytes);
            Marshal.Copy(bitmapData2.Scan0, b2bytes, 0, bytes);

            for (int n = 0; n <= bytes - 1; n++)
            {
                if (b1bytes[n] != b2bytes[n])
                {
                    result = false;
                    break;
                }
            }

            bmp1.UnlockBits(bitmapData1);
            bmp2.UnlockBits(bitmapData2);

            return result;
        }

Classic Bitmap Comparison Example:

        public static bool CompareBitmapsLazy(Bitmap bmp1, Bitmap bmp2)
        {
            if (bmp1 == null || bmp2 == null)
                return false;
            if (object.Equals(bmp1, bmp2))
                return true;
            if (!bmp1.Size.Equals(bmp2.Size) || !bmp1.PixelFormat.Equals(bmp2.PixelFormat))
                return false;

            //Compare bitmaps using GetPixel method
            for (int column = 0; column < bmp1.Width; column++)
            {
                for (int row = 0; row < bmp1.Height; row++)
                {
                    if (!bmp1.GetPixel(column, row).Equals(bmp2.GetPixel(column, row)))
                        return false;
                }
            }

            return true;
        }