From d48b9e9b98731feaa1a1dab6d1ff58e90ed9f016 Mon Sep 17 00:00:00 2001 From: <> Date: Sat, 18 Mar 2017 00:23:13 -0700 Subject: [PATCH] color conversion to hsl working --- includes/colors.c | 245 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 245 insertions(+) create mode 100644 includes/colors.c diff --git a/includes/colors.c b/includes/colors.c new file mode 100644 index 0000000..9a8f57b --- /dev/null +++ b/includes/colors.c @@ -0,0 +1,245 @@ +#include +#include +#include +#include +#define ASCII_ZERO 48 +#define ASCII_NINE 57 +#define MIN_CONTRAST 0.5 + //html = _dec_colors.sub(lambda match: _dec_spans[int(match.group(1))], qstr) + // this is an extremely fancy if not confusing way to say + // the single number that isn't an x, right after a ^ + // is an index to an array of strings. + //html = _hex_colors.sub(hex_repl, html) + // the next 3 letters after after ^x is digits for rgb + // the verdict is: + // regex is not needed + // do the hex replacement first, then do the dec replacement + + // instead of concatenating strings, they will be printed in parts. + +// can either be RGB or HLS +struct Rgb { + int r, g, b; +}; + +struct Hls { + int h; + float l, s; +}; + +void cvt_rgb(struct Rgb *dest, const struct Hls const *src) { + if ((0 > src -> h || src -> h > 360) || + (0 > src -> s && src -> s > 1) || + (0 > src -> l && src -> l > 1)) { + return; + } + float hue = src -> h; + float r, g, b; + float chroma = (1 - fabs(2 * (src -> l) - 1)) * (src -> s); + float x = chroma * (1 - fabs((int)(hue/60) % 2 - 1)); + float m = (src -> l) - chroma/2; + if (0 <= hue && hue < 60) { + r = chroma; + g = x; + b = 0; + } else if (60 <= hue && hue < 120) { + r = x; + g = chroma; + b = 0; + } else if (120 <= hue && hue < 180) { + r = 0; + g = chroma; + b = x; + } else if (180 <= hue && hue < 240) { + r = 0; + g = x; + b = chroma; + } else if (240 <= hue && hue < 300) { + r = x; + g = 0; + b = chroma; + } else if (300 <= hue && hue < 360) { + r = chroma; + g = 0; + b = x; + } else { + r = 0; + g = 0; + b = 0; + } + dest -> r = (r + m) * 255; + dest -> g = (g + m) * 255; + dest -> b = (b + m) * 255; +} + +void cvt_hls(struct Hls *dest, const struct Rgb const *src) { + if (src == NULL || dest == NULL) { + return; + } + float r = src -> r / 255.0f; + float g = src -> g / 255.0f; + float b = src -> b / 255.0f; + float min = fmin(fmin(r, g), b); + float max = fmax(fmax(r, g), b); + dest -> l = (max + min)/2; //bi-hexcone model. + if (max == min) { // neutral color. + dest -> h = 0; // undefined. + dest -> s = 0.0f; + } else { + float chroma = max - min; + dest -> s = (dest -> l > 0.5) ? (chroma/(2 - max - min)) : (chroma/(max + min)); + //piecewise function.. + float hue; + if (max == r) { + hue = (int)((g - b)/chroma) + (g < b ? 6 : 0); // % 6 will break magenta (255, 0, 255) + } else if (max == g) { + hue = ((b - r)/chroma) + 2.0f; + } else { + hue = ((r - g)/chroma) + 4.0f; + } + dest -> h = (int)(hue * 60); + } +} + +void dec(const int d) { + switch(d) { + case 0: + printf(""); + break; + case 1: + printf(""); + break; + case 2: + printf(""); + break; + case 3: + printf(""); + break; + case 4: + printf(""); + break; + case 5: + printf(""); + break; + case 6: + printf(""); + break; + case 7: + printf(""); + break; + case 8: + printf(""); + break; + case 9: + printf(""); + break; + } +} + +void hex(const char *str) { + const char h1[2] = {str[0], '\0'}; + const char h2[2] = {str[1], '\0'}; + const char h3[2] = {str[2], '\0'}; + struct Rgb nrgb; + nrgb.r = strtol(h1, NULL, 16); + nrgb.g = strtol(h2, NULL, 16); + nrgb.b = strtol(h3, NULL, 16); + struct Hls nhls; + cvt_hls(&nhls, &nrgb); + if (nhls.l < MIN_CONTRAST) { + nhls.l = MIN_CONTRAST; + cvt_rgb(&nrgb, &nhls); + } + printf("", nrgb.r, nrgb.g, nrgb.b); +} + +void b(char * const str) { +#define IS_DIGIT(x) (x >= ASCII_ZERO && x <= ASCII_NINE) + char *token = strtok(str, "^"); + char c; + while (token) { + c = token[0]; + if (IS_DIGIT(c)) { + dec(c - ASCII_ZERO); + printf("%s", token + 1); + } else if (c == 'x' && strlen(token) > 4) { + hex(token + 1); //exclude x + printf("%s", token + 4); + } else { + printf("%s", token); + } + token = strtok(NULL, "^"); + } + printf(""); +} + +// O(n) +void a(const char* str) { + //find instance of ^^ + //replace with ^ + //concatenate with rest of the string + char *copy; + copy = calloc(strlen(str) + 1, sizeof(char)); + strcpy(copy, str); + char *pos = copy; + while (pos = strstr(pos, "^^")) { + strcpy(pos, (pos + 1)); + } + b(copy); + free(copy); +} + +void testconversion(int r, int g, int b) { + struct Rgb x; + x.r = r; + x.g = g; + x.b = b; + struct Hls y; + cvt_hls(&y, &x); + printf("%d %f %f\n", y.h, y.s, y.l); +} + +void testconvhls(int h, float s, float l) { + struct Hls x; + x.h = h; + x.s = s; + x.l = l; + struct Rgb y; + cvt_rgb(&y, &x); + printf("%d %d %d\n", y.r, y.g, y.b); +} + +int main() { +/* a("^xf00Unregistered Player^7"); + a("^9[^1S^9]^x469Kom^0ier^7"); + a("^9sjn^5|^9F^5e^9tus^7"); + a("^0[^7>>^0]^xaefdizzy^7"); */ +/* testconversion(10, 15, 12); + testconversion(5, 5, 5); + testconversion(3, 15, 10); + testconversion(7, 8, 9); + testconvhls(144, 0.20, 0.5); + testconvhls(0, 0, 0.2); + testconvhls(154, 0.67, 0.035); + testconvhls(210, 0.125, 0.03); + testconvhls(60, 1, 0.25); + testconvhls(180, 1, 0.25); + testconvhls(240, 1, 0.25); */ + testconversion(0, 0, 0); + testconversion(255, 255, 255); + testconversion(255, 0, 0); + testconversion(0, 255, 0); + testconversion(0, 0, 255); + testconversion(255, 255, 0); + testconversion(0, 255, 255); + testconversion(255, 0, 255); + testconversion(192, 192, 192); + testconversion(128, 128, 128); + testconversion(128, 0, 0); + testconversion(128, 128, 0); + testconversion(0, 128, 0); + testconversion(128, 0, 128); + testconversion(128, 0, 128); + testconversion(0, 128, 128); + testconversion(0, 0, 128); +} \ No newline at end of file