From f50037dcbb47b54dc81bbacbff9c29d165119b11 Mon Sep 17 00:00:00 2001 From: Kuba Birecki Date: Sat, 4 Dec 2021 17:13:40 +0100 Subject: [PATCH] Fix HSL->RGB conversion --- app/src/animation/color.c | 44 +++++++++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 11 deletions(-) diff --git a/app/src/animation/color.c b/app/src/animation/color.c index 5681b667..53bec6e4 100644 --- a/app/src/animation/color.c +++ b/app/src/animation/color.c @@ -5,8 +5,24 @@ */ #include + #include +static float fmod(float a, float b) { + float mod = a < 0 ? -a : a; + float x = b < 0 ? -b : b; + + while (mod >= x) { + mod = mod - x; + } + + return a < 0 ? -mod : mod; +} + +static float fabs(float a) { + return a < 0 ? -a : a; +} + /** * HSL chosen over HSV/HSB as it shares the same parameters with LCh or HSLuv. * The latter color spaces could be interesting to experiment with because of their @@ -16,39 +32,45 @@ * Algorithm source: https://www.tlbx.app/color-converter */ void zmk_hsl_to_rgb(const struct zmk_color_hsl *hsl, struct zmk_color_rgb *rgb) { - // float a = hsl->h / 60; - uint8_t a = hsl->h / 60; - float chroma = hsl->s * (1 - abs(2 * hsl->l - 1)); - // I think 'a' actually needs to be a float here or this doesn't make sense. - // If uint, possible values are: (0,1), if float: (0...1) - float x = chroma * (1 - abs(a % 2 - 1)); - float m = hsl->l - chroma / 2; + float s = (float) hsl->s / 100; + float l = (float) hsl->l / 100; - switch (a) { + float a = (float) hsl->h / 60; + float chroma = s * (1 - fabs(2 * l - 1)); + float x = chroma * (1 - fabs(fmod(a, 2) - 1)); + float m = l - chroma / 2; + + switch ((uint8_t) a % 6) { case 0: rgb->r = m + chroma; rgb->g = m + x; rgb->b = m; + break; case 1: rgb->r = m + x; rgb->g = m + chroma; rgb->b = m; + break; case 2: rgb->r = m; rgb->g = m + chroma; rgb->b = m + x; + break; case 3: rgb->r = m; rgb->g = m + x; rgb->b = m + chroma; + break; case 4: rgb->r = m + x; rgb->g = m; rgb->b = m + chroma; + break; case 5: rgb->r = m + chroma; rgb->g = m; rgb->b = m + x; + break; } } @@ -56,9 +78,9 @@ void zmk_hsl_to_rgb(const struct zmk_color_hsl *hsl, struct zmk_color_rgb *rgb) * Converts ZMKs RGB (float) to Zephyr's led_rgb (uint8_t) format. */ void zmk_rgb_to_led_rgb(const struct zmk_color_rgb *rgb, struct led_rgb *led) { - led->r = rgb->r * 255; - led->g = rgb->g * 255; - led->b = rgb->b * 255; + led->r = (uint8_t) (rgb->r * 255); + led->g = (uint8_t) (rgb->g * 255); + led->b = (uint8_t) (rgb->b * 255); } /**