0

I'm trying to read in a bitmap starting with its header, but fread is skipping characters for me.

I'm using this typedef in my header:

#include <windows.h>  // Used for other
#include <cstdio>
typedef struct tagBITMAPHEADER{
    WORD    wFileType;      
    DWORD   dwFileSize;     
    WORD    dwReserved;     
    WORD    dwReserved2;        
    DWORD   dwBmpDataOffset;
    DWORD   dwBmpHeaderSize;
    DWORD   dwWidth;    
    DWORD   dwHeight;   
    WORD    wPlanes;    
    WORD    wBitsPerPixel;  
    DWORD   dwCompression;  
    DWORD   dwBitmapDataSz; 
    DWORD   dwHRes;     
    DWORD   dwVRes;     
    DWORD   dwColors;   
    DWORD   dwImpColors;    
} BITMAPHEADER, *PBITMAPHEADER;

And in my code, I just use a simple fopen and fread with binary.

#include "ImageLoader.h"
BITMAPHEADER pbhFileInfo;
FILE *fBitmap = fopen(FileName,"rb"); //Open file in read / binary  
if (fBitmap) //File is now open
{   fread(&pbhFileInfo,sizeof(BITMAPFILEHEADER),1,fBitmap);
    fclose(fBitmap);
}

Although my bitmap starts with '424DF25A0D' (hex), the first two variables read in seem to skip the 'F25A'

wFileType = 0x4d42 dwFileSize = 0x0000000d

Any idea what might be up?

Thanks in advance.

rpgFANATIC
  • 190
  • 3
  • 9
  • So you've stumbled across struct padding. You should also read about endianness. If you really want your code to be independent of data sizes, struct padding, and work on all types of endianness, you should manually decode the information and put it in your header struct. This is obviously more work, but is more reliable as well. – Alok Singhal Jan 11 '10 at 03:18

3 Answers3

1

Your struct is being aligned by the compiler.

You seem to be using Visual C++. Add this line before your struct definition:

#pragma pack(push 1)

And this line after the definition

#pragma pack(pop)

To learn more, see Why isn’t sizeof for a struct equal to the sum of sizeof of each member?

Community
  • 1
  • 1
Drew Dormann
  • 59,987
  • 13
  • 123
  • 180
1

In my opinion it is highly unwise to be using a struct in this way. Yes, you can get what you want in this case with a compiler specific pragma. I would consider that an acceptable solution if you were writing a Windows device driver or something else that was already very specific to a particular platform.

But this is loading a file in a standard format. It's code that could run in any environment.

Personally, I would write code that lifted the data out of a character array and plopped it into the structure by hand instead of relying on the structure to be layed out in just the right way by the compiler such that fread will magically put all the little bits of data in the right places.

Omnifarious
  • 54,333
  • 19
  • 131
  • 194
  • Since this is a Windows-specific format with a Windows-specific header file providing the definition, the code is likely to be running in a Windows environment. You still make a good point. – Mark Ransom Jan 11 '10 at 03:56
  • Yeah, not saying I'm perfect. Obviously, I'm still getting over some 'noob-ish' errors. I just couldn't understand for a while why a different structure would work. A lot of examples broke this one structure up into two, and then my cpp file worked just fine. – rpgFANATIC Jan 11 '10 at 13:50
  • Yeah, I've decided to follow your advice. Thanks everyone for helping! – rpgFANATIC Jan 16 '10 at 23:10
0

Are you opening the file in binary mode? If not, then this is your problem as it will convert the '0D' in 424DF25A0D to some other data as it interprets it as a carriage return/line feed character, instead of just raw binary data.

Grant Peters
  • 7,691
  • 3
  • 45
  • 57