#include #include #include "images.h" // write an int to a byte array void bmp__write_int(unsigned char* bytes, int num) { for (int i = 0; i < 4; i++) { bytes[i] = num >> (i * 8); } } void bmp__write_16bit(unsigned char* bytes, int num) { for (int i = 0; i < 2; i++) { bytes[i] = num >> (i * 8); } } int bmp__align_to_four_bytes(int row_length) { int os =row_length % 4; return os == 0 ?row_length : row_length + (4 - os); } int bmp__image_byte_size(Image image) { // calculate size: // bitmap file header = 14 // BITMAPCOREHEADER = 12 bytes int size = 14 + 12; // width must be padded to align to 4 bytes int row_bytes = bmp__align_to_four_bytes(image.width * 3); // 3 bytes per pixel // add row_bytes * height to total size size += row_bytes * image.height; return size; } // header format: // BMP header (14 bytes) // 0x42 0x4D "BM" // 0xAA 0xBB 0xCC 0xDD bmp file size (int) // 0x00 0x00 0x00 0x00 nulls // 0x1A 0x00 0x00 0x00 pixel array offset (int) (= 14 + 12); // DIB Header (BITMAPCOREHEADER) (12 bytes) // 0x0C 0x00 0x00 0x00 header size (int) (= 12) // 0xAA 0xBB width (unsigned 16 bit int) // 0xCC 0xDD height (unsigned 16 bit int) // 0x01 0x00 number of color planes (must be 1) // 0x18 0x00 number of bits per pixel (3 * 8 = 24) // char* bytes; // bytes + 2 => zeigt auf offset 2 (ist char*) // bytes[2] => wert an offset 2 (ist char) int image_save_bmp(Image image, const char* path) { int size = bmp__image_byte_size(image); unsigned char* bytes = calloc(sizeof(char), size); // magic bytes, signature "BM" // bmp header: bytes[0] = 'B'; bytes[1] = 'M'; // write size to header bmp__write_int(bytes + 2, size); // the next 4 byte are zeros // pixel array offset bmp__write_int(bytes + 10, 14 + 12); // DIB header: bmp__write_int(bytes + 14, 12); // header size bmp__write_16bit(bytes + 18, image.width); // width bmp__write_16bit(bytes + 20, image.height); // height bmp__write_16bit(bytes + 22, 1); // color planes bmp__write_16bit(bytes + 24, 3 * 8); // bits per pixel int byte_offset = 26; int byte_pos = 0; int line; for (line = 0; line < image.height; line++) { byte_pos = 0; for (int px = 0; px < image.width * 3; px += 3) { bytes[byte_offset + byte_pos++] = image.bitmap[line][px + 2]; bytes[byte_offset + byte_pos++] = image.bitmap[line][px + 1]; bytes[byte_offset + byte_pos++] = image.bitmap[line][px + 0]; } byte_offset += bmp__align_to_four_bytes(byte_pos); } printf("generated %i bytes out of %i calculated ones\n", byte_offset, size); FILE *fp = fopen(path, "w"); int written = fwrite(bytes, sizeof(char), size, fp); printf("wrote %i bytes...\n", written); fclose(fp); free(bytes); return 1; }