diff --git a/.DS_Store b/.DS_Store index 4b30aeb..b664519 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 0000000..98dddea --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,29 @@ +# --- +# Checks: 'bugprone-*,modernize-*,performance-*,readability-*' +# WarningsAsErrors: '' +# --- + +--- +# Enable a broad range of useful C checks +Checks: > + -*, + bugprone-*, + concurrency-*, + misc-*, + modernize-*, + performance-*, + readability-*, + portability-*, + -readability-braces-around-statements, + -readability-implicit-bool-conversion + +# Treat all enabled checks as errors (optional, shows up as Red in Neovim) +WarningsAsErrors: "" + +# Project-specific settings +CheckOptions: + - key: readability-identifier-naming.VariableCase + value: lower_case + - key: readability-identifier-naming.FunctionCase + value: lower_case +--- diff --git a/src/main.c b/src/main.c index fe4466d..386aa21 100644 --- a/src/main.c +++ b/src/main.c @@ -3,147 +3,159 @@ #include #include +#define BYTE_A 0xFF000000 +#define BYTE_R 0x00FF0000 +#define BYTE_G 0x0000FF00 +#define BYTE_B 0x000000FF +#define BYTE_RGB 0x00FFFFFF +#define BYTE 0xFF + +#define SHIFT_8 8 +#define SHIFT_16 16 +#define SHIFT_24 24 + +#define MAX 255 +#define HALF_MAX ((int)(MAX / 2) + 1) + +#define decode_a(clr) (((clr) >> SHIFT_24) & BYTE) +#define decode_r(clr) (((clr) >> SHIFT_16) & BYTE) +#define decode_g(clr) (((clr) >> SHIFT_8) & BYTE) +#define decode_b(clr) ((clr) & BYTE) + +#define encode(r, g, b) \ + (((unsigned int)(MAX) << SHIFT_24) | ((unsigned int)(r) << SHIFT_16) | \ + ((unsigned int)(g) << SHIFT_8) | (unsigned int)(b)) + +#define CLAMP_MAX(x) (((x) > MAX) ? MAX : (x)) +#define CLAMP_MIN(x) (((x) < 0) ? 0 : (x)) + typedef struct { int width, height, len; - char* name; - char magic_number[3]; + const char* name; + char fmt[3]; } Image; -unsigned int -encoder(unsigned char r, unsigned char g, unsigned char b) +static inline unsigned int +set_alpha(const unsigned int clr, const unsigned char alpha_value) { - return (b << 0) | (g << 8) | (r << 16); + return (clr & BYTE_RGB) | alpha_value << SHIFT_24; } -unsigned char -decoder(unsigned int clr, int byte) +static inline unsigned int +invert_rgb(const unsigned int clr) { - 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; + return ((~clr) & BYTE_RGB) | (clr & BYTE_A); } -unsigned int -set_alpha(unsigned int clr, unsigned char alpha_value) +static inline unsigned int +swap_rb(const unsigned int clr) { - return (clr & 0x00FFFFFF) | alpha_value << 24; + return (clr & 0xFF00FF00) | ((clr & BYTE_R) >> SHIFT_16) | + ((clr & BYTE_B) << SHIFT_16); } -unsigned int -invert_rgb(unsigned int clr) +static inline unsigned int +to_grayscale(const unsigned int clr) { - return ((~clr) & 0x00FFFFFF) | (clr & 0xFF000000); + unsigned int red = decode_r(clr); + unsigned int green = decode_g(clr); + unsigned int blue = decode_b(clr); + unsigned int gray = + ((red * 77) + (green * 150) + (blue * 29)) >> SHIFT_8; + + return (clr & BYTE_A) | (gray << SHIFT_16) | (gray << SHIFT_8) | gray; } -unsigned int -swap_rb(unsigned int clr) -{ - return (((clr & 0xFF00FF00) | ((decoder(clr, 3)) << 0) | - ((decoder(clr, 1) >> 0) << 16))); -} - -unsigned int -to_grayscale(unsigned int clr) -{ - int average = - (decoder(clr, 3) + decoder(clr, 2) + decoder(clr, 1)) * .33333; - unsigned int mask = encoder(average, average, average); - mask = set_alpha(mask, decoder(clr, 4)); - - return mask; -} - -unsigned int -apply_threshold(unsigned int clr, unsigned char limit) +static inline unsigned int +apply_threshold(const unsigned int clr, const unsigned char limit) { unsigned int mask = 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; + if (decode_b(to_grayscale(clr)) < limit) mask = encode(0, 0, 0); + else mask = encode(MAX, MAX, MAX); + return BYTE_A | mask; } -unsigned int -adjust_brightness(unsigned int clr, float factor) +static inline unsigned int +adjust_brightness(const unsigned int clr, const float factor) { - unsigned int red = decoder(clr, 3) * factor; - unsigned int green = decoder(clr, 2) * factor; - unsigned int blue = decoder(clr, 1) * factor; - if (red > 255) red = 255; - if (green > 255) green = 255; - if (blue > 255) blue = 255; - unsigned int mask = encoder(red, green, blue); - mask = set_alpha(mask, decoder(clr, 4)); - return mask; + unsigned int alpha = (clr & BYTE_A); + unsigned int red = + CLAMP_MAX((unsigned int)((float)decode_r(clr) * factor)); + unsigned int green = + CLAMP_MAX((unsigned int)((float)decode_g(clr) * factor)); + unsigned int blue = + CLAMP_MAX((unsigned int)((float)decode_b(clr) * factor)); + return (clr & BYTE_A) | (red << SHIFT_16) | (green << SHIFT_8) | blue; } -unsigned int -apply_tint(unsigned int clr_a, unsigned int clr_b) +static inline unsigned int +apply_tint(const unsigned int clr_a, const unsigned int clr_b) { - unsigned char blue = (decoder(clr_a, 1) + decoder(clr_b, 1)) / 2; - unsigned char green = (decoder(clr_a, 2) + decoder(clr_b, 2)) / 2; - unsigned char red = (decoder(clr_a, 3) + decoder(clr_b, 3)) / 2; + unsigned char blue = (decode_b(clr_a) + decode_b(clr_b)) / 2; + unsigned char green = (decode_g(clr_a) + decode_g(clr_b)) / 2; + unsigned char red = (decode_r(clr_a) + decode_r(clr_b)) / 2; - return set_alpha(encoder(red, green, blue), decoder(clr_a, 4)); + return set_alpha(encode(red, green, blue), decode_a(clr_a)); } -unsigned int -apply_opacity(unsigned clr_a, unsigned int clr_b, float ratio) +static inline unsigned int +apply_opacity(const unsigned clr_a, const unsigned int clr_b, const float ratio) { - unsigned char blue = - (decoder(clr_a, 1) * (1 - ratio) + (decoder(clr_b, 1) * ratio)); - unsigned char green = - (decoder(clr_a, 2) * (1 - ratio) + (decoder(clr_b, 2) * ratio)); - unsigned char red = - (decoder(clr_a, 3) * (1 - ratio) + (decoder(clr_b, 3) * ratio)); - return set_alpha(encoder(red, green, blue), decoder(clr_a, 4)); + unsigned char blue = (unsigned char)((decode_b(clr_a) * (1 - ratio)) + + ((decode_b(clr_b) * ratio))); + unsigned char green = (unsigned char)((decode_g(clr_a) * (1 - ratio)) + + ((decode_g(clr_b) * ratio))); + unsigned char red = (unsigned char)((decode_r(clr_a) * (1 - ratio)) + + ((decode_r(clr_b) * ratio))); + return set_alpha(encode(red, green, blue), decode_a(clr_a)); } -unsigned int* -ppm_encode(char* file, Image* img) +static inline unsigned int* +ppm_encode(const char* file, Image* img) { - unsigned char r, g, b; + printf("Starting encode...\n"); + unsigned char red; + unsigned char green; + unsigned char blue; + char fmt[3]; int max_val; FILE* fptr; fptr = fopen(file, "r"); - if (!fptr) return NULL; - fscanf(fptr, "%s", img->magic_number); + if (!fptr) return nullptr; + fscanf(fptr, "%s", fmt); 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; - if (img->magic_number[1] == '3') + if (!buf) return nullptr; + if (fmt[1] == '3') { 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); + fscanf(fptr, "%hhu %hhu %hhu", &red, &green, &blue); + buf[i] = encode(red, green, blue); } } - else if (img->magic_number[1] == '6') + else if (fmt[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); + fread(&red, sizeof(unsigned char), 1, fptr); + fread(&green, sizeof(unsigned char), 1, fptr); + fread(&blue, sizeof(unsigned char), 1, fptr); + buf[i] = encode(red, green, blue); } } fclose(fptr); + printf("Encoding done!\n"); return buf; } -void -ppm_apply_brightness(unsigned int* buf, Image img, float factor) +static inline void +ppm_apply_brightness(unsigned int* buf, const Image img, const float factor) { for (int i = 0; i < img.len; i++) { @@ -151,78 +163,89 @@ ppm_apply_brightness(unsigned int* buf, Image img, float factor) } } -void -ppm_decode(unsigned int* buf, Image img) +static inline void +ppm_decode(const unsigned int* buf, const Image img) { - unsigned char red, green, blue; + printf("Starting decode...\n"); 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 (img.fmt[1] == '3') fptr = fopen(img.name, "w"); + if (img.fmt[1] == '6') fptr = fopen(img.name, "wb"); if (!fptr) return; - fprintf(fptr, "%s\n%d %d\n255\n", img.magic_number, img.width, - img.height); - for (int i = 0; i < img.len; i++) + fprintf(fptr, "%s\n%d %d\n255\n", img.fmt, img.width, img.height); + if (img.fmt[1] == '3') { - red = decoder(buf[i], 3); - green = decoder(buf[i], 2); - blue = decoder(buf[i], 1); - fwrite(&red, 1, 1, fptr); - fwrite(&green, 1, 1, fptr); - fwrite(&blue, 1, 1, fptr); + for (int i = 0; i < img.len; i++) + { + unsigned char red = decode_r(buf[i]); + unsigned char green = decode_g(buf[i]); + unsigned char blue = decode_b(buf[i]); + fprintf(fptr, "%d %d %d ", red, green, blue); + if (i % 7 == 0) + { + fprintf(fptr, "\n"); + } + } + } + if (img.fmt[1] == '6') + { + for (int i = 0; i < img.len; i++) + { + unsigned char red = decode_r(buf[i]); + unsigned char green = decode_g(buf[i]); + unsigned char blue = decode_b(buf[i]); + fwrite(&red, 1, 1, fptr); + fwrite(&green, 1, 1, fptr); + fwrite(&blue, 1, 1, fptr); + } } fclose(fptr); + printf("Decode Done!\n"); } -unsigned int -channel_mask(unsigned int clr, char keep) +static inline unsigned int +channel_mask(const unsigned int clr, const char keep) { - unsigned int mask = 0; switch (keep) { case 'r': - mask = encoder(decoder(clr, 3), 0, 0); + return clr & (BYTE_A | BYTE_R); break; case 'g': - mask = encoder(0, decoder(clr, 2), 0); + return clr & (BYTE_A | BYTE_G); break; case 'b': - mask = encoder(0, 0, decoder(clr, 1)); + return clr & (BYTE_A | BYTE_B); break; } - mask = set_alpha(mask, decoder(clr, 4)); - return mask; + return 0; } -unsigned int -chromatic_circular_shift(unsigned int clr, int n) +static inline unsigned int +chromatic_circular_shift(const unsigned int clr, const int n) { - unsigned int mask = 0; - unsigned char r, g, b; - r = decoder(clr, 3); - g = decoder(clr, 2); - b = decoder(clr, 1); + unsigned int red = decode_r(clr); + unsigned int green = decode_g(clr); + unsigned int blue = decode_b(clr); - r = (r << n) | (r >> (8 - n)); - g = (g << n) | (g >> (8 - n)); - b = (b << n) | (b >> (8 - n)); - mask = encoder(r, g, b); - mask = set_alpha(mask, decoder(clr, 4)); - return mask; + red = ((red << n) | (red >> (SHIFT_8 - n))) & BYTE; + green = ((green << n) | (green >> (SHIFT_8 - n))) & BYTE; + blue = ((blue << n) | (blue >> (SHIFT_8 - n))) & BYTE; + return encode(red, green, blue); } -unsigned int* -horizontal_flip(unsigned int* buf, Image img) +static inline unsigned int* +horizontal_flip(unsigned int* buf, const Image img) { unsigned int* flip = malloc(img.len * sizeof(unsigned int)); - if (!flip) return NULL; + if (!flip) return nullptr; int idx = 0; for (int i = 0; i < img.height; i++) { for (int k = img.width - 1; k >= 0; k--) { - flip[idx] = buf[i * img.width + k]; + flip[idx] = buf[(i * img.width) + k]; idx++; } } @@ -231,18 +254,18 @@ horizontal_flip(unsigned int* buf, Image img) return flip; } -unsigned int* +static inline unsigned int* vertical_flip(unsigned int* buf, Image img) { unsigned int* flip = malloc(img.len * sizeof(unsigned int)); - if (!flip) return NULL; + if (!flip) return nullptr; int idx = 0; for (int i = img.height - 1; i >= 0; i--) { for (int k = 0; k < img.width; k++) { - flip[idx] = buf[i * img.width + k]; + flip[idx] = buf[(i * img.width) + k]; idx++; } } @@ -251,39 +274,34 @@ vertical_flip(unsigned int* buf, Image img) return flip; } -unsigned int +static inline 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; + int red = CLAMP_MIN(CLAMP_MAX( + (int)(factor * (float)(int)(decode_r(clr) - HALF_MAX)) + HALF_MAX)); + int green = CLAMP_MIN(CLAMP_MAX( + (int)(factor * (float)(int)(decode_g(clr) - HALF_MAX)) + HALF_MAX)); + int blue = CLAMP_MIN(CLAMP_MAX( + (int)(factor * (float)(int)(decode_b(clr) - HALF_MAX)) + HALF_MAX)); + return BYTE_A | (red << SHIFT_16) | (green << SHIFT_8) | blue; } -unsigned int* +static inline 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 row = 0; row < old_height; row++) { - for (int x = 0; x < old_width; x++) + for (int col = 0; col < old_width; col++) { - int new_height = x; - int new_width = (old_height - 1 - y); + int new_height = col; + int new_width = (old_height - 1 - row); - mask[new_height * old_height + new_width] = - buf[y * old_width + x]; + mask[(new_height * old_height) + new_width] = + buf[(row * old_width) + col]; } } img->width = old_height; @@ -292,52 +310,31 @@ rotate(unsigned int* buf, Image* img, int len) 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) -{ - for (int i = 31; i >= 0; i--) - { - if (i == 7 || i == 15 || i == 23) write(1, " ", 1); - char bit = (n & (1 << i)) ? '1' : '0'; - write(1, &bit, 1); - } - write(1, "\n", 1); -} - int main() { - Image image = create_image(3, 2, "../color.ppm", "P6"); + Image img = { .width = 3, + .height = 2, + .name = "../color.ppm", + .fmt = "P3", + .len = 0 }; - unsigned int* buf = ppm_encode("../assets/4ktest.ppm", &image); + unsigned int* buf = ppm_encode("../assets/8ktest.ppm", &img); if (buf) { - // ppm_apply_brightness(buf, image, 2); - // - for (int i = 0; i < image.len; i++) + ppm_apply_brightness(buf, img, 2); + + for (int i = 0; i < img.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[i] = channel_mask(buf[i], 'r'); + // buf[i] = chromatic_circular_shift(buf[i], (rand() % + // 5)); buf[i] = constrast_adjustment(buf[i], .1f); + // buf[i] = adjust_brightness(buf[i], 1.5f); + // buf[i] = swap_rb(buf[i]); + // buf[i] = to_grayscale(buf[i]); } // buf = rotate(buf, &image, image.len); - ppm_decode(buf, image); + ppm_decode(buf, img); free(buf); } return 0;