Thread: BMP image files reading

  1. #1
    Registered User
    Join Date
    Aug 2012
    Posts
    16

    BMP image files reading

    not 100% sure how im meant to read the image file and verify the first two cahracters are 'B' and 'M'

    using this struct:
    Code:
    typedef struct
    {
    unsigned char fileMarker1; /* 'B' */
    unsigned char fileMarker2; /* 'M' */
    unsigned int bfSize;
    unsigned short unused1;
    unsigned short unused2;
    unsigned int imageDataOffset; /* Offset to the start of image data */
    }FILEHEADER;
    The first two characters 'B' and 'M' indicate that this is a BMP file and their presence must be verified before any further analysis takes place.,

    any little advice for this would be very helpful
    Igor

  2. #2
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    Code:
    include file stuff goes here
    
    typedef struct stuff goes up here
    
    int main(void) {
       //declare your other variables up here if local
       FILEHEADER fileHeader;  //make an instance of the fileheader struct
    
       //open the file(s) in here
       //load the struct from the file here.
    
       if(fileHeader.fileMarker1=='B' && fileHeader.fileMarker2=='M') {
          //it is a bitmap file your other code would go in here
       }
    
       close any file(s) you opened, here
       return 0;
    }
    Welcome to the forum, Igor!
    Last edited by Adak; 08-28-2012 at 08:26 PM.

  3. #3
    Registered User
    Join Date
    Aug 2012
    Posts
    16
    Ohok thanks man heres what im up to so far, not sure if thats right but... it gets the B and M right though

    Code:
    #include <stdio.h>
    
    /* structs  */
    typedef struct
    {
    unsigned char fileMarker1; /* 'B' */
    unsigned char fileMarker2; /* 'M' */
    unsigned int bfSize;
    unsigned short unused1;
    unsigned short unused2;
    unsigned int imageDataOffset; /* Offset to the start of image data */
    }FILEHEADER;
     
    int main(int argc, char *argv[] )
     {   
     FILEHEADER fileHeader;  /* make an instance of the fileheader struct */
     FILE *inbin;
     FILE *outbin;
     char image[256];
     FILEHEADER data;
     
     
         printf("Filename: ");
      scanf("%s", &image);
     
      inbin = fopen(image, "rb");
      
    fread(&data,sizeof(unsigned char),8, inbin);
     
      if (inbin == NULL) 
      {
      printf("The file cannot be opened.\n");
      }
      else 
      {
      printf("filemarker1 = %c\n", data.fileMarker1);
         printf("filemarker2 = %c\n", data.fileMarker2);   
      } 
       
      
        
       
    fclose(inbin);
     
    return 0;
    }

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    First, every compiler may choose it's own way to align individual members within a structure.
    Data structure alignment - Wikipedia, the free encyclopedia
    Endianness - Wikipedia, the free encyclopedia

    Second, do you have a definition of your file format?
    BMP file format - Wikipedia, the free encyclopedia

    The up-shot of all this is you can't just declare a struct with all the right members and then just use fread() to read part of the file onto an instance of that struct. Random bytes from the file will just fall into the "holes" where the compiler inserted padding. Even if bytes end up in the right place, they could be in the wrong order if your machine is a different endian to the file format.

    Some compilers support "#pragma pack()" (or variations) to squeeze out the holes, which MAY allow you to fread directly onto a structure. It may fix padding issues, but it will never fix endian issues.


    The only way to make it foolproof is to read the file as an array of unsigned chars, and then assign members of your struct on a member by member basis.
    Code:
    unsigned char bmHeader[14];  // or whatever size
    fread( bmHeader, 1, sizeof(bmHeader), fp );
    
    // now transfer it to your data
    data.fileMarker1 = bmHeader[0];
    data.fileMarker2 = bmHeader[1];
    data.bfSize = bmHeader[2] + (bmHeader[3] << 8) + (bmHeader[4] << 16) + (bmHeader[5] << 24);
    // and so on
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    Registered User
    Join Date
    Aug 2012
    Posts
    16
    Hi Salem, thanks a lot for your assistance - the file format is the following;
    File Header > Info Header > Image Data

    with the structure as follows:

    insert
    Code:
     
    typedef struct                       
     {     unsigned char fileMarker1;       /* 'B' */                         
           unsigned char fileMarker2;       /* 'M' */  
           unsigned int   bfSize;            
           unsigned short unused1;      
            unsigned short unused2;          
           unsigned int   imageDataOffset;  /* Offset to the start of image data */
      }FILEHEADER;
    
    
    typedef struct                    
       {     unsigned int   biSize;      
             int            width;            /* Width of the image */    
             int            height;           /* Height of the image */    
             unsigned short planes;        
             unsigned short bitPix;        
             unsigned int   biCompression;        
             unsigned int   biSizeImage;       
             int            biXPelsPerMeter; 
             int            biYPelsPerMeter;       
             unsigned int   biClrUsed;        
             unsigned int   biClrImportant;    
     }INFOHEADER;
    
    
    typedef struct          
     {      unsigned char  b;         /* Blue value */    
            unsigned char  g;         /* Green value */     
            unsigned char  r;         /* Red value */
     }IMAGE;
    And yes I was under the impression little endien and big endien would become a problem - so to overcome this you wouldn't recommend using prgmapack? Thanks again for your time.
    Last edited by igor; 08-29-2012 at 04:41 AM.

  6. #6
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Why are you doing this? There are some good APIs out there that make it so easy to load a BMP file in correctly. Any code a beginner writes to do this tends to fail in all sorts of cases. BMP files can contain compression and whatnot.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  7. #7
    Registered User
    Join Date
    Aug 2012
    Posts
    16
    I wish it was that easy - unfortunately as a first year electrical engineer at university we are required to undertake a C programming course - this is an assignment. Seems like quite a difficult one at that.

  8. #8
    Registered User
    Join Date
    Jun 2011
    Posts
    4,513
    Quote Originally Posted by igor View Post
    I wish it was that easy - unfortunately as a first year electrical engineer at university we are required to undertake a C programming course - this is an assignment. Seems like quite a difficult one at that.
    I have an EE degree. It so happens that your "unfortunately/required" was my "sweet, awesome" experience. But it's a vast and varied field, so to each to their own! And I wish you the best of luck.

  9. #9
    TEIAM - problem solved
    Join Date
    Apr 2012
    Location
    Melbourne Australia
    Posts
    1,907
    I have an EE as well I remember thinking, "I wonder why they are teaching us C?" - Answer: You'll need it to program microprocessors (first in assembly language, but then in C). You'll want to be good at programming them, because they will be in most projects (does anyone use the 555 any more?). So my advice is to get good at C and keep practising.

    Have you already go access to the file you need to read? If it's an assignment, I'd imagine that there would be some sort of guidelines regarding the *.bmp file, you might even have access to a practice file.

  10. #10
    Registered User
    Join Date
    Jun 2011
    Posts
    4,513
    I use 555 timers to generate quick and dirty clocks for the low frequency PLDs, but pretty much use crystal oscillators for the microcontrollers as the inaccuracy of RC oscillators is not effective for the precision timing required by the applications I program for - especially at the higher frequencies that most of those devices are optimized for. But my two colleagues are analog guys who deal solely with RF (power amplification, impedance matching, etc). So programming does not come into play for many disciplines of EE, depending again on which aspect of the varied field one happens to get into. But it certainly is true that many circuits are more dependent on digital circuitry (programmable resistors, capacitors, oscillators, etc) than in the past. My apologies for digressing on this thread.

  11. #11
    TEIAM - problem solved
    Join Date
    Apr 2012
    Location
    Melbourne Australia
    Posts
    1,907
    I use 555 timers to generate quick and dirty clocks for the low frequency PLDs
    I stand corrected.


    But my two colleagues are analog guys who deal solely with RF (power amplification, impedance matching, etc). So programming does not come into play for many disciplines of EE
    That is after they graduate :P

    I started to type how much I love analogue electronics, but I stopped: I think that we are starting to get off topic...

  12. #12
    Registered User
    Join Date
    Aug 2012
    Posts
    16
    so back on topic :P as stated in post 5 is the format of a bmp file, specified in the outline - what would be the best way to read the file? I can read the file using the first structure - however am stumped as to how to read it in the format of all 3 structs instead? thanks again.

    I tried reading the file as an array and assigning the member of each array to the appropriate structure and variable, however, only the first few elements seemed to be correct, fileMarker1, fileMarker2 andbfSize. (retrieving B M and 56 respectively - the rest of the array contained 0s)
    Last edited by igor; 08-30-2012 at 04:03 AM.

  13. #13
    Registered User
    Join Date
    Sep 2008
    Location
    Toronto, Canada
    Posts
    1,834
    You shouldn't use 'int' in the structs. The BMP file specification says dword which means 32 bit. It's better to use 'long' because 'int' may have different sizes depending on platform.
    Also you must use #pragma pack(1) or whatever is appropriate for your compiler to ensure that there is no structure element padding.
    After INFOHEADER there is a palette array followed by image data.

  14. #14
    Registered User
    Join Date
    Aug 2012
    Posts
    16
    Quote Originally Posted by nonoob View Post
    You shouldn't use 'int' in the structs. The BMP file specification says dword which means 32 bit. It's better to use 'long' because 'int' may have different sizes depending on platform.
    Also you must use #pragma pack(1) or whatever is appropriate for your compiler to ensure that there is no structure element padding.
    After INFOHEADER there is a palette array followed by image data.
    Thanks for your reply. Regarding using int in the structs - this is the format given in the assignment outline, so i have no choice

    I attempted to use #pragma pack (just for the 1 structure) see code below; however, for some reason bfSize was getting the wrong value. Values were outputted as followed, B > M > 921656 > 0 > 0 > 54 (all right except bfsize, 921656). Any ideas why ?

    Code:
        #include <stdio.h>
    
    #pragma pack(push, 1);
    
    
    typedef struct
    {
    unsigned char fileMarker1; /* 'B' */
    unsigned char fileMarker2; /* 'M' */
    unsigned int bfSize;
    unsigned short unused1;
    unsigned short unused2;
    unsigned int imageDataOffset; /* Offset to the start of image data */
    }header;
    
    #pragma pop;
    int main ( int argc, char *argv[] )
    {
        char filename[256];
        FILE *image;
        header data;
    
                    printf("Enter File Name: \n");        scanf("%s", &filename);
                
            image = fopen(filename, "rb" );
    
    
            fread(&data, sizeof(unsigned char), sizeof(data), image);
            
            
            if(image == NULL)
            {
                printf("The file cannot be opened.\n");
    
    
            }
    
    
            else
            {
                printf("fileMarker1 = %c\n", data.fileMarker1);
    
    
                printf("fileMarker2 = %c\n", data.fileMarker2);
    
    
                printf("bfSize = %d\n", data.bfSize);
    
    
                printf("unused 1 = %d\n", data.unused1);
    
    
                printf("unused 2 = %d\n", data.unused2); 
    
    
                printf("imagedataoffset = %d\n", data.imageDataOffset);
    
    
            }
    return 0;

    think i may have worked something out
    Last edited by igor; 08-30-2012 at 06:53 AM.

  15. #15
    Registered User
    Join Date
    Aug 2005
    Location
    Austria
    Posts
    1,990
    Check your printf formats. "%d" should not be used for unsigned ints.
    Kurt

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Image reading and writing
    By jawad242 in forum C++ Programming
    Replies: 2
    Last Post: 05-23-2011, 10:07 AM
  2. Problem reading tiff image files?
    By compz in forum C++ Programming
    Replies: 9
    Last Post: 10-30-2009, 04:17 AM
  3. Reading an image
    By drrcknlsn in forum C++ Programming
    Replies: 2
    Last Post: 01-27-2008, 10:21 PM
  4. Fat Image reading
    By cfrost in forum C++ Programming
    Replies: 0
    Last Post: 03-05-2005, 06:06 AM
  5. *question* Reading Image Files
    By madsmile in forum C Programming
    Replies: 5
    Last Post: 03-05-2002, 12:57 PM

Tags for this Thread