colors

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

commit fe59e379d1733e8ab4c2d0a694a4cbb1ef596e91
parent 554aa12cce86d7de6673b76cf18a64e87047e2ac
Author: z3bra <willyatmailoodotorg>
Date:   Tue,  6 Oct 2015 00:01:45 +0200

hexsort: sort colors by dominant color

This takes a color as argument (eg, 'g' for green), and will sort
colors (formatted as #xxxxxx) from the "most green" to the "most
magenta" (negative of green).

This works by turning hexcode into RGB arrays, and sort them by "score"
calculated as (if sorting by green value):

    green_val / ((red_val + blue_val)/2)

Diffstat:
Abin/hexsort.c | 165+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 165 insertions(+), 0 deletions(-)

diff --git a/bin/hexsort.c b/bin/hexsort.c @@ -0,0 +1,165 @@ +/* See LICENSE file for copyright and license details. */ +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <unistd.h> +#include <string.h> + +struct color_t { + char hex[8]; + int rgb[3]; + double val; + struct color_t *next; +}; + +struct color_t *head = NULL; +struct color_t **sorted = NULL; +struct color_t **messed = NULL; + +void +usage(char *argv0) { + fprintf(stderr, "usage: %s [kbgcrmyw]\n", argv0); +} + +/* + * converts an hexadecimal representation of a color into a 3 dimensionnal + * array (RGB decomposition) + */ +void +hex2rgb(char *hex, int *rgb) +{ + int i; + char tmp[2]; + for (i = 0; i < 3; i++) { + strncpy(tmp, hex + 1 + 2 * i, 2); + rgb[i] = strtol(tmp, NULL, 16); + } +} + +double +color_dominant(int *rgb, uint8_t mask) +{ + double pure = 0, negative = 0; + + /* 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); + + /* 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); + + /* + * calculate the average of either pure or negative color depending on + * the mask's value + */ + switch (mask) { + case 1: + case 2: + case 4: + negative /= 2; + break; + case 3: + case 5: + case 6: + pure /= 2; + break; + case 7: + return pure; + case 0: + return -negative; + } + + /* return our color's ratio */ + return negative > 0 ? pure / negative : pure; +} + +/* create a color node, and add it to the list */ +struct color_t * +color_new(char *hex, uint8_t mask) +{ + struct color_t *new = NULL; + + new = malloc(sizeof(struct color_t)); + if (new == NULL) + return; + + strncpy(new->hex, hex, 8); + hex2rgb(hex, new->rgb); + new->val = color_dominant(new->rgb, mask); + return new; +} + +/* + * Takes an unsorted list of colors as an argument, and sort it depending on + * the mask value. + * The mask is a 3 bit representation of the RGB composition you want to use to + * sort colors, eg mask 011 will return the brightess cyan first, and darkest + * red last. + */ +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 { + if (new->val <= cur->val) { + cur->next = color_sort(cur->next, new, mask); + return cur; + } else { + new->next = cur; + } + } + return new; +} + +/* + * print the content of our list in the format: + * <HEX> <RGB> <SCORE> + */ +void +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); + } +} + +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; + } + } + + while (fgets(hex, 8, stdin)) { + if (hex[0] == '#') { + head = color_sort(head, color_new(hex, mask), mask); + } + } + color_print(head); + return 0; +}