color.c
2584 bytes
1/* Copyright 2017 Jason Williams
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include "color.h"
18#include "led_tables.h"
19#include "progmem.h"
20#include "util.h"
21
22rgb_t hsv_to_rgb_impl(hsv_t hsv, bool use_cie) {
23 rgb_t rgb;
24 uint8_t region, remainder, p, q, t;
25 uint16_t h, s, v;
26
27 if (hsv.s == 0) {
28#ifdef USE_CIE1931_CURVE
29 if (use_cie) {
30 rgb.r = rgb.g = rgb.b = pgm_read_byte(&CIE1931_CURVE[hsv.v]);
31 } else {
32 rgb.r = hsv.v;
33 rgb.g = hsv.v;
34 rgb.b = hsv.v;
35 }
36#else
37 rgb.r = hsv.v;
38 rgb.g = hsv.v;
39 rgb.b = hsv.v;
40#endif
41 return rgb;
42 }
43
44 h = hsv.h;
45 s = hsv.s;
46#ifdef USE_CIE1931_CURVE
47 if (use_cie) {
48 v = pgm_read_byte(&CIE1931_CURVE[hsv.v]);
49 } else {
50 v = hsv.v;
51 }
52#else
53 v = hsv.v;
54#endif
55
56 region = h * 6 / 255;
57 remainder = (h * 2 - region * 85) * 3;
58
59 p = (v * (255 - s)) >> 8;
60 q = (v * (255 - ((s * remainder) >> 8))) >> 8;
61 t = (v * (255 - ((s * (255 - remainder)) >> 8))) >> 8;
62
63 switch (region) {
64 case 6:
65 case 0:
66 rgb.r = v;
67 rgb.g = t;
68 rgb.b = p;
69 break;
70 case 1:
71 rgb.r = q;
72 rgb.g = v;
73 rgb.b = p;
74 break;
75 case 2:
76 rgb.r = p;
77 rgb.g = v;
78 rgb.b = t;
79 break;
80 case 3:
81 rgb.r = p;
82 rgb.g = q;
83 rgb.b = v;
84 break;
85 case 4:
86 rgb.r = t;
87 rgb.g = p;
88 rgb.b = v;
89 break;
90 default:
91 rgb.r = v;
92 rgb.g = p;
93 rgb.b = q;
94 break;
95 }
96
97 return rgb;
98}
99
100rgb_t hsv_to_rgb(hsv_t hsv) {
101#ifdef USE_CIE1931_CURVE
102 return hsv_to_rgb_impl(hsv, true);
103#else
104 return hsv_to_rgb_impl(hsv, false);
105#endif
106}
107
108rgb_t hsv_to_rgb_nocie(hsv_t hsv) {
109 return hsv_to_rgb_impl(hsv, false);
110}