#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 r, g, b; float hue = src -> h; 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 = ceil((r + m) * 255); dest -> g = ceil((g + m) * 255); dest -> b = ceil((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); testconvhls(0, 0, 0); testconvhls(0, 0, 1); testconvhls(0, 1, 0.5); testconvhls(120, 1, 0.5); testconvhls(240, 1, 0.5); testconvhls(60, 1, 0.5); testconvhls(180, 1, 0.5); testconvhls(300, 1, 0.5); testconvhls(0, 0, 0.75); testconvhls(0, 0, 0.5); testconvhls(0, 1, 0.25); testconvhls(60, 1, 0.25); testconvhls(120, 1, 0.25); testconvhls(300, 1, 0.25); testconvhls(180, 1, 0.25); testconvhls(240, 1, 0.25); }