colors

extract colors from pictures
git clone git://git.2f30.org/colors.git
Log | Files | Refs | README | LICENSE

commit b80c7fb1653faa2b4e2bf83b0c4b209afc33fc4a
parent 89be999289757f6a15bc78ca53e9cb5c95289794
Author: z3bra <willyatmailoodotorg>
Date:   Tue,  6 Oct 2015 21:26:00 +0200

hexsort: rewrote algorithm from scratch

Diffstat:
bin/a.out | 0
bin/hexsort.c | 124+++++++++++++++++++++++++++++++++++++++++++++++--------------------------------
2 files changed, 74 insertions(+), 50 deletions(-)

diff --git a/bin/a.out b/bin/a.out Binary files differ. diff --git a/bin/hexsort.c b/bin/hexsort.c @@ -5,6 +5,9 @@ #include <unistd.h> #include <string.h> +/* magic to return the ratio between two numbers */ +#define RATIO(a,b) (((a)>(b) ? 1.0*(b)/(a) : ((a) > 0 ? 1.0*(a)/(b) : 0))) + struct color_t { char hex[8]; int rgb[3]; @@ -18,7 +21,7 @@ struct color_t **messed = NULL; void usage(char *argv0) { - fprintf(stderr, "usage: %s [kbgcrmyw]\n", argv0); + fprintf(stderr, "usage: %s [mask]\n", argv0); } /* @@ -37,36 +40,63 @@ hex2rgb(char *hex, int *rgb) } /* + * Returns the "ratio" of the negative color for an RGB representation. + * + * For mask 4 (100)b which is red. It will return the purity ratio of its + * negative color: cyan (#00ffff). For example: + * + * #ff2d2d 255,45,45 45/45 = 1.0 (this is a "full" cyan) + * #ff3c1e 255,6°,30 60/30 = 0.5 (this is a "half" cyan) + */ +double +color_ratio(int *rgb, uint8_t mask) +{ + switch(mask) { + case 4: return RATIO(rgb[1],rgb[2]); + case 2: return RATIO(rgb[0],rgb[2]); + case 1: return RATIO(rgb[0],rgb[1]); + case 3: return RATIO(rgb[1],rgb[2]); + case 5: return RATIO(rgb[0],rgb[2]); + case 6: return RATIO(rgb[0],rgb[1]); + } + return 0; +} + +/* * Calculate a score for the dominance of the color given by `mask` (3 bit * representation of the RGB color, eg: 101 is magenta). - * For now, it sums the 1 bits, calculate the average value and substract the - * negative value of the color (eg, opposite of 101 is 010: green). - * TODO: take into consideration the "distance" between two colors for two - * bits masks. - * For example, with mask 101: - * - * HECODE RGB SCORE - * ----------------------- - * #500050 80,0,80 80 - * #ff0000 255,0,0 127.5 + * This will calculate the score of the color regarding the mask, and return + * this value for comparison with other colors. "pure" refers to the color + * represented by the mask, "negative" refers to the opposite of this color. + * + * We differentiate 3 types of masks: + * + 100, 010, 001 + * + 110, 101, 011 + * + 111, 000 * - * #ff0000 gets a higher score because it's brigther. But that's definitely not - * a nice magenta. + * First group will be the pure color, divided by the negative ratio. + * Second group will be the pure color multiplied by the pure ratio. + * Last group is just a plain sum of all colors. + * + * (Check function color_ratio() for an explanation on the ratio) */ double color_dominant(int *rgb, uint8_t mask) { - double pure = 0, negative = 0; + double pure = 0, negative = 0, ratio = 0; + + int prgb[3]; + int nrgb[3]; /* get the score of the current value */ - pure += rgb[0] * ((mask & 4)>>2); - pure += rgb[1] * ((mask & 2)>>1); - pure += rgb[2] * ((mask & 1)>>0); + prgb[0] = rgb[0] * ((mask & 4)>>2); + prgb[1] = rgb[1] * ((mask & 2)>>1); + prgb[2] = rgb[2] * ((mask & 1)>>0); /* score of the negative value */ - negative += rgb[0] * (((mask ^ 4)>>2)&1); - negative += rgb[1] * (((mask ^ 2)>>1)&1); - negative += rgb[2] * (((mask ^ 1)>>0)&1); + nrgb[0] = rgb[0] * (((mask ^ 4)>>2)&1); + nrgb[1] = rgb[1] * (((mask ^ 2)>>1)&1); + nrgb[2] = rgb[2] * (((mask ^ 1)>>0)&1); /* * calculate the average of either pure or negative color depending on @@ -76,21 +106,23 @@ color_dominant(int *rgb, uint8_t mask) case 1: case 2: case 4: - negative /= 2; - break; + pure = prgb[0] + prgb[1] + prgb[2]; + negative = (nrgb[0] + nrgb[1] + nrgb[2])/2; + ratio = 1 + negative * color_ratio(nrgb, mask); + return ((pure - negative) / ratio); + case 3: case 5: case 6: - pure /= 2; - break; - case 7: - return pure; - case 0: - return -negative; + pure = (prgb[0] + prgb[1] + prgb[2])/2; + negative = nrgb[0] + nrgb[1] + nrgb[2]; + ratio = 1 + pure * color_ratio(prgb, mask); + return ((pure - negative) * ratio); } - /* return our color's ratio */ - return negative > 0 ? pure / negative : pure; + pure = prgb[0] + prgb[1] + prgb[2]; + negative = nrgb[0] + nrgb[1] + nrgb[2]; + return pure - negative; } /* create a color node, and add it to the list */ @@ -101,11 +133,11 @@ color_new(char *hex, uint8_t mask) new = malloc(sizeof(struct color_t)); if (new == NULL) - return; + return NULL; strncpy(new->hex, hex, 8); hex2rgb(hex, new->rgb); - new->val = color_dominant(new->rgb, mask); + new->val = color_dominant(new->rgb, mask); return new; } @@ -119,7 +151,6 @@ color_new(char *hex, uint8_t mask) struct color_t * color_sort(struct color_t *cur, struct color_t *new, uint8_t mask) { - int newval; if (cur == NULL) { new->next = NULL; } else { @@ -142,34 +173,27 @@ color_print(struct color_t *node) { struct color_t *tmp = NULL; for (tmp=node; tmp; tmp=tmp->next) { - printf("%s\t", tmp->hex); - printf("%d,%d,%d\t", tmp->rgb[0], tmp->rgb[1], tmp->rgb[2]); - printf("%f\n", tmp->val); + printf("%s\t%d,%d,%d\t%f\n", + tmp->hex, + tmp->rgb[0], + tmp->rgb[1], + tmp->rgb[2], + tmp->val ); } } int main(int argc, char *argv[]) { - int rgb[3]; char hex[8]; uint8_t mask = 7; /* print whitest by default */ if (argc > 1) { - switch (argv[1][0]) { - case 'k': mask = 0; break; - case 'b': mask = 1; break; - case 'g': mask = 2; break; - case 'c': mask = 3; break; - case 'r': mask = 4; break; - case 'm': mask = 5; break; - case 'y': mask = 6; break; - case 'w': mask = 7; break; - default: - usage(argv[0]); - return 1; - } + if (strncmp(argv[1], "-h", 2) == 0) + usage(argv[0]); + else + mask = atoi(argv[1]); } while (fgets(hex, 8, stdin)) {