2

I have the following codes to convert an image(bitmap) to byte array:

public byte[] ConvertImageToByteArray(Image imageToConvert, ImageFormat formatOfImage)
{
    byte[] Ret;
    try
    {
        using (MemoryStream ms = new MemoryStream())
        {
            imageToConvert.Save(ms, formatOfImage);
            Ret = ms.ToArray();
        }
    }
    catch (Exception) 
    { 
        throw;
    }

    return Ret;
}

and Convert byte array back to image(bitmap):

public Bitmap ConvertByteArrayToImage(byte[] myByteArray)
{
    Image newImage;

    using (MemoryStream ms = new MemoryStream(myByteArray, 0, myByteArray.Length))
    {
        ms.Write(myByteArray, 0, myByteArray.Length);
        newImage = Image.FromStream(ms, true);
    }
    return newImage;
 }

Here's my Main Program:

    byte[] test = ConvertImageToByteArray(Image.FromFile("oldImage.bmp"), ImageFormat.Bmp);

    Bitmap bmp = ConvertByteArrayToImage(test);
    bmp.Save("newImage.bmp");

But when I compare both of the image files(old & new bitmap images), their checksum appeared to be different. Any reason for that happening? How to fix it to maintain its integrity?

Roy Lee
  • 10,572
  • 13
  • 60
  • 84
  • Are the files the same size? Are you saving with the same bits per pixel? – John Koerner Oct 25 '12 at 09:02
  • Yes they had the same size. I didn't modify the content when I was running the program. All I did is read the image to byte array and convert the byte array back to image. I wonder why the checksum is different. – Roy Lee Oct 25 '12 at 09:04
  • If the files are the exact same, they should produce the same checksum. Open a binary compare tool like [UltraCompare](http://www.ultraedit.com/products/ultracompare/tour/binary-file-compare.html) and see if there are any differences. It is possible that the bits per pixel are different or that something in the bitmap header changed. – John Koerner Oct 25 '12 at 09:05
  • I see I see, so any way to keep their checksum same? Thanks for the quick reply :) – Roy Lee Oct 25 '12 at 09:07
  • 1
    If you can figure out what is changing, you might be able to set a property on the bitmap encoder to ensure that it is writing the value correctly. The BMP file format is pretty well [documented](http://en.wikipedia.org/wiki/BMP_file_format), so it should be pretty easy to determine what is changing. – John Koerner Oct 25 '12 at 09:10
  • I found out that if I run the program with the 'newImage.bmp', the new 'newImage1.bmp' actually having the same checksum, so does it means the program has changed their header at the first place? which is what you'ev mentioned. – Roy Lee Oct 25 '12 at 09:16
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/18562/discussion-between-john-koerner-and-roylee) – John Koerner Oct 25 '12 at 09:18

2 Answers2

2

Basically, there are many ways an identical image can be encoded in a BMP file. If I try your example on a random image I found, I see the .NET Bitmap class saves the file without filling the biSizeImage field in the BITMAPINFOHEADER structure in the BMP header (but the original image produced by IrfanView has it filled), which is a completely correct and documented possibility. (“This may be set to zero for BI_RGB bitmaps.”)

And this is definitely not the only variable thing in the BMP format. For instance, there are multiple possible orderings of pixel data in the image (top-to-bottom, bottom-to-top), specified in the header. (“If biHeight is positive, the bitmap is a bottom-up DIB and its origin is the lower-left corner. If biHeight is negative, the bitmap is a top-down DIB and its origin is the upper-left corner.”)

So, if you receive any BMP file from a source not under your control and really need to produce an image using exactly the same BMP variant, you have a lot work to do, and I don’t think you could use the standard .NET helper classes for that.

See also this question: Save bitmap to file has zero in image size field

Community
  • 1
  • 1
Mormegil
  • 7,955
  • 4
  • 42
  • 77
  • I see, I have checked their hex and found out the front bits are different after .NET C#. Actually I'm working out on enc/decrypt on image file: bmp, C#. So my attempt was to convert the image file into byte array before encryption. I think I have to lose this way, any other method ? – Roy Lee Oct 25 '12 at 09:37
  • 1
    You either want to encrypt/decrypt _images_, then why bother checking if the exact bytes in the _file_ are identical, if the images are? Or you want to encrypt/decrypt _files_, then do not process them with `Bitmap`, just load the file as plain old `byte[]`. – Mormegil Oct 25 '12 at 09:41
1

After chatting a bit, you solution comes down to reading and writing bytes, take the image object out the equation and just deal with the raw bytes.

To read the file:

    MemoryStream ms = new MemoryStream(File.ReadAllBytes("filename"));

To write the file:

    File.WriteAllBytes("outputfile", ms.ToArray());
John Koerner
  • 37,428
  • 8
  • 84
  • 134