Skip to main content
GameDev.net gamedev.net
🔒 Locked

Why do I get wrong fileheader-values reading bitmap ?

Started by poelsgeert Apr 20, 2001 at 9:17 AM 9 replies 500+ views
Original Post
poelsgeert
poelsgeert
hello, I copied Andre Lamothe''s routine (Tricks of the p.346) to read a bitmap but changed the way the file is read a little (used fread/fseek instead of _lread/ _seek ). I get some strange results, even only after reading the file_header. This is my header : typedef struct { WORD bfType; DWORD bfSize; WORD bfReserved1; WORD bfReserved2; DWORD bfOffBits; } BITMAP_FILE_HEADER; typedef struct { BITMAP_FILE_HEADER bitmapfileheader; BITMAP_INFO bitmapinfo; PALETTEENTRY palette[MAX_COLORS_PALETTE]; UCHAR * buffer; } BITMAP_FILE, * BITMAP_FILE_PTR; Here is the part where I read this header : int LoadBitmap(const char* filename, BITMAP_FILE_PTR aBitmap) { FILE * bitmap_fp; if ( (bitmap_fp = fopen(filename, "rb")) != NULL) { fread(&aBitmap->bitmapfileheader, sizeof(BITMAP_FILE_HEADER), 1,bitmap_fp); // check for bitmap if ( aBitmap->bitmapfileheader.bfType == BITMAP_ID ) { The hex view of my bitmap is this : 42 4D 36 B4 04 00 00 00 00 00 36 04 00 00 28 00 ... Using the Visual C++ debugger I get these values : bfType = 19778 correct bfSize = 4 (should be 308278, x04B436) bfReserved1 = 0 correct bfReserved2 = 1078 (should be 0, 1078 should be in OffBits) bfOffBits = 2621440 incorrect What goes wrong ? Geert
Dragonskin
Dragonskin
I think that it''s a problem with your structures. I am willing to bet that if you loaded the variables individually, it would work perfectly. As I''m not at home I can''t tell you the EXACT way to fix this, but I know that there''s a way to pack structures so they come out exactly as you want them. Otherwise the compiler will pad it to make it align with memory better.

--Dragonskin
Anthracks
Anthracks
EDIT: As was just pointed out, this blatantly doesn't answer your question. Sorry about that, skip down to another reply...

Sorry if this comes across as condescending, I have no idea what you know so I'm sorta going for the basics here heh.

I think the data you're reading is actually correct...maybe you misunderstood how big a WORD or DWORD is? From MSDN help:

WORD A 16-bit unsigned integer (2 bytes).
DWORD A 32-bit unsigned integer (4 bytes).

So, your structure is 14 bytes in size (2+4+2+2+4), and you really only need the first 14 bytes from your hex editor.

42 4D 36 B4 04 00 00 00 00 00 36 04 00 00

Now, this is what your structure says:

bfType=0x4D42 (19778, correct)
bfSize=0x0004B436 (308278, correct)
bfReserved1=0x0000, correct
bfReserved2=0x0000, correct
bfOffBits=0x00000436 (1078, correct).

And there you have it, your data is correct .

Did that help you out?

Anthracks

Edited by - Anthracks on April 20, 2001 11:56:24 AM
Dragonskin
Dragonskin
I just looked it up on MSDN...

For VC++, use #pragma pack(N) where N is the number of the alignment. What you could do is temporarily put it down to 1 (around your structures) and then put it back up to the normal value afterwards.

Anthracks was right that the data was correct, but the structure''s alignment is off, so it doesn''t matter. You can''t get the right stuff unless it''s packed or loaded value by value.
Anthracks
Anthracks
Heh yeah, I just realized myself that I didn''t really answer his question...I think I need another elementary school course in critical reading .

I think you guys are right...I thought at first it was something else, because I don''t use any special packing in my bitmap code. But then I dug into the header files, and lo and behold it *is* packed specially heh.

Poelsgeert: My suggestion is to use the headers that come with windows; they are designed to work this way. They are exactly the same as the one you made...just do this (after you #include "windows.h"):

  
BITMAPFILEHEADER fileHeader;
BITMAPINFOHEADER infoHeader;


and you''re golden. These files are defined with the #pragma pack(1) option, so they pack correctly. Do yourself a favor, just use the standard windows header. That''s actually what LaMothe''s book says, he just isn''t clear on the fact that the structures he prints in the book ARE the ones windows comes with.

Anthracks
poelsgeert
poelsgeert
Thanks for the various responses !

I''m glad I didn''t use the standard Windows header since I now know this kind of thing can happen :-)

What solved the problem was using
#pragma pack(push, 1) before my structs and
#pragma pack(pop, 1) right after them.

Great, this works but can somebody explain me why ?
I suppose I urgently should look into x86 adressing.
With only (D)WORDS, this struct seemed aligned fine.
What''s a possible way this struct can be laid out in memory with and without this pragma directive when this program runs ?
If somebody would be so kind to briefly show .. .

>The best way is just to always extract the values manually
Because of this potential alignment problems ?
Do the others agree on this ?
zechis
zechis
Packing synopsis:

Each byte is represented by a ''-'', therefore:
|----| = DWORD alignment

the first two elements of your structure cannot be next to each other because the first element is a WORD.

|----|----|
|WWDD|DD..| = NO GOOD!

DWORD (packing 4) alignment says that no element can straddle a DWORD boundary, so it fills in the rest with garbage until the next boundary, then starts the next element.

|----|----|
|WWxx|DDDD|

So, when you read it in without the packing:
42 4D 36 B4 04 00 00 00 00 00 ...
424D got stored in the WORD bfType, 36B4 got stored in the packbytes (''xx'' in the above picture), and 04000000 got stored in the DWORD bfSize, that''s why you got the wrong value of 4 for the bfSize.

Also, VC default packing is 4. Your second #pragma(pop,1) should be #pragma(pop) or #pragma(pop,4)
(pop,1) doesn''t do anything because it was already set to 1 by the first (push,1).

BTW, it is easier to just use the BITMAPFILEHEADER structure in the windows header. Why reinvent the wheel?
flame_warrior
flame_warrior
Change the code generation from 8 bytes to 1 - 2 bytes, use it.

I had the same problem, but changing the code generation from 8 to 1 - 2 bytes corrected the flaw.
Hello from my world

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.