commit b80c7fb1653faa2b4e2bf83b0c4b209afc33fc4a
parent 89be999289757f6a15bc78ca53e9cb5c95289794
Author: z3bra <willyatmailoodotorg>
Date: Tue, 6 Oct 2015 21:26:00 +0200
hexsort: rewrote algorithm from scratch
Diffstat:
A | bin/a.out | | | 0 | |
M | 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)) {