Thread: Reading Bitmap File Header Problem.

  1. #1
    Registered User
    Join Date
    Apr 2004
    Posts
    21

    Reading Bitmap File Header Problem.

    Hello,

    Ive been at this for hours and cant figure out where its going wrong. Im simply trying to open a bitmap read its header information into a struct and display it. Ive checked around and think this structure is correct for what im trying to do. On my system short is 2 bytes and long is 4 bytes. The only thing which is correct in my output is the Type at the top, after that the figures are not correct. Im compiling on a linux box using gcc and am trying to read a small bitmap made in ms paint.

    Could someone have a look at this and advise where im going wrong. Ive really tried to figure out for myself and considered its something to do with padding maybe ? This is the first time ive messed around with file headers though so could use some advice.

    Thank You.

    Stan.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    struct BitMap
    {
      short Type;
      long Size;
      short Reserve1;
      short Reserve2;
      long OffBits;
      long biSize;
      long biWidth;
      long biHeight;
      short biPlanes;
      short biBitCount;
      long biCompression;
      long biSizeImage;
      long biXPelsPerMeter;
      long biYPelsPerMeter;
      long biClrUsed;
      long biClrImportant;
    } Header;
    
    int main( void )
    {
      FILE *BMPFile = fopen ("paint.bmp", "rb");
    
      if (BMPFile == NULL)
        return;
      
      memset(&Header, 0, sizeof(Header));
      
      fread(&Header, 54, 1, BMPFile);
    
      printf("\nType:%d\n", Header.Type);
      printf("Size:%d\n", Header.Size);  
      printf("Reserve1:%d\n", Header.Reserve1);  
      printf("Reserve2:%d\n", Header.Reserve2);
      printf("OffBits:%d\n", Header.OffBits); 
      printf("biSize:%d\n", Header.biSize);      
      printf("Width:%d\n", Header.biWidth);    
      printf("Height:%d\n", Header.biHeight);  
      printf("biPlanes:%d\n", Header.biPlanes);  
      printf("biBitCount:%d\n", Header.biBitCount);
      printf("biCompression:%d\n", Header.biCompression);  
      printf("biSizeImage:%d\n", Header.biSizeImage);  
      printf("biXPelsPerMeter:%d\n", Header.biXPelsPerMeter);  
      printf("biYPelsPerMeter:%d\n", Header.biYPelsPerMeter);  
      printf("biClrUsed:%d\n", Header.biClrUsed);  
      printf("biClrImportant:%d\n\n", Header.biClrImportant);  
    
      fclose(BMPFile);
      
      return 0;
    }
    Output :

    Code:
    Type:19778
    Size:1
    Reserve1:0
    Reserve2:118
    OffBits:2621440
    biSize:33554432
    Width:25165824
    Height:65536
    biPlanes:4
    biBitCount:0
    biCompression:-2147483648
    biSizeImage:247726081
    biXPelsPerMeter:247726080
    biYPelsPerMeter:0
    biClrUsed:0
    biClrImportant:0

  2. #2
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,218
    Yes, it has to do with padding. Most compilers word-align struct members, so your 'short' members are probably taking up 4 bytes instead of the expected 2. Depending on the compiler you're using, you should be able to instruct it to use the struct as "packed".
    If you understand what you're doing, you're not learning anything.

  3. #3
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Also, use "%hd" for shorts and "%ld" for longs. And the prototype for memset is in <string.h>.
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  4. #4
    Registered User
    Join Date
    Mar 2004
    Posts
    536
    Quote Originally Posted by StanleyC
    Hello,

    Ive been at this for hours and cant figure out where its going wrong. Im simply trying to open a bitmap read its header information into a struct and display it. Ive checked around and think this structure is correct for what im trying to do. On my system short is 2 bytes and long is 4 bytes. The only thing which is correct in my output is the Type at the top, after that the figures are not correct. Im compiling on a linux box using gcc and am trying to read a small bitmap made in ms paint.

    Could someone have a look at this and advise where im going wrong. Ive really tried to figure out for myself and considered its something to do with padding maybe ? This is the first time ive messed around with file headers though so could use some advice.


    Thank You.

    Stan.
    Here's a suggestion: If you know what's supposed to be in the file (size, width, height, etc.) but your program can't read them in correctly: Use a utility, like dump, if you have it on your system, or write a program that just shows hex values of the bytes in the program.

    That is, instead of reading in the structure that you are assuming, just read some 50 or 60 bytes into a char array. Then look at the bytes to see if you can deduce where the ints, or whatever, are actually stored.

    For example if you look at the first two bytes in your file, you will see
    0x42, 0x4d. What does this mean to you, well, remembering that this is a Windows-type file, it probably stores numeric values in little-endian mode, and the number 0x4d42 is equal to decimal 19778. Our first success! We understand the first two bytes of the file.

    Now the size of the file is next. I don't have your file to work with, but for my .bmp file, the next four bytes are 0x32, 0x25, 0x00, 0x00.

    Now, I don't know whether size is a two-byte or four-byte quantity, but in either case, the size has value 0x2532, which is equal to 9522 decimal. I look at the dir listing for the file, and I see that its size is 9522 bytes!. Well, at least something is working. If you see the correct bytes, but you can't read them into your struct with your program, it's very well may have something to do with padding. Instead of reading the entire struct, maybe you can think abour reading each element separately. That is, read two bytes into Header.type, then read four bytes into Header.size, etc.

    Now just to poke around a little, I know that my bitmap is 96x96, so I look for bytes 0x60 in various places among the bytes that I can see, and so I can nail down the locations within the file, just to make sure I understand how things are really done.

    Now, after poking around a little, I'll bet you will know a lot about bitmaps and a little about files in C. (More than if you just plugged in some code that someone else wrote for a class project some time ago.)



    Regards,

    Dave

  5. #5
    Registered User
    Join Date
    Apr 2004
    Posts
    21
    Thanks for the advice. I read up about allignment and padding and from what i read it looked liked the problem was related to how my struct was laid out. Apparently if I had laid it out biggest to smaller in a logical order the compiler wouldnt have padded it, but because I wanted to stream it in from fread I had to have the struct in the order the data was coming in..

    I couldnt find out how to disable padding on that struct so as temp fix I just read the data into each struct separately which seems to have done the trick. Now my code looks like this and the output below the code is now correct.

    Guess now im going to have to figure out how to disable padding by the compiler which sounds a pretty scary thing to do.

    Thanks for all suggestions.

    Stan

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    struct BitMap
    {
      short Type;
      long Size;
      short Reserve1;
      short Reserve2;
      long OffBits;
      long biSize;
      long biWidth;
      long biHeight;
      short biPlanes;
      short biBitCount;
      long biCompression;
      long biSizeImage;
      long biXPelsPerMeter;
      long biYPelsPerMeter;
      long biClrUsed;
      long biClrImportant;
    } Header;
    
    int main( void )
    {
      FILE *BMPFile = fopen ("24.bmp", "rb");
    
      if (BMPFile == NULL)
        return;
      
      memset(&Header, 0, sizeof(Header));
      
      fread(&Header.Type, 2, 1, BMPFile);
      fread(&Header.Size, 4, 1, BMPFile);
      fread(&Header.Reserve1, 2, 1, BMPFile);
      fread(&Header.Reserve2, 2, 1, BMPFile);
      fread(&Header.OffBits, 4, 1, BMPFile);
      fread(&Header.biSize, 4, 1, BMPFile);
      fread(&Header.biWidth, 4, 1, BMPFile);
      fread(&Header.biHeight, 4, 1, BMPFile);
      fread(&Header.biPlanes, 2, 1, BMPFile);
      fread(&Header.biBitCount, 2, 1, BMPFile);
      fread(&Header.biCompression, 4, 1, BMPFile);
      fread(&Header.biSizeImage, 4, 1, BMPFile);
      fread(&Header.biXPelsPerMeter, 4, 1, BMPFile);
      fread(&Header.biYPelsPerMeter, 4, 1, BMPFile);
      fread(&Header.biClrUsed, 4, 1, BMPFile);
      fread(&Header.biClrImportant, 4, 1, BMPFile);
                  
      printf("\nType:%hd\n", Header.Type);
      printf("Size:%ld\n", Header.Size);  
      printf("Reserve1:%hd\n", Header.Reserve1);  
      printf("Reserve2:%hd\n", Header.Reserve2);
      printf("OffBits:%ld\n", Header.OffBits); 
      printf("biSize:%ld\n", Header.biSize);      
      printf("Width:%ld\n", Header.biWidth);    
      printf("Height:%ld\n", Header.biHeight);  
      printf("biPlanes:%hd\n", Header.biPlanes);  
      printf("biBitCount:%hd\n", Header.biBitCount);
      printf("biCompression:%ld\n", Header.biCompression);  
      printf("biSizeImage:%ld\n", Header.biSizeImage);  
      printf("biXPelsPerMeter:%ld\n", Header.biXPelsPerMeter);  
      printf("biYPelsPerMeter:%ld\n", Header.biYPelsPerMeter);  
      printf("biClrUsed:%ld\n", Header.biClrUsed);  
      printf("biClrImportant:%ld\n\n", Header.biClrImportant);  
      
      fclose(BMPFile);
      
      return 0;
    }
    Ouput :

    Code:
    Type:19778
    Size:1254
    Reserve1:0
    Reserve2:0
    OffBits:54
    biSize:40
    Width:20
    Height:20
    biPlanes:1
    biBitCount:24
    biCompression:0
    biSizeImage:1200
    biXPelsPerMeter:2834
    biYPelsPerMeter:2834
    biClrUsed:0
    biClrImportant:0

  6. #6
    Registered User
    Join Date
    Mar 2004
    Posts
    536
    Quote Originally Posted by StanleyC
    Guess now im going to have to figure out how to disable padding by the compiler which sounds a pretty scary thing to do.
    It's OK to try new things, and I think it is a Good Thing to understand such things. However, if you want to use your program, now and forever, regardless of changes in compilers and/or compiler command-line switches, etc., I don't see any shame in using it in its present form.

    Congratulations! Onward and upward!!!

    Dave

  7. #7
    Registered User
    Join Date
    Apr 2004
    Posts
    21
    Dave, Sorry I was in the middle of posting a reply while your post came in. I agree, trying to determine whats in a file on your own would result in you learning more than using a predefined struct however I was just experimenting with file headers for the first time today and hadnt experienced compiler padding problems before. Saying that though ive learnt alot and ill bear in mind what you have said about figuring out file header formats.

    Thanks

    Stan

  8. #8
    Registered User
    Join Date
    Mar 2004
    Posts
    536
    Quote Originally Posted by StanleyC
    Dave, Sorry

    Stan
    I can't imagine why you would say, "sorry." You got it done!. My only point (other than the one on top of my head) was that if you find yourself stuck: you know what's supposed to be in the file, but your program doesn't seem to be reading it correctly, then you might try another approach. Namely, find out exactly what is in the file byte-by-byte, then go on.

    I can't tell you how glad I am that you got it without someone jumping in and posting a finished program already written in its entirety.

    Regards,

    Dave

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Problem reading a password from a file.
    By medeshago in forum C Programming
    Replies: 15
    Last Post: 12-21-2008, 07:20 AM
  2. Problem reading BMP
    By Mortissus in forum C Programming
    Replies: 4
    Last Post: 02-02-2006, 06:32 AM
  3. Problem reading file.
    By Hulag in forum C Programming
    Replies: 11
    Last Post: 10-24-2004, 09:39 AM
  4. what does this mean to you?
    By pkananen in forum C++ Programming
    Replies: 8
    Last Post: 02-04-2002, 03:58 PM