#define STB_IMAGE_IMPLEMENTATION #define STB_IMAGE_WRITE_IMPLEMENTATION #define STBI_FAILURE_USERMSG #include "stb_image.h" #include "stb_image_write.h" /* 0 - balanced 1 - average of two largest channels, bias towards darker shades, use if unsure 2 - makes image brighter 3 - ??? (lots of banding so reduce strength) */ #define LUMINANCE_METHOD 1 /* 1 is the minimum, going below 1 makes surprising effects the higher value the less effect it has so when I say "reduce strength" I mean "increase the value" */ #define VIBRANCE_STRENGTH 1.1 /* if a pixel goes below 0% or above 100% basically subtract the difference so -10% becomes 10% and 110% becomes 90% this was supposed to fix clipping but messes up colors (I remember I had in mind a fix but I don't remember it) uncomment to enable */ //#define BETTER_CLAMP const static inline int max(int a, int b) { return a > b ? a : b; } const static inline int max3(int a, int b, int c) { int ab = max(a, b); return ab > c ? ab : c; } const static inline int min(int a, int b) { return a < b ? a : b; } const static inline int min3(int a, int b, int c) { int ab = min(a, b); return ab < c ? ab : c; } #ifdef BETTER_CLAMP const static inline int cdiff(int n, int min, int max) { if (n > max) return max - (n - max); else if (n < min) { return min + (min - n); } return n; } const static inline int clamp(int n, int min, int max) { return cdiff(n, min, max); } // I don't know if const static inline was needed #else const static inline int clamp(int n, int min, int max) { return n > max ? max : (n < min ? min : n); } #endif void vibrancer(unsigned char *pixel) { int r = pixel[0], g = pixel[1], b = pixel[2]; // TODO remove unnecessary calculations int min_rgb = min3(r, g, b); int max_rgb = max3(r, g, b); int sum = r + g + b; int m; if (LUMINANCE_METHOD == 3) // twist m = 3*sum - 4*(min_rgb + max_rgb); else if (LUMINANCE_METHOD == 2) // nomax m = (sum - max_rgb) / 2; else if (LUMINANCE_METHOD == 1) // nomin m = (sum - min_rgb) / 2; else // simple m = sum / 3; r -= (m - r) / VIBRANCE_STRENGTH; g -= (m - g) / VIBRANCE_STRENGTH; b -= (m - b) / VIBRANCE_STRENGTH; pixel[0] = clamp(r, 0, 255); pixel[1] = clamp(g, 0, 255); pixel[2] = clamp(b, 0, 255); } int main(int argc, char **argv) { if (VIBRANCE_STRENGTH == 0) { printf("VIBRANCE_STRENGTH cannot be zero"); return 1; } char* input = argv[1]; char* output = argv[2]; if (argc < 3) { printf("Please specify input and output files\n"); return 2; } int width, height, channels; unsigned char *img = stbi_load(input, &width, &height, &channels, 0); //printf("Width: %d, Height: %d, Channels: %d\n", width, height, channels); if (img == NULL) { printf("Error loading image\n"); printf("%s\n", stbi_failure_reason()); return 1; } if (channels < 3) { printf("Not enough channels (%d)", channels); return 1; } for (int y=0; y