diff options
author | kdx <kikoodx@paranoici.org> | 2023-07-24 15:17:51 +0200 |
---|---|---|
committer | kdx <kikoodx@paranoici.org> | 2023-07-24 15:17:51 +0200 |
commit | 4cd7ee8210aafaf927e381603e4995fb3b1e68d9 (patch) | |
tree | e3d7ba11d336aa735e35fa094e537eed22f60c06 | |
parent | 4c1ecac3addae3d418a15ab5d8fe4848e9fad714 (diff) | |
download | catgy-4cd7ee8210aafaf927e381603e4995fb3b1e68d9.tar.gz |
bit3 & blurge & gol
-rw-r--r-- | catgy.c | 111 |
1 files changed, 94 insertions, 17 deletions
@@ -1,6 +1,7 @@ #include <stdint.h> #include <stdio.h> #include <strings.h> +#include <time.h> #define STB_IMAGE_IMPLEMENTATION #include "stb_image.h" @@ -11,19 +12,32 @@ struct image { uint8_t *data; }; -static int process(char **argv); +static int process(int argc, char **argv); +static void bit3(struct image *img); static void chaos1(struct image *img); static void chaos3(struct image *img); +static void blurge(struct image *img); +static void gol(struct image *img); int main(int argc, char **argv) { - if (argc != 3) { - fprintf(stderr, "usage: %s filter image\n", + if (argc < 2) { + fprintf(stderr, "usage: %s image [filters]\n", argv[0]); return 1; } - return process(argv); + srand(time(NULL)); + + return process(argc, argv); +} + +static void +bit3(struct image *img) +{ + /* deterministic threshold to 3-bit */ + for (long i = 0; i < img->w * img->h * CHANS; i++) + img->data[i] = (img->data[i] > 0x7f) * 0xff; } static void @@ -47,11 +61,67 @@ chaos3(struct image *img) img->data[i] = (img->data[i] > (rand() & 0xff)) * 0xff; } +static void +average(uint8_t dest[3], uint8_t src[9]) +{ + for (int i = 0; i < 3; i++) + dest[i] = (src[i] + src[i + 3] + src[i + 6]) / 3; +} + +static void +blurge(struct image *img) +{ + for (int y = 0; y < img->h; y++) + for (int x = 1; x < img->w - 1; x++) + average(&img->data[x * 3 + y * img->w * 3], + &img->data[x * 3 - 3 + y * img->w * 3]); +} + +static int +neighbors(struct image *img, int x, int y, int o) +{ + const int stride = img->w * 3; + return (img->data[o + (x - 1) * 3 + (y ) * stride] != 0) + + (img->data[o + (x + 1) * 3 + (y ) * stride] != 0) + + (img->data[o + (x ) * 3 + (y - 1) * stride] != 0) + + (img->data[o + (x ) * 3 + (y + 1) * stride] != 0) + + (img->data[o + (x - 1) * 3 + (y - 1) * stride] != 0) + + (img->data[o + (x - 1) * 3 + (y + 1) * stride] != 0) + + (img->data[o + (x + 1) * 3 + (y - 1) * stride] != 0) + + (img->data[o + (x + 1) * 3 + (y + 1) * stride] != 0); +} + +static void +gol(struct image *img) +{ + uint8_t *copy = malloc(img->w * img->h * img->chans); + if (copy == NULL) { + perror("malloc"); + return; + } + memcpy(copy, img->data, img->w * img->h * img->chans); + + for (int y = 1; y < img->h - 1; y++) { + for (int x = 1; x < img->w - 1; x++) { + for (int o = 0; o < 3; o++) { + const int near = neighbors(img, x, y, o); + const int i = x * 3 + y * img->w * 3 + o; + if (near < 2 || near > 3) + copy[i] = 0; + else + copy[i] = 0xff; + } + } + } + + memcpy(img->data, copy, img->w * img->h * img->chans); + free(copy); +} + static int -process(char **argv) +process(int argc, char **argv) { - const char *filter = argv[1]; - const char *path = argv[2]; + const char *path = argv[1]; /* read image */ struct image img; @@ -78,23 +148,30 @@ process(char **argv) const char *name; void (*fun)(struct image *img); } filters[] = { + { "bit3", bit3 }, { "chaos1", chaos1 }, { "chaos3", chaos3 }, + { "blurge", blurge }, + { "gol", gol }, }; int filtered = 0; - for (size_t i = 0; i < sizeof(filters) / sizeof(filters[0]); i++) { - if (strcasecmp(filter, filters[i].name) == 0) { - filters[i].fun(&img); - filtered = 1; - break; + + for (int i = 2; i < argc; i++) { + const char *filter = argv[i]; + for (size_t i = 0; i < sizeof(filters) / sizeof(filters[0]); i++) { + if (strcasecmp(filter, filters[i].name) == 0) { + filters[i].fun(&img); + filtered = 1; + break; + } } - } - if (!filtered) { - fprintf(stderr, "error: unknown filter '%s'\n", filter); - stbi_image_free(img.data); - return 1; + if (!filtered) { + fprintf(stderr, "error: unknown filter '%s'\n", filter); + stbi_image_free(img.data); + return 1; + } } /* write PPM */ |