diff options
Diffstat (limited to 'jack/color.c')
-rw-r--r-- | jack/color.c | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/jack/color.c b/jack/color.c new file mode 100644 index 0000000..9728d99 --- /dev/null +++ b/jack/color.c @@ -0,0 +1,140 @@ +// Copyright 2025 [email protected] +// SPDX-License-Identifier: GPL-2.0-or-later +#include "color.h" +#include <lib/lib8tion/lib8tion.h> + +#define K255 255 +#define K171 171 +#define K170 170 +#define K85 85 + +// Adapted from https://fastled.io/docs/hsv2rgb_8cpp_source.html +// void hsv2rgb_rainbow() function +RGB rgb_matrix_hsv_to_rgb(const HSV hsv) { + // Yellow has a higher inherent brightness than + // any other color; 'pure' yellow is perceived to + // be 93% as bright as white. In order to make + // yellow appear the correct relative brightness, + // it has to be rendered brighter than all other + // colors. + const uint8_t hue = hsv.h; + const uint8_t sat = hsv.s; + uint8_t val = hsv.v; + + // offset8 = (hue [0..31]) * 8 + uint8_t offset8 = hue & 0x1F; + offset8 <<= 3; + + uint8_t third = scale8(offset8, (256 / 3)); // max = 85 + uint8_t r, g, b; + if (!(hue & 0x80)) { + // 0XX + if (!(hue & 0x40)) { + // 00X + // section 0-1 + if (!(hue & 0x20)) { + // 000 + // case 0: // R -> O + r = K255 - third; + g = third; + b = 0; + } else { + // 001 + // case 1: // O -> Y + r = K171; + g = K85 + third; + b = 0; + } + } else { + // 01X + // section 2-3 + if (!(hue & 0x20)) { + // 010 + // case 2: // Y -> G + // uint8_t twothirds = (third << 1); + uint8_t twothirds = scale8(offset8, ((256 * 2) / 3)); // max=170 + r = K171 - twothirds; + g = K170 + third; + b = 0; + } else { + // 011 + // case 3: // G -> A + r = 0; + g = K255 - third; + b = third; + } + } + } else { + // section 4-7 + // 1XX + if (!(hue & 0x40)) { + // 10X + if (!(hue & 0x20)) { + // 100 + // case 4: // A -> B + r = 0; + // uint8_t twothirds = (third << 1); + uint8_t twothirds = scale8(offset8, ((256 * 2) / 3)); // max=170 + g = K171 - twothirds; // K170? + b = K85 + twothirds; + } else { + // 101 + // case 5: // B -> P + r = third; + g = 0; + b = K255 - third; + } + } else { + if (!(hue & 0x20)) { + // 110 + // case 6: // P -- K + r = K85 + third; + g = 0; + b = K171 - third; + } else { + // 111 + // case 7: // K -> R + r = K170 + third; + g = 0; + b = K85 - third; + } + } + } + // This is one of the good places to scale the green down, + // although the client can scale green down as well. + g >>= 1; + // Scale down colors if we're desaturated at all + // and add the brightness_floor to r, g, and b. + if (sat != 255) { + if (sat == 0) { + r = 255; + b = 255; + g = 255; + } else { + uint8_t desat = 255 - sat; + desat = scale8_video(desat, desat); + uint8_t satscale = 255 - desat; + r = scale8(r, satscale); + g = scale8(g, satscale); + b = scale8(b, satscale); + uint8_t brightness_floor = desat; + r += brightness_floor; + g += brightness_floor; + b += brightness_floor; + } + } + // Now scale everything down if we're at value < 255. + if (val != 255) { + val = scale8_video(val, val); + if (val == 0) { + r = 0; + g = 0; + b = 0; + } else { + r = scale8(r, val); + g = scale8(g, val); + b = scale8(b, val); + } + } + return (RGB){.r = r, .g = g, .b = b}; +} |