#include "ColourCode.h" #include #include #include #include static const unsigned char HEX_VALS[256] = { ['0'] = 0, ['1'] = 1, ['2'] = 2, ['3'] = 3, ['4'] = 4, ['5'] = 5, ['6'] = 6, ['7'] = 7, ['8'] = 8, ['9'] = 9, ['a'] = 10, ['b'] = 11, ['c'] = 12, ['d'] = 13, ['e'] = 14, ['f'] = 15, ['A'] = 10, ['B'] = 11, ['C'] = 12, ['D'] = 13, ['E'] = 14, ['F'] = 15, }; static int is_hex_digit(char c) { return HEX_VALS[(unsigned char)c] || c == '0'; } static int is_valid_hex(const char *s, int len) { if (len != 3 && len != 6) return 0; for (int i = 0; i < len; i++) { if (!is_hex_digit(s[i])) return 0; } return 1; } static void hex_to_rgb(const char *hex, int *r, int *g, int *b, int len) { *r = *g = *b = 0; if (len == 3) { *r = HEX_VALS[(unsigned char)hex[0]] * 17; *g = HEX_VALS[(unsigned char)hex[1]] * 17; *b = HEX_VALS[(unsigned char)hex[2]] * 17; } else if (len == 6) { *r = HEX_VALS[(unsigned char)hex[0]] * 16 + HEX_VALS[(unsigned char)hex[1]]; *g = HEX_VALS[(unsigned char)hex[2]] * 16 + HEX_VALS[(unsigned char)hex[3]]; *b = HEX_VALS[(unsigned char)hex[4]] * 16 + HEX_VALS[(unsigned char)hex[5]]; } } static void rgb_to_hsl(int r, int g, int b, int *h, int *s, int *l) { int max = r > g ? (r > b ? r : b) : (g > b ? g : b); int min = r < g ? (r < b ? r : b) : (g < b ? g : b); int delta = max - min; *l = (max + min) / 2; *s = 0; *h = 0; if (delta > 0) { *s = (int)((double)delta / (1.0 - fabs(2.0 * *l / 255.0 - 1.0)) * 100.0); if (max == r) { *h = (int)(60.0 * fmod((double)(g - b) / delta, 6.0)); } else if (max == g) { *h = (int)(60.0 * (((b - r) / delta) + 2.0)); } else { *h = (int)(60.0 * (((r - g) / delta) + 4.0)); } if (*h < 0) *h += 360; } } static void rgb_to_hsv(int r, int g, int b, int *h, int *s, int *v) { int max = r > g ? (r > b ? r : b) : (g > b ? g : b); int min = r < g ? (r < b ? r : b) : (g < b ? g : b); int delta = max - min; *v = max * 100 / 255; *s = max > 0 ? delta * 100 / max : 0; *h = 0; if (delta > 0) { if (max == r) { *h = (int)(60.0 * fmod((double)(g - b) / delta, 6.0)); } else if (max == g) { *h = (int)(60.0 * (((b - r) / delta) + 2.0)); } else { *h = (int)(60.0 * (((r - g) / delta) + 4.0)); } if (*h < 0) *h += 360; } } static void rgb_to_cmyk(int r, int g, int b, int *c, int *m, int *y, int *k) { int max = r > g ? (r > b ? r : b) : (g > b ? g : b); double kf = 1.0 - max / 255.0; if (kf >= 0.99) { *c = *m = *y = *k = 100; } else { *c = (int)((1.0 - r / 255.0 - kf) / (1.0 - kf) * 100); *m = (int)((1.0 - g / 255.0 - kf) / (1.0 - kf) * 100); *y = (int)((1.0 - b / 255.0 - kf) / (1.0 - kf) * 100); *k = (int)(kf * 100); } } int is_colour_code_query(const char *query) { if (!query) return 0; const char *p = query; if (p[0] == '#') { p++; while (*p == ' ') p++; const char *end = p; while (is_hex_digit(*end)) end++; int len = end - p; return is_valid_hex(p, len); } return 0; } InfoBox fetch_colour_data(char *query) { InfoBox info = {NULL, NULL, NULL, NULL}; if (!query) return info; const char *p = query; if (p[0] != '#') return info; p++; while (*p == ' ') p++; const char *end = p; while (is_hex_digit(*end)) end++; int len = end - p; if (!is_valid_hex(p, len)) return info; int r, g, b; hex_to_rgb(p, &r, &g, &b, len); int h, s, l; rgb_to_hsl(r, g, b, &h, &s, &l); int h2, s2, v; rgb_to_hsv(r, g, b, &h2, &s2, &v); int c, m, y, k; rgb_to_cmyk(r, g, b, &c, &m, &y, &k); char html[1024]; snprintf(html, sizeof(html), "
" "
" "
" "
" "
" "#%.*s
" "
RGB(%d, %d, %d)
" "
HSL(%d, %d%%, %d%%)
" "
HSV(%d, %d%%, %d%%)
" "
CMYK(%d%%, %d%%, %d%%, %d%%)
" "
" "
" "
", len, p, len, p, r, g, b, h, s, l, h2, s2, v, c, m, y, k); info.title = strdup("Colour"); info.extract = strdup(html); info.thumbnail_url = NULL; info.url = strdup("#"); return info; }