#include #include #include "images.h" // write an int to a byte array void write_int(char* bytes, int num) { for (int i = 0; i < 4; i++) { bytes[i] = num >> (i * 8); } } void write_byte(char* bytes, int num) { bytes[0] = (char) num; } void write_16bit(char* bytes, int num) { for (int i = 0; i < 2; i++) { bytes[i] = num >> (i * 8); } } int align_to_four_bytes(int size) { int os = size % 4; return os == 0 ? size : size + (4 - os); } int image_new(int width, int height, Image* img) { //Image* img = malloc(sizeof(Image)); if (img == NULL) return 0; img->height = height; img->width = width; // initialize bitmap... img->bitmap = malloc(height * sizeof(int*)); for (int i = 0; i < height; i++) { img->bitmap[i] = malloc(3 * width * sizeof(int)); } //*image = *img; return 1; } int 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 width_bytes = align_to_four_bytes(image->width * 3); // 3 bytes per pixel // add width_bytes * height to total size size += width_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) int image_save(Image* image, char* path) { int size = image_byte_size(image); char* bytes = calloc(sizeof(char), size); // magic bytes, signature "BM" bytes[0] = 0x42; bytes[1] = 0x4d; // write size to header write_int(bytes + 2, size); // the next 4 byte are zeros // piyel array offset write_int(bytes + 10, 14 + 12); write_int(bytes + 14, 12); write_16bit(bytes + 18, image->width); // width write_16bit(bytes + 20, image->height); // height write_16bit(bytes + 22, 1); // color planes 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 += 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; } int image_set_px(Image* image, int x, int y, int r, int g, int b) { if (!image_check_coords(image, x, y)) return 0; image->bitmap[y][(3 * x) + 0] = (char) r; image->bitmap[y][(3 * x) + 1] = (char) g; image->bitmap[y][(3 * x) + 2] = (char) b; return 1; } int image_set_px_c(Image* image, int x, int y, Color* color) { if (!image_check_coords(image, x, y)) return 0; image->bitmap[y][(3 * x) + 0] = (char) color->r; image->bitmap[y][(3 * x) + 1] = (char) color->g; image->bitmap[y][(3 * x) + 2] = (char) color->b; return 1; } int image_check_coords(Image* image, int x, int y) { return x >= 0 && x < image->width && y >= 0 && y < image->height; } int image_destroy(Image* image) { for (int i = 0; i < image->height; i++) { free(image->bitmap[i]); } free(image->bitmap); return 1; } ///////// Colors Color* color_new(int r, int g, int b) { Color* c = malloc(sizeof(Color)); c->r = r; c->g = g; c->b = b; return c; } int image_draw_rect(Image* image, int x1, int y1, int x2, int y2, Color* color) { int retval = 1; int y; for (; x1 < x2; x1++) { for (y = y1; y < y2; y++) { if (!image_set_px_c(image, x1, y, color)) retval = 0; } } return retval; }