FastLED 3.9.15
Loading...
Searching...
No Matches
five_bit_hd_gamma.cpp
Go to the documentation of this file.
1
3
4#define FASTLED_INTERNAL 1
5#include "five_bit_hd_gamma.h"
6#include "FastLED.h"
7
8#include "fastled_progmem.h"
9#include "lib8tion/intmap.h"
10#include "lib8tion/math8.h"
11#include "lib8tion/scale8.h"
13#include "fl/namespace.h"
14
15
16// Author: Zach Vorhies
17namespace fl {
18
19namespace {
20template <typename T> T mymax(T a, T b) { return (a > b) ? a : b; }
21
22template <typename T> T max3(T a, T b, T c) { return mymax(mymax(a, b), c); }
23
24} // namespace
25
26#ifndef FASTLED_FIVE_BIT_HD_GAMMA_FUNCTION_2_8
27// Fast a memory efficient gamma=2 function.
28void five_bit_hd_gamma_function(CRGB color, uint16_t *r16, uint16_t *g16,
29 uint16_t *b16) {
30 uint16_t _r16 = map8_to_16(color.r);
31 uint16_t _g16 = map8_to_16(color.g);
32 uint16_t _b16 = map8_to_16(color.b);
33 *r16 = scale16by8(_r16, color.r);
34 *g16 = scale16by8(_g16, color.g);
35 *b16 = scale16by8(_b16, color.b);
36}
37#else
38// Using look up table for gamma16 correction at power of 2.8
39static const uint16_t PROGMEM _gamma_2_8[256] = {
40 0, 0, 0, 1, 1, 2, 4, 6, 8, 11, 14,
41 18, 23, 29, 35, 41, 49, 57, 67, 77, 88, 99,
42 112, 126, 141, 156, 173, 191, 210, 230, 251, 274, 297,
43 322, 348, 375, 404, 433, 464, 497, 531, 566, 602, 640,
44 680, 721, 763, 807, 853, 899, 948, 998, 1050, 1103, 1158,
45 1215, 1273, 1333, 1394, 1458, 1523, 1590, 1658, 1729, 1801, 1875,
46 1951, 2029, 2109, 2190, 2274, 2359, 2446, 2536, 2627, 2720, 2816,
47 2913, 3012, 3114, 3217, 3323, 3431, 3541, 3653, 3767, 3883, 4001,
48 4122, 4245, 4370, 4498, 4627, 4759, 4893, 5030, 5169, 5310, 5453,
49 5599, 5747, 5898, 6051, 6206, 6364, 6525, 6688, 6853, 7021, 7191,
50 7364, 7539, 7717, 7897, 8080, 8266, 8454, 8645, 8838, 9034, 9233,
51 9434, 9638, 9845, 10055, 10267, 10482, 10699, 10920, 11143, 11369, 11598,
52 11829, 12064, 12301, 12541, 12784, 13030, 13279, 13530, 13785, 14042, 14303,
53 14566, 14832, 15102, 15374, 15649, 15928, 16209, 16493, 16781, 17071, 17365,
54 17661, 17961, 18264, 18570, 18879, 19191, 19507, 19825, 20147, 20472, 20800,
55 21131, 21466, 21804, 22145, 22489, 22837, 23188, 23542, 23899, 24260, 24625,
56 24992, 25363, 25737, 26115, 26496, 26880, 27268, 27659, 28054, 28452, 28854,
57 29259, 29667, 30079, 30495, 30914, 31337, 31763, 32192, 32626, 33062, 33503,
58 33947, 34394, 34846, 35300, 35759, 36221, 36687, 37156, 37629, 38106, 38586,
59 39071, 39558, 40050, 40545, 41045, 41547, 42054, 42565, 43079, 43597, 44119,
60 44644, 45174, 45707, 46245, 46786, 47331, 47880, 48432, 48989, 49550, 50114,
61 50683, 51255, 51832, 52412, 52996, 53585, 54177, 54773, 55374, 55978, 56587,
62 57199, 57816, 58436, 59061, 59690, 60323, 60960, 61601, 62246, 62896, 63549,
63 64207, 64869, 65535};
64
65void five_bit_hd_gamma_function(CRGB rgb, uint16_t *r16, uint16_t *g16,
66 uint16_t *b16) {
67 *r16 = _gamma_2_8[rgb.r];
68 *g16 = _gamma_2_8[rgb.g];
69 *b16 = _gamma_2_8[rgb.b];
70}
71#endif // FASTLED_FIVE_BIT_HD_GAMMA_FUNCTION_2_8
72
73uint8_t five_bit_bitshift(uint16_t r16, uint16_t g16, uint16_t b16,
74 uint8_t brightness, CRGB *out, uint8_t *out_power_5bit) {
75 if (brightness == 0) {
76 *out = CRGB(0, 0, 0);
77 *out_power_5bit = 0;
78 return 0;
79 }
80 if (r16 == 0 && g16 == 0 && b16 == 0) {
81 *out = CRGB(0, 0, 0);
82 *out_power_5bit = (brightness <= 31) ? brightness : 31;
83 return brightness;
84 }
85
86 // Note: One day someone smarter than me will come along and invent a closed
87 // form solution for this. However, the numerical method works extremely
88 // well and has been optimized to avoid division performance penalties as
89 // much as possible.
90
91 // Step 1: Initialize brightness
92 static const uint8_t kStartBrightness = 0b00010000;
93 uint8_t v5 = kStartBrightness;
94 // Step 2: Boost brightness by swapping power with the driver brightness.
96
97 // Step 3: Boost brightness of the color channels by swapping power with the
98 // driver brightness.
99 uint16_t max_component = max3(r16, g16, b16);
100 // five_bit_color_bitshift(&r16, &g16, &b16, &v5);
101 uint8_t shifts = brightness_bitshifter16(&v5, &max_component, 4, 2);
102 if (shifts) {
103 r16 = r16 << shifts;
104 g16 = g16 << shifts;
105 b16 = b16 << shifts;
106 }
107
108 // Step 4: scale by final brightness factor.
109 if (brightness != 0xff) {
110 r16 = scale16by8(r16, brightness);
111 g16 = scale16by8(g16, brightness);
112 b16 = scale16by8(b16, brightness);
113 }
114
115
116 // brighten hardware brightness by turning on low order bits
117 if (v5 > 1) {
118 // since v5 is a power of two, subtracting one will invert the leading bit
119 // and invert all the bits below it.
120 // Example: 0b00010000 -1 = 0b00001111
121 // So 0b00010000 | 0b00001111 = 0b00011111
122 v5 = v5 | (v5 - 1);
123 }
124 // Step 5: Convert back to 8-bit and output.
125 *out = CRGB(map16_to_8(r16), map16_to_8(g16), map16_to_8(b16));
126 *out_power_5bit = v5;
127 return brightness;
128}
129
131 uint8_t global_brightness,
132 CRGB *out_colors,
133 uint8_t *out_power_5bit) {
134
135 if (global_brightness == 0) {
136 *out_colors = CRGB(0, 0, 0);
137 *out_power_5bit = 0;
138 return;
139 }
140
141 // Step 1: Gamma Correction
142 uint16_t r16, g16, b16;
143 five_bit_hd_gamma_function(colors, &r16, &g16, &b16);
144
145 // Step 2: Color correction step comes after gamma correction. These values
146 // are assumed to be be relatively close to 255.
147 if (colors_scale.r != 0xff) {
148 r16 = scale16by8(r16, colors_scale.r);
149 }
150 if (colors_scale.g != 0xff) {
151 g16 = scale16by8(g16, colors_scale.g);
152 }
153 if (colors_scale.b != 0xff) {
154 b16 = scale16by8(b16, colors_scale.b);
155 }
156
157 five_bit_bitshift(r16, g16, b16, global_brightness, out_colors,
158 out_power_5bit);
159}
160
161} // namespace fl
central include file for FastLED, defines the CFastLED class/object
UISlider brightness("Brightness", 255, 0, 255, 1)
Defines brightness bitshifting functions.
Wrapper definitions to allow seamless use of PROGMEM in environments that have it.
Declares functions for five-bit gamma correction.
uint8_t brightness_bitshifter8(uint8_t *brightness_src, uint8_t *brightness_dst, uint8_t max_shifts)
uint8_t brightness_bitshifter16(uint8_t *brightness_src, uint16_t *brightness_dst, uint8_t max_shifts, uint8_t steps=2)
LIB8STATIC_ALWAYS_INLINE uint16_t scale16by8(uint16_t i, fract8 scale)
Scale a 16-bit unsigned value by an 8-bit value, which is treated as the numerator of a fraction whos...
Definition scale8.h:468
LIB8STATIC_ALWAYS_INLINE uint8_t map16_to_8(uint16_t x)
Definition intmap.h:31
LIB8STATIC_ALWAYS_INLINE uint16_t map8_to_16(uint8_t x)
Definition intmap.h:25
Defines integer mapping functions.
Fast, efficient 8-bit math functions specifically designed for high-performance LED programming.
Implements the FastLED namespace macros.
void __builtin_five_bit_hd_gamma_bitshift(CRGB colors, CRGB colors_scale, uint8_t global_brightness, CRGB *out_colors, uint8_t *out_power_5bit)
uint8_t five_bit_bitshift(uint16_t r16, uint16_t g16, uint16_t b16, uint8_t brightness, CRGB *out, uint8_t *out_power_5bit)
void five_bit_hd_gamma_function(CRGB color, uint16_t *r16, uint16_t *g16, uint16_t *b16)
Implements a simple red square effect for 2D LED grids.
Definition crgb.h:16
Fast, efficient 8-bit scaling functions specifically designed for high-performance LED programming.
Representation of an RGB pixel (Red, Green, Blue)
Definition crgb.h:54