From 107588ae7f657d1230ac4bb8faf04758b11f53aa Mon Sep 17 00:00:00 2001 From: Anton Lydike Date: Mon, 9 Mar 2020 12:49:59 +0100 Subject: [PATCH] initial commit --- .gitignore | 2 + README.md | 3 ++ images/images.c | 140 ++++++++++++++++++++++++++++++++++++++++++++++++ images/images.h | 24 +++++++++ main.c | 33 ++++++++++++ 5 files changed, 202 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 images/images.c create mode 100644 images/images.h create mode 100644 main.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..386f581 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.out +*.o \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..71a16b0 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# C learning workplace + +here we learn C. \ No newline at end of file diff --git a/images/images.c b/images/images.c new file mode 100644 index 0000000..3b814f0 --- /dev/null +++ b/images/images.c @@ -0,0 +1,140 @@ +#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(width * sizeof(int*)); + for (int j = 0; j < width; j++) { + img->bitmap[i][j] = malloc(3 * 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; px++) { + 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][x][0] = (char) r; + image->bitmap[y][x][1] = (char) g; + image->bitmap[y][x][2] = (char) 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++) { + for (int j = 0; j < image->width; j++) { + free(image->bitmap[i][j]); + } + free(image->bitmap[i]); + } + free(image->bitmap); + + return 1; +} + diff --git a/images/images.h b/images/images.h new file mode 100644 index 0000000..0d82a28 --- /dev/null +++ b/images/images.h @@ -0,0 +1,24 @@ +#ifndef IMAGES_H +#define IMAGES_H + +typedef struct _image { + char*** bitmap; + int width; + int height; +} Image; + +int image_new(int width, int height, Image* image); + +int image_save(Image* image, char* path); + +int image_set_px(Image* image, int x, int y, int r, int g, int b); + +int image_check_coords(Image* image, int x, int y); + +int image_destroy(Image* image); + +int image_byte_size(Image *image); + +#include "images.c" + +#endif \ No newline at end of file diff --git a/main.c b/main.c new file mode 100644 index 0000000..8dc051a --- /dev/null +++ b/main.c @@ -0,0 +1,33 @@ +#include +#include +#include "images/images.h" + +int main(int argc, char* argv[]) { + + Image img; + image_new(255,255, &img); + + int r,g,b; + + for (int i = 0; i < 255; i++) { + for (int j = 0; j < 255; j++) { + double factor = (i*i + j*j) / (100*100); + r = i; + g = 255 -j; + b = i -255; + + + image_set_px(&img, i, j, factor * r, factor * g, factor * b); + + } + } + + printf("Writing file to /home/anton/projects/mona/chaos/test.bmp\n"); + + if (!image_save(&img, "/home/anton/projects/mona/chaos/test.bmp")) { + printf("Error writing file!\n"); + } else { + printf("Wrote file successfully\n"); + } + image_destroy(&img); +} \ No newline at end of file