home | blog | art | now | git gpg | email | rss

morph

Generate xresources colors from an image.
git clone https://pollux.codes/git/morph.git
Log | Files | Refs | README | LICENSE
commit 6e53850c21f0ee6325b8267188592f34b7612071
parent 6f4565a9ed0e17dfb2a1ff0689594315796bd16d
Author: Pollux <pollux@pollux.codes>
Date:   Sun, 20 Jul 2025 22:55:40 -0500

docs: Document functions and add more TODOs

Signed-off-by: Pollux <pollux@pollux.codes>

Diffstat:
Mmorph.c | 19+++++++++++++++++--
1 file changed, 17 insertions(+), 2 deletions(-)

diff --git a/morph.c b/morph.c @@ -43,6 +43,7 @@ typedef struct { size_t len; } col_cluster_t; +/// Exit the program with an error message. void die(const char *fmt, ...) { va_list ap; @@ -60,6 +61,8 @@ die(const char *fmt, ...) { exit(1); } +/// Compare the luminances of the two given colors. Returns 1 if the first has +/// a larger luminance, returns -1 otherwise. int compare_l(const void *a, const void *b) { const col_lab_t *ca = (const col_lab_t *)a; @@ -72,6 +75,8 @@ compare_l(const void *a, const void *b) { } } +/// Compare the 'a' of the two given colors. Returns 1 if the first has a +/// larger 'a', returns -1 otherwise. int compare_a(const void *a, const void *b) { const col_lab_t *ca = (const col_lab_t *)a; @@ -84,6 +89,8 @@ compare_a(const void *a, const void *b) { } } +/// Compare the 'b' of the two given colors. Returns 1 if the first has a +/// larger 'b', returns -1 otherwise. int compare_b(const void *a, const void *b) { const col_lab_t *ca = (const col_lab_t *)a; @@ -96,6 +103,7 @@ compare_b(const void *a, const void *b) { } } +/// Returns the distance between the two given colors in the OkLab color space. float get_color_distance(const col_lab_t c1, const col_lab_t c2) { return sqrtf((c1.l - c2.l) * (c1.l - c2.l) + @@ -273,7 +281,7 @@ cluster_image_colors(col_lab_t *colors, int color_count, int cluster_count) { } } - // TODO OPTIMIZE: Replace with quickselect followed by partition + // TODO OPTIMIZE v1.0: Replace with quickselect followed by partition switch (largest_dimension) { case 0: @@ -300,7 +308,7 @@ cluster_image_colors(col_lab_t *colors, int color_count, int cluster_count) { clusters[largest_cluster].len /= 2; } - // TODO OPTIMIZE: Optimize this using quickselect + // TODO OPTIMIZE v1.0: Optimize this using quickselect for(int c = 0; c < cluster_count; c++) { @@ -325,6 +333,7 @@ cluster_image_colors(col_lab_t *colors, int color_count, int cluster_count) { return cluster_colors; } +/// Rotates the hue of the given Lab color by the given angle in radians. col_lab_t hue_shift(col_lab_t in, float angle) { @@ -340,6 +349,10 @@ hue_shift(col_lab_t in, float angle) { return out; } +/// Given a palette and a target color, finds the color in the palette closest +/// to the target color in Lab color space. The palette weights can be used to +/// biase the result towards specific colors; colors with larger weights are +/// more likely to be picked. col_lab_t match_color(col_lab_t *palette, float *palette_weights, size_t palette_size, col_lab_t target_color) { @@ -360,6 +373,7 @@ match_color(col_lab_t *palette, float *palette_weights, size_t palette_size, return best_color; } +/// Prints the given color in the X resources format, e.g. "name: #aabbcc" void export_color(const char *name, col_lab_t color) { @@ -390,6 +404,7 @@ main(int argc, char **argv) { col_lab_t color; + // TODO v1.0: Proper input argement handling. if(argc <= 1) die("No image provided.");