Fix HSL->RGB conversion

This commit is contained in:
Kuba Birecki 2021-12-04 17:13:40 +01:00
parent 2326f36e50
commit f50037dcbb

View file

@ -5,8 +5,24 @@
*/
#include <stdlib.h>
#include <zmk/animation.h>
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);
}
/**