0

I'm trying to read the header of BMP files in c manually. I've used some images to test it out but find that the biSize from the BITMAPINFOHEADER of the images are exceedingly huge.

Firstly, I am unfortunately not on a windows machine, therefore I have to define the data types (such as WORD, DWORD, LONG and BYTE) according to the MS-DTYP documents. Maybe this could lead to some problems.

Secondly, I think I am not fully aware of how the numbers are stored and formatted when being output in c. Hence, the result might be right but it's just me who can not understand it.

Lastly, I have discovered that the size of struct BITMAPFILEHEADER is not 14 bytes as the sum of the sizes of the members in the struct. Therefore, is it possible that the fread() reads more bytes to the struct than it should have?

Code

typedef unsigned long DWORD;
typedef long LONG;
typedef unsigned short WORD;
typedef unsigned char BYTE;

typedef struct tagBITMAPFILEHEADER {
  WORD  bfType;
  DWORD bfSize;
  WORD  bfReserved1;
  WORD  bfReserved2;
  DWORD bfOffBits;  // bit from the beginning of this struct to bitmap
} BITMAPFILEHEADER, *LPBITMAPFILEHEADER, *PBITMAPFILEHEADER;

typedef struct tagBITMAPINFOHEADER {
    DWORD biSize;
    LONG  biWidth;      // width of image in pixels
    LONG  biHeight;     // height of image in pixels
    WORD  biPlanes;
    WORD  biBitCount;   // size of each pixel in bits
    DWORD biCompression;
    DWORD biSizeImage;
    LONG  biXPelsPerMeter;
    LONG  biYPelsPerMeter;
    DWORD biClrUsed;
    DWORD biClrImportant;
} BITMAPINFOHEADER, *LPBITMAPINFOHEADER, *PBITMAPINFOHEADER;

bool
ReadBmp(char *path){
/*
parameter:
    char *path: the path (string) to the target bmp

return:
    True: if success
    False: if failed
*/

    // get the pointer of the bmp file
    FILE * f_ptr;
    if((f_ptr = fopen(path, "rb"))==NULL){
        perror("ReadBmp failed when reading bmp: ");
        return false;
    }

    // load file header to fhead
    BITMAPFILEHEADER fhead; // file header
    fread(&fhead, sizeof(BITMAPFILEHEADER), 1, f_ptr);

    // load the DIB into dib
    BITMAPINFOHEADER dib;
    fread(&dib, sizeof(BITMAPINFOHEADER), 1, f_ptr);

    printf("size: %lu\n", dib.biSize);
}

int
main(void){
    ReadBmp("../imgs/master_yoda.bmp");

    return 0;
}

Result

size: 1063975552894894080

While the actual size of master_yoda.bmp is 2.2MB. I've also check the bfType from BITMAPFILEHEADER and it works fine with a return of 19778 == 0x4D42, which is the identifier for bmp files.

Navxihziq
  • 43
  • 5
  • 2
    Look at the bytes that make up your `biWidth` member. Is it `ec 40 00 00` or `00 00 40 ec`? The former would be little-endian for 16620, which is far more reasonable – Botje Dec 01 '21 at 15:27
  • @Botje I'm terribly sorry that I don't have a proper tool to look into the content of an image file right now so I can't verify your suggestion. However, the picture itself is in the shape of `1024*700` which is unlikely to have a `biWidth` value of 16620 – Navxihziq Dec 01 '21 at 15:39
  • You might want to base your types on the ones from `stdint.h` (e.g. `uint32_t`), since I think there's a decent chance your `long` is a 64 bit integer, and `DWORD` is meant to be a 32 bit integer. – Hasturkun Dec 01 '21 at 15:46
  • @Hasturkun Yes the size of `LONG` should be 32 bit. I had checked the document again and realized that there were errors in the first few `typedef`s. However, the value of `biSize` remains the same after I modified the definition. – Navxihziq Dec 01 '21 at 15:55
  • There might be some issue with padding as well. You could print the complete headers byte wise as hex values and compare with expected values. Also compare the sizes of your types with expected values. If that does not match, you cannot read the headers all in one go but have to read each field one after the other. – Gerhardh Dec 01 '21 at 16:28
  • Can we look at master_yoda.bmp? – n. m. could be an AI Dec 01 '21 at 16:29
  • https://stackoverflow.com/a/8933773/17034 – Hans Passant Dec 01 '21 at 16:29
  • @HansPassant Indeed, I just found the exact same post. It really solves my problem! Thanks! – Navxihziq Dec 01 '21 at 16:39

0 Answers0