C++ no worky!

edited September 2007 in Tech
As the title suggests, I've run into trouble with C++; moreover, my compiler, i686-apple-darwin8-gcc-4.0.1 (which I invoke with a modest gcc).

My program attempts to load a Windows bitmap, created with gimp.app running under X11 (I'm on a Mac running Tiger) which can be opened just fine in Preview.

It first opens the file with a call to fopen. All is well.

However, when I make two successive calls to fread- one to extract a BITMAPFILEHEADER and another to extract a BITMAPINFOHEADER- I run into problems.

Here's the typical output showing what BITMAPINFOHEADER and BITMAPFILEHEADER contain:

BITMAPFILEHEADER
bfType 19778
bfSize 0
bfReserved1 0
bfReserved2 54
bfOffBits 2621440
BITMAPINFOHEADER
biSize 4194304
biWidth 4194304
biHeight 65536
biPlanes 24
biBitCount 0
biCompression 805306368
biSizeImage 185794560
biXPelsPerMeter 185794560
biYPelsPerMeter 0
biClrUsed 0
biClrImportant 1111687168


For one, biSize and biWidth are waaaay off- the image is 64 pixels by 64 pixels (OpenGL compliant) and biBitCount is definitely not 0, among other things.

Another test:

I purposely set the color of the test image to 65, 66, and 67 so that for each pixel I'd see CBA (A = 65, B = 66, etc.) in a text editor and opened the image with vim. Replacing each CBA with CBA, vim told me that there was 4096 substitutions, exactly how many there should have been (width*height, or 64^2).

I added code to print the data in the image and saved the output to a file. I opened the output with vim and did the same as with the image 4095 substitutions and but one straggling 'A' at the beginning of the file.

Two bytes were missing and BITMAPINFOHEADER shows up as 16 bytes (two more than it should be) long with a call to sizeof().

But why? Here's the structures:


struct BITMAPINFOHEADER {
DWORD biSize ;
LONG biWidth ;
LONG biHeight ;
WORD biPlanes ;
WORD biBitCount ;
DWORD biCompression ;
DWORD biSizeImage;
LONG biXPelsPerMeter ;
LONG biYPelsPerMeter ;
DWORD biClrUsed ;
DWORD biClrImportant ;

};

struct BITMAPFILEHEADER {
WORD bfType ;
DWORD bfSize ;
WORD bfReserved1 ;
WORD bfReserved2 ;
DWORD bfOffBits ;

};
WORD shows up as two bytes, DWORD as four, and LONG as four.

They're defined as follows, straight from MSDN's site (as with the bitmap structures). I even checked them against Wine's include files:
typedef unsigned long DWORD ; // WinDef.h 32 bit unsigned integer
typedef unsigned short WORD ; // WinDef.h - 16 bit unsigned integer
typedef long LONG ; // WinNT.h - 32 bit signed integer

Anybody got any idea as to why this doesn't work?

EDIT: I compiled with this command:

g++ main.cpp -framework OpenGL -framework GLUT && ./a.out

Comments

  • edited September 2007
    Believe it or not, gcc is to blame- here's, and I quote, proof:
    "...gcc (and many other compilers) align variables on double word boundaries by default. In 32-bit protected mode, the CPU reads memory faster if the data starts at a double word boundary." -Paul A. Carter's PC Assembly Language.

    Hopefully I won't get sued for that.