FastLED 3.9.7
Loading...
Searching...
No Matches
detail.h
1#pragma once
2
3#include <stdint.h>
4
5
6inline uint32_t Adafruit_DotStar_ColorHSV(uint16_t hue, uint8_t sat, uint8_t val) {
7
8 uint8_t r, g, b;
9
10 // Remap 0-65535 to 0-1529. Pure red is CENTERED on the 64K rollover;
11 // 0 is not the start of pure red, but the midpoint...a few values above
12 // zero and a few below 65536 all yield pure red (similarly, 32768 is the
13 // midpoint, not start, of pure cyan). The 8-bit RGB hexcone (256 values
14 // each for red, green, blue) really only allows for 1530 distinct hues
15 // (not 1536, more on that below), but the full unsigned 16-bit type was
16 // chosen for hue so that one's code can easily handle a contiguous color
17 // wheel by allowing hue to roll over in either direction.
18 hue = (hue * 1530L + 32768) / 65536;
19 // Because red is centered on the rollover point (the +32768 above,
20 // essentially a fixed-point +0.5), the above actually yields 0 to 1530,
21 // where 0 and 1530 would yield the same thing. Rather than apply a
22 // costly modulo operator, 1530 is handled as a special case below.
23
24 // So you'd think that the color "hexcone" (the thing that ramps from
25 // pure red, to pure yellow, to pure green and so forth back to red,
26 // yielding six slices), and with each color component having 256
27 // possible values (0-255), might have 1536 possible items (6*256),
28 // but in reality there's 1530. This is because the last element in
29 // each 256-element slice is equal to the first element of the next
30 // slice, and keeping those in there this would create small
31 // discontinuities in the color wheel. So the last element of each
32 // slice is dropped...we regard only elements 0-254, with item 255
33 // being picked up as element 0 of the next slice. Like this:
34 // Red to not-quite-pure-yellow is: 255, 0, 0 to 255, 254, 0
35 // Pure yellow to not-quite-pure-green is: 255, 255, 0 to 1, 255, 0
36 // Pure green to not-quite-pure-cyan is: 0, 255, 0 to 0, 255, 254
37 // and so forth. Hence, 1530 distinct hues (0 to 1529), and hence why
38 // the constants below are not the multiples of 256 you might expect.
39
40 // Convert hue to R,G,B (nested ifs faster than divide+mod+switch):
41 if (hue < 510) { // Red to Green-1
42 b = 0;
43 if (hue < 255) { // Red to Yellow-1
44 r = 255;
45 g = hue; // g = 0 to 254
46 } else { // Yellow to Green-1
47 r = 510 - hue; // r = 255 to 1
48 g = 255;
49 }
50 } else if (hue < 1020) { // Green to Blue-1
51 r = 0;
52 if (hue < 765) { // Green to Cyan-1
53 g = 255;
54 b = hue - 510; // b = 0 to 254
55 } else { // Cyan to Blue-1
56 g = 1020 - hue; // g = 255 to 1
57 b = 255;
58 }
59 } else if (hue < 1530) { // Blue to Red-1
60 g = 0;
61 if (hue < 1275) { // Blue to Magenta-1
62 r = hue - 1020; // r = 0 to 254
63 b = 255;
64 } else { // Magenta to Red-1
65 r = 255;
66 b = 1530 - hue; // b = 255 to 1
67 }
68 } else { // Last 0.5 Red (quicker than % operator)
69 r = 255;
70 g = b = 0;
71 }
72
73 // Apply saturation and value to R,G,B, pack into 32-bit result:
74 uint32_t v1 = 1 + val; // 1 to 256; allows >>8 instead of /255
75 uint16_t s1 = 1 + sat; // 1 to 256; same reason
76 uint8_t s2 = 255 - sat; // 255 to 0
77 return ((((((r * s1) >> 8) + s2) * v1) & 0xff00) << 8) |
78 (((((g * s1) >> 8) + s2) * v1) & 0xff00) |
79 (((((b * s1) >> 8) + s2) * v1) >> 8);
80}