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 68b7a8e7640e3445da89fa3d573e282791c9d57c
parent 92ca84cdf5c13181a2d54b3514d021d090cbc39e
Author: Pollux <pollux@pollux.codes>
Date:   Sun, 20 Jul 2025 00:13:15 -0500

feat: Generate colorscheme and output

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

Diffstat:
Mmorph.c | 71+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
1 file changed, 63 insertions(+), 8 deletions(-)

diff --git a/morph.c b/morph.c @@ -8,11 +8,17 @@ #include <Imlib2.h> -#define PRIMARY_COLOR_COUNT 32 +#define PRIMARY_COLOR_COUNT 128 +#define PI 3.1415926535 #define min(a, b) ((a) < (b) ? (a) : (b)) #define max(a, b) ((a) > (b) ? (a) : (b)) +#define TARGET_COLOR(name, cr, cg, cb, cl) \ + color = match_color(palette, palette_weights, PRIMARY_COLOR_COUNT*4, rgb_to_lab((col_rgb_t){ .r = cr, .g = cg, .b = cb}));\ + color.l = cl;\ + export_color(name, color); + /// Type to represent a color in the srgb color space. Use the functions /// rgb_to_lab and lab_to_rgb to convert between different color spaces. typedef struct { @@ -300,6 +306,37 @@ hue_shift(col_lab_t in, float angle) { return out; } +col_lab_t +match_color(col_lab_t *palette, float *palette_weights, size_t palette_size, col_lab_t target_color) { + + float best_score = 0; + col_lab_t best_color; + + for(int c = 0; c < palette_size; c++) { + col_lab_t palette_color = palette[c]; + float color_distance = sqrtf((palette_color.l - target_color.l)*(palette_color.l - target_color.l) + (palette_color.a - target_color.a)*(palette_color.a - target_color.a) + (palette_color.b - target_color.b)*(palette_color.b - target_color.b)); + float score = palette_weights[c] / color_distance; + + if(score > best_score) { + best_score = score; + best_color = palette_color; + } + } + + return best_color; +} + +void +export_color(const char* name, col_lab_t color) { + col_rgb_t rgb = lab_to_rgb(color); + + int red = min(1, max(0, rgb.r)) * 255; + int green = min(1, max(0, rgb.g)) * 255; + int blue = min(1, max(0, rgb.b)) * 255; + + printf("%s: #%02x%02x%02x\n", name, red, green, blue); +} + int main(int argc, char **argv) { @@ -326,17 +363,35 @@ main(int argc, char **argv) { for(int c = 0; c < PRIMARY_COLOR_COUNT; c++) { palette[4 * c] = primary_colors[c]; palette_weights[4 * c] = 1; - palette[4 * c + 1] = hue_shift(primary_colors[c], M_PI); + palette[4 * c + 1] = hue_shift(primary_colors[c], PI); palette_weights[4 * c] = 0.5; - palette[4 * c + 2] = hue_shift(primary_colors[c], M_PI / 6); + palette[4 * c + 2] = hue_shift(primary_colors[c], PI / 6); palette_weights[4 * c] = 0.3; - palette[4 * c + 3] = hue_shift(primary_colors[c], -M_PI / 6); + palette[4 * c + 3] = hue_shift(primary_colors[c], -PI / 6); palette_weights[4 * c] = 0.3; } - - // TODO: Match colors with target colors - - // TODO: Export colors + + col_lab_t color; + + TARGET_COLOR("st.color0" , 0, 0, 0, 0.2) + TARGET_COLOR("st.color1" , 1, 0, 0, 0.7) + TARGET_COLOR("st.color2" , 0, 1, 0, 0.7) + TARGET_COLOR("st.color3" , 1, 1, 0, 0.7) + TARGET_COLOR("st.color4" , 0, 0, 1, 0.7) + TARGET_COLOR("st.color5" , 1, 0, 1, 0.7) + TARGET_COLOR("st.color6" , 0, 1, 1, 0.7) + TARGET_COLOR("st.color7" , 0, 0, 0, 0.9) + TARGET_COLOR("st.color8" , 0, 0, 0, 0.4) + TARGET_COLOR("st.color9" , 1, 0, 0, 0.8) + TARGET_COLOR("st.color10", 0, 1, 0, 0.8) + TARGET_COLOR("st.color11", 1, 1, 0, 0.8) + TARGET_COLOR("st.color12", 0, 0, 1, 0.8) + TARGET_COLOR("st.color13", 1, 0, 1, 0.8) + TARGET_COLOR("st.color14", 0, 1, 1, 0.8) + TARGET_COLOR("st.color15", 0, 0, 0, 1.0) + + TARGET_COLOR("st.surface", 0, 0, 0, 0.1) + TARGET_COLOR("st.on_surface", 0, 0, 0, 1.0) free(image_pixels); free(image_pixels_lab);