You don't fread()
into the entire struct at once. Instead, you fread()
into its fields separately, like this:
if (fread(&header->magic[0], 2, 1, fp) != 1) {
// error
}
if (fread(&header->filesz, 4, 1, fp) != 1) {
// error
}
Question
Here is my code. I would like to know how to "properly" read the BMP file and then read the header values without forcing the struct to be packed.
typedef struct __attribute__((packed)){
uint8_t magic[2]; /* the magic number used to identify the BMP file:
0x42 0x4D (Hex code points for B and M).
The following entries are possible:
BM - Windows 3.1x, 95, NT, ... etc
BA - OS/2 Bitmap Array
CI - OS/2 Color Icon
CP - OS/2 Color Pointer
IC - OS/2 Icon
PT - OS/2 Pointer. */
uint32_t filesz; /* the size of the BMP file in bytes */
uint16_t creator1; /* reserved. */
uint16_t creator2; /* reserved. */
uint32_t offset; /* the offset, i.e. starting address,
of the byte where the bitmap data can be found. */
} bmp_header_t;
fp = fopen("input.bmp", "r");
bmp_header_p = malloc(sizeof(bmp_header_t));
fread(bmp_header_p, sizeof(char), 14, fp);
printf("magic number = %c%c\n", bmp_header_p->magic[0], bmp_header_p->magic[1]);
printf("file size = %" PRIu32 "\n", bmp_header_p->filesz);
Solution
You don't fread()
into the entire struct at once. Instead, you fread()
into its fields separately, like this:
if (fread(&header->magic[0], 2, 1, fp) != 1) {
// error
}
if (fread(&header->filesz, 4, 1, fp) != 1) {
// error
}
OTHER TIPS
If you don't want to pack the structure, you'll have to read each field and set it appropriately:
fread(bmp_header_p->magic, sizeof bmp_header_p->magic, 1, fp);
fread(&bmp_header_p->filesz, sizeof bmp_header_p->filesz, 1, fp);
fread(&bmp_header_p->creator1, sizeof bmp_header_p->creator1, 1, fp);
... and so on. You may want to check and fix endianness if necessary too, since portability seems to be a concern for you. Don't forget to add some error checking!