I want to create a simple BMP and save it. Because I don't want to complicate things I decided to follow the example from Example 1 and just change the required things, like width and stuffs like that.
I save the BMP_header
in the following struct:
typedef struct{
unsigned short file_type; // hex for "BM"
unsigned int file_size;
unsigned int empty_space; // empty space always 0x0
unsigned int offset; // always 0x36000000
}BMP_header;
Also I have created a function that initialise one struct:
BMP_header* BMP_header_init(unsigned int bmp_data){
BMP_header* coppy = (BMP_header*)malloc(sizeof(BMP_header));
coppy->file_type = 0x4d42;
coppy->file_size = (54 + bmp_data) << 24;
coppy->empty_space = 0;
coppy->offset = 0x36000000;
return coppy;
}
To write the header to a file, I have tried the traditional method
fwrite(header, sizeof(*header), 1, f);
header being the BMP_header_init
result. The problem is that my expected output doesn't match what I would expected, simply adding 0s for no reason.
I have tried to write every field of the field, thinking that the padding from the unsigned short field would be the cause.
The expected output should be, without the space:
42 4D 46 00 00 00 00 00 00 00 36 00 00 00
that matches the Example 1 from wikipedia, but for some reasons I get an extra 3 pair of 0s (I now they are in hex):
42 4D *00 00 00* 46 00 00 00 00 00 00 00 36 00 00 00
The only thing I do in main is to build a struct and then write it to the file:
FILE* f = fopen("img.bmp", "wb");
BMP_header* header = BMP_header_init(16); // to match the example
fwrite(header, sizeof(*header), 1, f);
With bmp_data
equal to 16, your expression (54 + bmp_data) << 24
creates the value 70 << 24
= 1,174,405,120 = 4600000016. As seen from the fact that the short
containing the value 4D4216 is written to the file with the 4216 byte first and then the 4D16 byte, your C implementation stores the least significant byte first. So 4600000016 produces bytes 0016, 0016, 0016, and 4616 in the file, in that order.
There is no need for the << 24
. Remove it. Also change coppy->offset = 0x36000000;
to coppy->offset = 0x36;
.
Note that this code will not be portable, as other C implementations may store the bytes of objects in different orders.
Additionally, I would have expected a typical C implementation to insert two bytes of padding after the unsigned short file_type
and before the unsigned int file_size
in the structure, to keep the unsigned int
aligned to a multiple of four bytes. It is odd that does not appear between the two members in the file.