0

Because BMP files are written from bottom to top (in terms of pixels), I need to read a BMP file in reverse (and get rid of the 54-byte header). My code so far:

public string createNoHeaderBMP(string curBMP)  //copies everything but the header    from the curBMP to the tempBMP
    {
        string tempBMP = "C:\\TEMP.bmp";

        Stream inStream = File.OpenRead(curBMP);
        BinaryReader br = new BinaryReader(inStream);

        byte[] fullBMP = new byte[(width * height * 3) + 138];
        byte[] buffer = new Byte[1];
        long bytesRead;
        long totalBytes = 0;

        while ((bytesRead = br.Read(buffer, 0, 1)) > 0)
        {
            fullBMP[fullBMP.Length - 1 - totalBytes] = buffer[0];
            totalBytes++;
        }

        FileStream fs = new FileStream(tempBMP, FileMode.Create, FileAccess.Write);
        fs.Write(fullBMP, 54, fullBMP.Length - 54);
        fs.Close();
        fs.Dispose();

        return tempBMP;
    }

for some reason it fails to do the job completely, and this results in an image with part of the right side placed on the left. Why isn't it completely reversing the file? Also, these BMP files are very large (600MB), so I can't use a simple memorystream and do a seek and swap operation because I'll get the "Out of Memory" exception.

Aeon2058
  • 527
  • 6
  • 22
  • Why so you mention that you can't read the entire file, yet you just did? Also, NEVER hard code a value for the array like you did. It's not guaranteed that there will be EXACTLY 138 bytes of header data. – Cole Tobin Apr 01 '13 at 13:15
  • 3
    If using a MemoryStream would get you an OOM exception, how are you able to allocate space for the `fullBMP` array without receiving the same exception? – cdhowie Apr 01 '13 at 13:17
  • 1
    MemoryStream and Byte[] are essentially the same thing, MS has some additional wrappers which can make it easier to handle though... see http://stackoverflow.com/questions/16939/difference-between-a-byte-array-and-memorystream AND http://stackoverflow.com/questions/11828599/c-sharp-memorystream-vs-byte-array – Nevyn Apr 01 '13 at 13:27

2 Answers2

2

I haven't checked the BMP specification, and I don't have any knowledge of it. I'll just assume that what you say is true.

Most programs that display bitmaps just read the header to find out how big the image is, and then read the data from top to bottom, painting the bitmap from bottom to top instead. And you can also seek in most files. So you could use inStream and seek in that, without ever needing to have the whole file in memory.

Then, if you can allocate a byte array of 600 MiB (i.e. a 600 MiB structure in memory), then surely you can allocate a MemoryStream that takes up to 600 MiB of memory space. Or, if you get an OutOfMemoryException, then you'll get it regardless of whether you use a byte[] or a MemoryStream. The latter is just easier to work with.

Your idea of just reversing everything will fail unless you realize thay you've also reversed the colors of each pixel from R-G-B format (or whatever it currently is) to B-G-R. And I'm not sure of the direction of BMP scan lines, but if they run from left-to-right, then your reversed bitmap will have the image flipped horizontally.

The reason you have part of the image on the right side displayed on the left is because you can't just reverse a bitmap's bytes and expect it to come out correctly. Also, you probably have the length of a scan line wrong when drawing it.

Also, you say the header is 54 bytes but you add 138 bytes to the array size in fullBMP. Check your constants: are they guaranteed to never change, then make them const. May they change? Then read them from the bitmap.

Daniel A.A. Pelsmaeker
  • 47,471
  • 20
  • 111
  • 157
0

I posted an answer here for reversing a large file without storing it in RAM.

You could use it to do something like this (may need adjustment to get a proper Bitmap as Daniel mentioned):

using (var inputFile = File.OpenRead("input.bmp"))
using (var inputFileReversed = new ReverseStream(inputFile))
using (var outputFile = File.Open("output.bmp", FileMode.Create, FileAccess.Write))
{
    inputFile.Seek(headerSize, SeekOrigin.Begin); //skip the header
    inputFileReversed.CopyTo(outputFile);
}
Fidel
  • 7,027
  • 11
  • 57
  • 81