Confused Newbie

Discussion in 'C Programming' started by ilan.pillemer@gmail.com, Mar 28, 2007.

  1. Guest

    Hi,

    I am not sure if this is the right place to ask my question.
    If not, can some direct me to the right place, please?

    Anyways, here is the problem.
    I have written a little program to write bitmaps.

    But when I write the bitmap headers as understood from the
    specifications I found when googling specifically the offset
    to the bitmap data goes in the wrong place.

    I used od -d to look at the header that I was producing and the header
    of a sample bitmap file. By doing this I saw what needed to be
    changed.

    And I hacked the code it force things right. But it looks ugly.

    I have included the code that should work and the hack.

    Here are the octal dumps, note the value of 54 - ie the offset is in
    the wrong place. And I cannot figure out why....

    Note, I have already reduced the size of the header from 16 bytes to
    the expected 14 bytes by not writing the last two bytes to the file.

    octal dump of broken bitmap
    [ilan@pillemer COS340A]$ od -d gasket.bmp | grep 19778 -C5
    0000000 19778 0 54 36 0 0 54 40
    0000020 0 1024 0 768 0 1 24 0
    0000040 0 0 0 0 0 0 0 0
    0000060 0 0 0 0 254 65024 0 254
    0000100 65024 1 509 64768 1 509 64768 2
    0000120 764 64512 2 764 64512 3 1019 64256

    octal dump of bitmap formed by hack - works.
    [ilan@pillemer COS340A]$ od -d gasket_hack.bmp | grep 19778 -C5
    0000000 19778 0 54 36 0 54 0 40
    0000020 0 1024 0 768 0 1 24 0
    0000040 0 0 0 0 0 0 0 0
    0000060 0 0 0 0 254 65024 0 254
    0000100 65024 1 509 64768 1 509 64768 2
    0000120 764 64512 2 764 64512 3 1019 64256
    [ilan@pillemer COS340A]$

    *Code before Hack*

    typedef struct /**** BMP file header structure
    ****/
    {
    unsigned short bfType; /* Magic number for file */
    unsigned int bfSize; /* Size of file */
    unsigned short bfReserved1; /* Reserved */
    unsigned short bfReserved2; /* ... */
    unsigned int bfOffBits; /* Offset to bitmap data. */

    } BITMAPFILEHEADER;

    typedef struct /**** BMP file info structure
    ****/
    {
    unsigned int biSize; /* Size of info header */
    int biWidth; /* Width of image */
    int biHeight; /* Height of image */
    unsigned short biPlanes; /* Number of color planes */
    unsigned short biBitCount; /* Number of bits per pixel */
    unsigned int biCompression; /* Type of compression to use */
    unsigned int biSizeImage; /* Size of image data */
    int biXPelsPerMeter; /* X pixels per meter */
    int biYPelsPerMeter; /* Y pixels per meter */
    unsigned int biClrUsed; /* Number of colors used */
    unsigned int biClrImportant; /* Number of important colors */

    } BITMAPINFOHEADER;

    <snip>
    bitfile = fopen("gasket.bmp","wb");
    rc = fwrite(&header,sizeof(BITMAPFILEHEADER)-2,1,bitfile);
    rc = fwrite(&info,sizeof(BITMAPINFOHEADER),1,bitfile);

    ====================================================================
    *Hack*
    ====================================================================

    typedef struct /**** BMP file header structure
    ****/
    {
    unsigned short bfType; /* Magic number for file */
    unsigned int bfSize; /* Size of file */
    unsigned short bfReserved1; /* Reserved */
    unsigned short bfReserved2; /* ... */
    unsigned int bfOffBits; /* Offset to bitmap data. Actually
    moved to other header. */

    } BITMAPFILEHEADER;

    typedef struct /**** BMP file info structure
    ****/
    {
    unsigned int bfOffBeats; /* Because of some complication moved
    offset to here. Ugly Hack. */
    unsigned int biSize; /* Size of info header */
    int biWidth; /* Width of image */
    int biHeight; /* Height of image */
    unsigned short biPlanes; /* Number of color planes */
    unsigned short biBitCount; /* Number of bits per pixel */
    unsigned int biCompression; /* Type of compression to use */
    unsigned int biSizeImage; /* Size of image data */
    int biXPelsPerMeter; /* X pixels per meter */
    int biYPelsPerMeter; /* Y pixels per meter */
    unsigned int biClrUsed; /* Number of colors used */
    unsigned int biClrImportant; /* Number of important colors */

    } BITMAPINFOHEADER;

    <snip>
    bitfile = fopen("gasket.bmp","wb");
    rc = fwrite(&header,sizeof(BITMAPFILEHEADER)-6,1,bitfile);
    rc = fwrite(&info,sizeof(BITMAPINFOHEADER),1,bitfile);
     
    , Mar 28, 2007
    #1
    1. Advertising

  2. Chris Dollin Guest

    wrote:


    > But when I write the bitmap headers as understood from the
    > specifications I found when googling specifically the offset
    > to the bitmap data goes in the wrong place.
    >
    > I used od -d to look at the header that I was producing and the header
    > of a sample bitmap file. By doing this I saw what needed to be
    > changed.


    > typedef struct /**** BMP file info structure
    > ****/
    > {
    > unsigned int biSize; /* Size of info header */
    > int biWidth; /* Width of image */
    > int biHeight; /* Height of image */
    > unsigned short biPlanes; /* Number of color planes */
    > unsigned short biBitCount; /* Number of bits per pixel */
    > unsigned int biCompression; /* Type of compression to use */
    > unsigned int biSizeImage; /* Size of image data */
    > int biXPelsPerMeter; /* X pixels per meter */
    > int biYPelsPerMeter; /* Y pixels per meter */
    > unsigned int biClrUsed; /* Number of colors used */
    > unsigned int biClrImportant; /* Number of important colors */
    >
    > } BITMAPINFOHEADER;
    >
    > <snip>
    > bitfile = fopen("gasket.bmp","wb");
    > rc = fwrite(&header,sizeof(BITMAPFILEHEADER)-2,1,bitfile);
    > rc = fwrite(&info,sizeof(BITMAPINFOHEADER),1,bitfile);


    Don't do that. You're expecting the layout of your struct and the
    layout of bytes in the bitmap format to correspond exactly. This
    will happen only by an accident of the implementation: it requires
    (a) that the compiler use no padding and (b) that your machine's
    endianness -- the order that bytes appear in words -- is the same
    as that specified by the bitmap file, as indeed they are not.

    Write the bytes out in the correct order, as specified by the map
    format. (You could assemble the bytes in a buffer and write /that/
    out, but even that assumes that a C char aka byte corresponds to a
    bitmap's byte. One day that might not be true ...)

    It might be something like [I've quietly ignored signedness issues]

    write_short( bitfile, header.bfType );
    write_int( bitfile, header.bfSize );
    write_int( bitfile, header.bfReserved1 );
    write_short( bitfile, header.bfreserved2 );
    write_int( bitfile, header.bfOffBits );
    ...

    /* assuming 4-byte ints written big-endian */
    void write_int( FILE *sink, unsigned int x )
    {
    putc( (x >> 24) & 0xff, sink );
    putc( (x >> 16) & 0xff, sink );
    putc( (x >> 8) & 0xff, sink );
    putc( x & 0xff, sink );
    }

    ...

    It's probably a FAQ but I forgot to look it up.

    --
    Jena user conference, September 2007: http://hpl.hp.com/conferences/juc2007/
    "The path to the web becomes deeper and wider." - October Project

    Hewlett-Packard Limited registered no:
    registered office: Cain Road, Bracknell, Berks RG12 1HN 690597 England
     
    Chris Dollin, Mar 28, 2007
    #2
    1. Advertising

  3. Guest

    On Mar 28, 3:29 pm, Chris Dollin <> wrote:
    > Don't do that. You're expecting the layout of your struct and the
    > layout of bytes in the bitmap format to correspond exactly. This
    > will happen only by an accident of the implementation: it requires
    > (a) that the compiler use no padding and (b) that your machine's
    > endianness -- the order that bytes appear in words -- is the same
    > as that specified by the bitmap file, as indeed they are not.


    So is that why the "54" is in wrong place.. my confusion was caused
    by the war in Lilliput.

    Thanks!

    --ilAn
     
    , Mar 28, 2007
    #3
  4. ilAn Guest

    On Mar 28, 3:29 pm, Chris Dollin <> wrote:
    > wrote:
    > > But when I write the bitmap headers as understood from the
    > > specifications I found when googling specifically the offset
    > > to the bitmap data goes in the wrong place.

    >
    > > I usedod-d to look at the header that I was producing and the header
    > > of a sample bitmap file. By doing this I saw what needed to be
    > > changed.
    > > typedef struct /**** BMP file info structure
    > > ****/
    > > {
    > > unsigned int biSize; /* Size of info header */
    > > int biWidth; /* Width of image */
    > > int biHeight; /* Height of image */
    > > unsigned short biPlanes; /* Number of color planes */
    > > unsigned short biBitCount; /* Number of bits per pixel */
    > > unsigned int biCompression; /* Type of compression to use */
    > > unsigned int biSizeImage; /* Size of image data */
    > > int biXPelsPerMeter; /* X pixels per meter */
    > > int biYPelsPerMeter; /* Y pixels per meter */
    > > unsigned int biClrUsed; /* Number of colors used */
    > > unsigned int biClrImportant; /* Number of important colors */

    >
    > > } BITMAPINFOHEADER;

    >
    > > <snip>
    > > bitfile = fopen("gasket.bmp","wb");
    > > rc = fwrite(&header,sizeof(BITMAPFILEHEADER)-2,1,bitfile);
    > > rc = fwrite(&info,sizeof(BITMAPINFOHEADER),1,bitfile);

    >
    > Don't do that. You're expecting the layout of your struct and the
    > layout of bytes in the bitmap format to correspond exactly. This
    > will happen only by an accident of the implementation: it requires
    > (a) that the compiler use no padding and (b) that your machine's
    > endianness -- the order that bytes appear in words -- is the same
    > as that specified by the bitmap file, as indeed they are not.
    >
    > Write the bytes out in the correct order, as specified by the map
    > format. (You could assemble the bytes in a buffer and write /that/
    > out, but even that assumes that a C char aka byte corresponds to a
    > bitmap's byte. One day that might not be true ...)
    >
    > It might be something like [I've quietly ignored signedness issues]
    >
    > write_short( bitfile, header.bfType );
    > write_int( bitfile, header.bfSize );
    > write_int( bitfile, header.bfReserved1 );
    > write_short( bitfile, header.bfreserved2 );
    > write_int( bitfile, header.bfOffBits );
    > ...
    >
    > /* assuming 4-byte ints written big-endian */
    > void write_int( FILE *sink, unsigned int x )
    > {
    > putc( (x >> 24) & 0xff, sink );
    > putc( (x >> 16) & 0xff, sink );
    > putc( (x >> 8) & 0xff, sink );
    > putc( x & 0xff, sink );
    > }
    >
    > ...
    >
    > It's probably a FAQ but I forgot to look it up.
    >
    > --
    > Jena user conference, September 2007: http://hpl.hp.com/conferences/juc2007/
    > "The path to the web becomes deeper and wider." - October Project
    >
    > Hewlett-Packard Limited registered no:
    > registered office: Cain Road, Bracknell, Berks RG12 1HN 690597 England



    Actually, then endianness in my computer is exactly the same as that
    specificed in the bitmap header file.

    comp.programmer.unix pointed out the problem. The flaw was in the
    false assumption that the padding of the struct was at the end; when
    indeed it was not.

    http://groups.google.co.za/group/co...st&q=bamboozled&rnum=1&hl=en#3c1a8021ddfa3e2f

    Regards,
    Ilan Pillemer
     
    ilAn, Mar 31, 2007
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Dave Smithz
    Replies:
    4
    Views:
    352
    Dave Smithz
    Oct 27, 2004
  2. Wizard

    Very New, Newbie Confused

    Wizard, Jan 3, 2005, in forum: ASP .Net
    Replies:
    1
    Views:
    400
    Daniel Fisher\(lennybacon\)
    Jan 3, 2005
  3. voger
    Replies:
    5
    Views:
    3,778
    voger
    Sep 20, 2005
  4. Raoul Gough
    Replies:
    0
    Views:
    933
    Raoul Gough
    Aug 7, 2003
  5. seemanta dutta
    Replies:
    8
    Views:
    501
    Jon Bell
    Mar 4, 2004
Loading...

Share This Page