diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..4b30aeb Binary files /dev/null and b/.DS_Store differ diff --git a/CMakeLists.txt b/CMakeLists.txt index 225404f..074f498 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,5 +4,10 @@ set(CMAKE_C_STANDARD_REQUIRED ON) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) include_directories(include) project(ppm_image_processor LANGUAGES C) +find_package(JPEG REQUIRED) add_executable(ppm_image_processor src/main.c) + +target_include_directories(ppm_image_processor PRIVATE ${JPEG_INCLUDE_DIRS}) + +target_link_libraries(ppm_image_processor PRIVATE ${JPEG_LIBRARIES}) diff --git a/src/main.c b/src/main.c index 80e80ce..fe4466d 100644 --- a/src/main.c +++ b/src/main.c @@ -1,15 +1,19 @@ #include #include +#include #include +typedef struct +{ + int width, height, len; + char* name; + char magic_number[3]; +} Image; + unsigned int encoder(unsigned char r, unsigned char g, unsigned char b) { - unsigned int color = 0; - color |= b << 0; - color |= g << 8; - color |= r << 16; - return color; + return (b << 0) | (g << 8) | (r << 16); } unsigned char @@ -22,16 +26,6 @@ decoder(unsigned int clr, int byte) return 0; } -// unsigned int -// decoder_int(unsigned int clr, int byte) -// { -// if (byte == 1) return (clr & 0x000000FF) >> 0; -// else if (byte == 2) return (clr & 0x0000FF00) >> 8; -// else if (byte == 3) return (clr & 0x00FF0000) >> 16; -// else if (byte == 4) return (clr & 0xFF000000) >> 24; -// return 0; -// } - unsigned int set_alpha(unsigned int clr, unsigned char alpha_value) { @@ -41,9 +35,7 @@ set_alpha(unsigned int clr, unsigned char alpha_value) unsigned int invert_rgb(unsigned int clr) { - unsigned char alpha = (clr & 0xFF000000) >> 24; - - return ((~clr) & 0x00FFFFFF) | alpha << 24; + return ((~clr) & 0x00FFFFFF) | (clr & 0xFF000000); } unsigned int @@ -56,14 +48,10 @@ swap_rb(unsigned int clr) unsigned int to_grayscale(unsigned int clr) { - unsigned char alpha = decoder(clr, 4); - unsigned char red = decoder(clr, 3); - unsigned char green = decoder(clr, 2); - unsigned char blue = decoder(clr, 1); - - int average = (red + green + blue) / 3; + int average = + (decoder(clr, 3) + decoder(clr, 2) + decoder(clr, 1)) * .33333; unsigned int mask = encoder(average, average, average); - mask = set_alpha(mask, alpha); + mask = set_alpha(mask, decoder(clr, 4)); return mask; } @@ -72,8 +60,7 @@ unsigned int apply_threshold(unsigned int clr, unsigned char limit) { unsigned int mask = 0; - unsigned char average = decoder(to_grayscale(clr), 1); - if (average < limit) mask = encoder(0, 0, 0); + if (decoder(to_grayscale(clr), 1) < limit) mask = encoder(0, 0, 0); else mask = encoder(255, 255, 255); mask = set_alpha(mask, decoder(clr, 4)); return mask; @@ -116,54 +103,74 @@ apply_opacity(unsigned clr_a, unsigned int clr_b, float ratio) } unsigned int* -ppm_encode(char* file, int* w, int* h, int* max_val, char* magic_number) +ppm_encode(char* file, Image* img) { unsigned char r, g, b; + int max_val; FILE* fptr; fptr = fopen(file, "r"); if (!fptr) return NULL; - fscanf(fptr, "%s", magic_number); - fscanf(fptr, "%d %d", w, h); - fscanf(fptr, "%d", max_val); - unsigned int* buf = malloc((*w) * (*h) * sizeof(unsigned int)); + fscanf(fptr, "%s", img->magic_number); + fscanf(fptr, "%d %d", &img->width, &img->height); + img->len = img->width * img->height; + fscanf(fptr, "%d", &max_val); + fgetc(fptr); + unsigned int* buf = malloc(img->len * sizeof(unsigned int)); if (!buf) return NULL; - - for (int i = 0; i < (*w * *h); i++) + if (img->magic_number[1] == '3') { - fscanf(fptr, "%hhu %hhu %hhu", &r, &g, &b); - unsigned int packed = encoder(r, g, b); - buf[i] = set_alpha(packed, 255); + for (int i = 0; i < img->len; i++) + { + fscanf(fptr, "%hhu %hhu %hhu", &r, &g, &b); + unsigned int packed = encoder(r, g, b); + buf[i] = set_alpha(packed, 255); + } } + else if (img->magic_number[1] == '6') + { + for (int i = 0; i < img->len; i++) + { + fread(&r, sizeof(unsigned char), 1, fptr); + fread(&g, sizeof(unsigned char), 1, fptr); + fread(&b, sizeof(unsigned char), 1, fptr); + unsigned int packed = encoder(r, g, b); + buf[i] = set_alpha(packed, 255); + } + } + fclose(fptr); return buf; } void -ppm_apply_brightness(unsigned int* buf, int buf_size, float factor) +ppm_apply_brightness(unsigned int* buf, Image img, float factor) { - for (int i = 0; i < buf_size; i++) + for (int i = 0; i < img.len; i++) { buf[i] = adjust_brightness(buf[i], factor); } } void -ppm_decode(unsigned int* buf, int buf_size, char* name, int* w, int* h) +ppm_decode(unsigned int* buf, Image img) { unsigned char red, green, blue; - FILE* fptr = fopen(name, "w"); + FILE* fptr; + + if (img.magic_number[1] == '3') fptr = fopen(img.name, "w"); + if (img.magic_number[1] == '6') fptr = fopen(img.name, "wb"); if (!fptr) return; - fprintf(fptr, "P3\n%d %d\n255\n", *w, *h); - for (int i = 0; i < buf_size; i++) + + fprintf(fptr, "%s\n%d %d\n255\n", img.magic_number, img.width, + img.height); + for (int i = 0; i < img.len; i++) { red = decoder(buf[i], 3); green = decoder(buf[i], 2); blue = decoder(buf[i], 1); - fprintf(fptr, "%d %d %d ", red, green, blue); - if ((i + 1) % *w == 0) - { - fprintf(fptr, "\n"); - } + fwrite(&red, 1, 1, fptr); + fwrite(&green, 1, 1, fptr); + fwrite(&blue, 1, 1, fptr); } fclose(fptr); } @@ -206,15 +213,16 @@ chromatic_circular_shift(unsigned int clr, int n) } unsigned int* -horizontal_flip(unsigned int* buf, int size, int w, int h) +horizontal_flip(unsigned int* buf, Image img) { - unsigned int* flip = malloc((w * h) * sizeof(unsigned int)); + unsigned int* flip = malloc(img.len * sizeof(unsigned int)); + if (!flip) return NULL; int idx = 0; - for (int i = 0; i < w; i++) + for (int i = 0; i < img.height; i++) { - for (int k = h - 1; k >= 0; k--) + for (int k = img.width - 1; k >= 0; k--) { - flip[idx] = buf[i * w + k]; + flip[idx] = buf[i * img.width + k]; idx++; } } @@ -224,16 +232,17 @@ horizontal_flip(unsigned int* buf, int size, int w, int h) } unsigned int* -vertical_flip(unsigned int* buf, int size, int w, int h) +vertical_flip(unsigned int* buf, Image img) { - unsigned int* flip = malloc((w * h) * sizeof(unsigned int)); + unsigned int* flip = malloc(img.len * sizeof(unsigned int)); + if (!flip) return NULL; int idx = 0; - for (int i = h - 1; i >= 0; i--) + for (int i = img.height - 1; i >= 0; i--) { - for (int k = 0; k < w; k++) + for (int k = 0; k < img.width; k++) { - flip[idx] = buf[i * w + k]; + flip[idx] = buf[i * img.width + k]; idx++; } } @@ -242,6 +251,62 @@ vertical_flip(unsigned int* buf, int size, int w, int h) return flip; } +unsigned int +constrast_adjustment(unsigned int clr, float factor) +{ + unsigned int mask = 0; + int r = factor * (decoder(clr, 3) - 128) + 128; + int g = factor * (decoder(clr, 2) - 128) + 128; + int b = factor * (decoder(clr, 1) - 128) + 128; + if (r > 255) r = 255; + if (g > 255) g = 255; + if (b > 255) b = 255; + if (r < 0) r = 0; + if (g < 0) g = 0; + if (b < 0) b = 0; + mask = encoder(r, g, b); + mask = set_alpha(mask, decoder(clr, 4)); + return mask; +} + +unsigned int* +rotate(unsigned int* buf, Image* img, int len) +{ + unsigned int* mask = malloc(len * sizeof(unsigned int)); + int old_width = img->width; + int old_height = img->height; + for (int y = 0; y < old_height; y++) + { + for (int x = 0; x < old_width; x++) + { + int new_height = x; + int new_width = (old_height - 1 - y); + + mask[new_height * old_height + new_width] = + buf[y * old_width + x]; + } + } + img->width = old_height; + img->height = old_width; + free(buf); + return mask; +} + +Image +create_image(int w, int h, char* name, char* fmt) +{ + Image image = { + .width = w, + .height = h, + .len = w * h, + .name = name, + }; + image.magic_number[0] = fmt[0]; + image.magic_number[1] = fmt[1]; + image.magic_number[2] = '\0'; + return image; +} + void print_bits_int(unsigned int n) { @@ -254,41 +319,26 @@ print_bits_int(unsigned int n) write(1, "\n", 1); } -void -print_bits_char(unsigned char n) -{ - for (int i = 7; i >= 0; i--) - { - char bit = (n & (1 << i)) ? '1' : '0'; - write(1, &bit, 1); - } - write(1, "\n", 1); -} - int main() { - // unsigned int test = 40; - // print_bits_int(test); - // test = (test << 3) | (test >> (8 - 3)); - // print_bits_int(test); + Image image = create_image(3, 2, "../color.ppm", "P6"); - // unsigned int color = encoder(200, 10, 50); - // color = set_alpha(color, 100); - // print_bits_int(color); - // // unsigned int channelled_color = channel_mask(color, 'g'); - // color = chromatic_circular_shift(color, 3); - // print_bits_int(color); - int width, height; - char magic_number[3]; - int max_val; - - unsigned int* buf = - ppm_encode("../test.ppm", &width, &height, &max_val, magic_number); - // ppm_apply_brightness(buf, (width * height), .5); - // buf = vertical_flip(buf, (width * height), width, height); - buf = horizontal_flip(buf, (width * height), width, height); - ppm_decode(buf, (width * height), "../new.ppm", &width, &height); - free(buf); + unsigned int* buf = ppm_encode("../assets/4ktest.ppm", &image); + if (buf) + { + // ppm_apply_brightness(buf, image, 2); + // + for (int i = 0; i < image.len; i++) + { + // buf[i] = channel_mask(buf[i], 'b'); + // buf[i] = chromatic_circular_shift(buf[i], (rand() % 10)); + // buf[i] = constrast_adjustment(buf[i], 2); + buf[i] = to_grayscale(buf[i]); + } + // buf = rotate(buf, &image, image.len); + ppm_decode(buf, image); + free(buf); + } return 0; }