Centro
Centro

Reputation: 4012

Comparing two images problem

I want to compare two images byte by byte. Both of them are 8-bit BMP images and are exactly 40000 bytes in size. The first image is generated in memory as an array of bytes, the second is read from a file into an Image object.

I use MemoryStream instances for the comparison:

    byte[] generatedImage = new byte[40000];
    // some unrelated logic of image generation ...
    MemoryStream imageStream1 = new MemoryStream(generatedImage);

    // loaded image, 200x200 bmp - 40000 bytes
    MemoryStream imageStream2 = new MemoryStream();
    Image loadedImage = Image.FromFile("image.bmp");
    loadedImage.Save(imageStream2, ImageFormat.Bmp);

The problem is that the memory stream of the loaded image imageStream2 contains more than 40000 bytes, as far as I understand it contains some information about BMP itself as well. So the second stream is created with Length equal to 41078 and Position equal to 1278. I would understand if the Position was 1078, but it isn't, and from the position there are less than 40000 bytes left.

In my algorithm I need compare the images as fast as possible, so I rejected an idea of creating bitmaps and comparing via the GetPixel method. I use the MemoryStream.ReadByte method for the comparison.

How can I get "real" BMP bytes from the second Stream? Is there any way in this case to compare the images on byte-to-byte basis?

Upvotes: 3

Views: 1711

Answers (4)

Dan Byström
Dan Byström

Reputation: 9244

Here's a post about comparing to images in C# quite fast. It starts out with a pretty slow version (which is still better than GetPixel) and ends up with a version that is 25 times as fast:

http://danbystrom.se/2008/12/14/improving-performance/

It returns a number that is zero if the images are identical, and the higher the return value is - the more they differ. It should point you in the right direction.

One word of caution, however. It is optimized to work on 32bpp images only. If you have 24bpp images (which a .jpg is by default afterbeing loaded) you either need more "complicated" code or simply convert it into 32bpp. The "complication" is that you then can't do all the comparing in one loop, but instead loop row by row and compare each row individually.

Upvotes: 3

Alireza Maddah
Alireza Maddah

Reputation: 5885

Comparing Images byte by byte is not a good solution to your problem. In this situation, you may use the implementation of one of the Hash algorithms.

A “Hash Function” gets a value of variable length and produces an output with constant length. For instance, SHA256 algorithm gets the input value and generates a 256 bits output. Note that hashes of two sets of data are identical if and only if the corresponding data matches and any minor change in data causes the hash value to change dramatically, so this is a cool method when comparing large amount of data. For more information, read "Hash in a Flash" section of this article: http://www.codeproject.com/KB/GDI-plus/comparingimages.aspx?msg=3503625&display=Mobile

Upvotes: 0

Ansis Māliņš
Ansis Māliņš

Reputation: 1704

http://en.wikipedia.org/wiki/BMP_file_format#Bitmap_file_header

Read 4 bytes at offset 10 to obtain the offset of the pixel data. Read 4 bytes at offset 2 to get the size of the entire thing including header. Subtract the former from the latter to get the size of the pixel data.

Upvotes: 2

Oliver
Oliver

Reputation: 45119

I wouldn't compare them on a byte level. Instead i would put them into a Bitmap. And iterate over all pixel by calling GetPixel(x,y) with all possible values from zero to Width or Height.

Upvotes: 0

Related Questions