Thread: BMP image files reading

  1. #16
    Registered User
    Join Date
    Sep 2008
    Location
    Toronto, Canada
    Posts
    1,834
    You should not be doing an fread() before checking whether the file opened.

  2. #17
    Registered User
    Join Date
    May 2012
    Location
    Arizona, USA
    Posts
    948
    Quote Originally Posted by nonoob View Post
    It's better to use 'long' because 'int' may have different sizes depending on platform.
    The same can be said about long too. It could be larger than 32 bits on some platforms. I know of one platform where a long is 36 bits wide!

    It's better to read the data into a char buffer and extract the values from it. This solves all of the problems of data sizes and endianness.

    Edit: Salem already mentioned this technique and provided sample code. You should follow that advice.
    Last edited by christop; 08-30-2012 at 10:50 AM.

  3. #18
    Registered User
    Join Date
    Aug 2012
    Posts
    16
    thanks a lot - and yeah im aware of the few little issues (with fread before open and %d instead of %u for unsigned int - though that was just a quick test to see if i was getting right values and not really necessary for the full program)...after further reading and stuff (thanks salem, and other sources) i now understand the issues with endianness. Could someone further explain the technique of reading in to a char buffer/array ? i attempted it and whilst the B and M values were stored correctly...im guessing (due to my results), that simply doing
    Code:
     unsigned char array[5];                  /* ignore code (incorrect) - should be 14 size etc   */
                                    
     fread(array, 1, sizeof(array), image); 
                       
                data.fileMarker1 = array[0];
                data.fileMarker2 = array[1];
                data.bfSize = array[2];
                data.unused1 = array[3];
                data.unused2 = array[4];
                data.imageDataOffset = array[5];
    (for the fileheader/first structure) is incorrect.

    Salem's example of the code uses bit-shifting - is that necessary if so, why? Sorry if this seem obvious to some.

    EDIT: upon further research, i realised the size of the array should obviously be sizeof(header) (the struct) which is 14...however, im still not 100% sure as to how to assign each member correctly (which is obviously the issue regarding my incorrect results and code). Has to do with the size of each data type in the struct > so for data.imageDataOffset, could i just assign it to the 10th member of the array, or is that the incorrect way of going about it, and bit shifting should be used instead
    Last edited by igor; 09-04-2012 at 01:45 AM.

  4. #19
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    You can't really get away from the bit shifting, when you're reading an array of bytes and you want to assign that to data types which are wider than a byte (say an int).

    Code:
    $ cat foo.c
    #include <stdio.h>
    
    int main ()
    {
        unsigned long a = 0x12345678;
        size_t  i;
        for ( i = 0 ; i < sizeof(a) ; i++ ) {
            unsigned char b = a & 0xff;
            a = a >> 8;
            printf("Byte %d is %02x\n", (int)i, b );
        }
        return 0;
    }
    $ ./a.out 
    Byte 0 is 78
    Byte 1 is 56
    Byte 2 is 34
    Byte 3 is 12
    Now if 0x78 0x56 0x34 0x12 were bytes in some unsigned char array, read from a file, then to reassemble the unsigned long, you would need to do
    0x78 + (0x56<<8)
    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. #20
    Registered User
    Join Date
    Aug 2012
    Posts
    16
    ahh okay, worked it out thanks a lot!! all seems to work fine (from the first 2 structures) on both little and big endien - EXCEPT one member, imagedataoffset is getting different results when printing as an unsigned int (%u, or %d for that matter)...on pc i get the value of 54 (which i believe is the correct value), on linux im getting 1107296310. However when printing as a char, %c, both print 6. Any idea as to why this is occurring ? As stated, all other members work fine for both platforms. (also just checked to ensure, all values of all 14 members of the array are the same on both platforms, with array[10] = 54, and array[11] to array[13] being 0 (the 4 bytes associated with the unsigned int) ).
    Last edited by igor; 09-04-2012 at 03:27 AM.

  6. #21
    Registered User
    Join Date
    May 2012
    Posts
    1,066
    Quote Originally Posted by igor View Post
    EXCEPT one member, imagedataoffset is getting different results when printing as an unsigned int (%u, or %d for that matter)...on pc i get the value of 54 (which i believe is the correct value), on linux im getting 1107296310. However when printing as a char, %c, both print 6. Any idea as to why this is occurring ? As stated, all other members work fine for both platforms. (also just checked to ensure, all values of all 14 members of the array are the same on both platforms, with array[10] = 54, and array[11] to array[13] being 0 (the 4 bytes associated with the unsigned int) ).
    54 in binary is 110110
    1107296310 in binary is 1000010000000000000000000110110

    As you can see the last byte is the same as 54. I guess you have some misalignmet issue

    It would be easier to help you if you show the relevant code (structure definition and how you read the file into the array).

    Bye, Andreas

  7. #22
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Quote Originally Posted by igor View Post
    (also just checked to ensure, all values of all 14 members of the array are the same on both platforms, with array[10] = 54, and array[11] to array[13] being 0 (the 4 bytes associated with the unsigned int) ).
    That seems unlikely... maybe array[13] was 0 when you checked it but it's probably an uninitialized value, or at least it appears to be getting assigned 0x42 = 66 somehow! It's quite possible for uninitialized variables to suddenly look okay when you print them or in a debugger, and quite likely to be zero in visual studio in debug mode (I think it zeros all memory automatically).

    Since it's the last element of the array, perhaps you're reading one less byte from the file than you should be? Try setting imagedataoffset to zero beforehand; this probably won't do anything, which would confirm that something's wrong with array[13]. What is the actual byte in the file? For example:
    Code:
    $ hexdump test.bmp | head -n 1
    0000000 4d42 647a 0000 0000 0000 007a 0000 006c
    In my case it really is zero, but it never hurts to double-check.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  8. #23
    Registered User
    Join Date
    Aug 2012
    Posts
    16
    Quote Originally Posted by AndiPersti View Post
    54 in binary is 110110
    1107296310 in binary is 1000010000000000000000000110110

    As you can see the last byte is the same as 54. I guess you have some misalignmet issue

    It would be easier to help you if you show the relevant code (structure definition and how you read the file into the array).

    Bye, Andreas
    Here is the code;
    Code:
    char filename[20];
    	FILE *image;
    	header data;
    	unsigned char array[13];
    
    
    printf("Enter File Name: \n");
    		scanf("%s", &filename);
    			
    		image = fopen(filename, "rb" );
    
    
                           fread(array, 1, 14, image);
    	
    	
    			data.fileMarker1 = array[0];
    			data.fileMarker2 = array[1];
    			data.bfSize = array[2] + (array[3] << 8) + (array[4] << 16) + (array[5] << 24);
    			data.unused1 = array[6] + (array[7] << 8);
    			data.unused2 = array[8] + (array[9] << 8);
    			data.imageDataOffset = array[10] + (array[11] << 8) + (array[12] << 16) + (array[13] << 24);
    Thats the basis of the code - the struct can be seen on the previous page, named header (or maybe FILEHEADER). As mentioned works fine on pc though strangely produces a different value for imagedataoffset. Thanks again for your assistance.

  9. #24
    Registered User
    Join Date
    May 2012
    Location
    Arizona, USA
    Posts
    948
    Quote Originally Posted by igor View Post
    Code:
    	unsigned char array[13];
                           fread(array, 1, 14, image);
    			data.imageDataOffset = array[10] + (array[11] << 8) + (array[12] << 16) + (array[13] << 24);
    These three lines are a buffer overflow. array[13] does not exist. It is one char past the end of the array.

    fread tries to write to array[13], which is especially bad (not to say that reading from array[13] is good; it's still undefined behavior).

  10. #25
    Registered User
    Join Date
    Aug 2012
    Posts
    16
    [QUOTE=christop;1122134]These three lines are a buffer overflow. array[13] does not exist. It is one char past the end of the array.

    you're a legend! thanks so much for you're help!

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