#include #include #include #include "images.h" // write an int to a byte array void bmp__write_int(FILE *fp, int num) { for (int i = 0; i < 4; i++) { putc(num >> (i * 8), fp); } } void bmp__write_16bit(FILE *fp, int num) { for (int i = 0; i < 2; i++) { putc(num >> (i * 8), fp); } } unsigned long int bmp__align_to_four_bytes(unsigned long int row_length) { unsigned long int os =row_length % 4; return os == 0 ?row_length : row_length + (4 - os); } unsigned long int bmp__image_byte_size(Image image) { // calculate size: // bitmap file header = 14 // BITMAPCOREHEADER = 12 bytes unsigned long int size = 14 + 12; // width must be padded to align to 4 bytes unsigned long 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) { unsigned long int size = bmp__image_byte_size(image); if ((unsigned long int) size > (unsigned long int) UINT_MAX) { printf("bitmap is too big!\n"); return 0; } else { printf("predicted size is %lu out of %u possible", size, UINT_MAX); } FILE *fp = fopen(path, "w"); //unsigned char* bytes = calloc(sizeof(char), size); // magic bytes, signature "BM" // bmp header: fputs("BM", fp); // offset 0 // write size to header bmp__write_int(fp, size); // offset 2 bmp__write_int(fp, 0); // offset 6 - the next 4 byte are zeros // pixel array offset bmp__write_int(fp, 14 + 12); // offset 10 // DIB header: bmp__write_int(fp, 12); // header size bmp__write_16bit(fp, image.width); // width bmp__write_16bit(fp, image.height); // height bmp__write_16bit(fp, 1); // color planes bmp__write_16bit(fp, 3 * 8); // bits per pixel int line, px; for (line = 0; line < image.height; line++) { for (px = 0; px < image.width * 3; px += 3) { putc(image.bitmap[line][px + 2], fp); putc(image.bitmap[line][px + 1], fp); putc(image.bitmap[line][px + 0], fp); } int mod = px % 4; if (mod != 0) { for (int i = 0; i < 4-mod; i++) { putc(0, fp); } } } printf("wrote %li bytes...\n", size); fclose(fp); return 1; }