FastLED 3.9.15
Loading...
Searching...
No Matches
five_bit_hd_gamma.h
Go to the documentation of this file.
1
3
4#pragma once
5
6#include "fl/gamma.h"
7#include "fl/int.h"
8#include "fl/math.h"
9
10#include "crgb.h"
11#include "lib8tion/scale8.h"
12
13namespace fl {
14
19
20// Applies gamma correction for the RGBV(8, 8, 8, 5) color space, where
21// the last byte is the brightness byte at 5 bits.
22// To override this five_bit_hd_gamma_bitshift you'll need to define
23// FASTLED_FIVE_BIT_HD_BITSHIFT_FUNCTION_OVERRIDE in your build settings
24// then define the function anywhere in your project.
25// Example:
26// FASTLED_NAMESPACE_BEGIN
27// void five_bit_hd_gamma_bitshift(
28// fl::u8 r8, fl::u8 g8, fl::u8 b8,
29// fl::u8 r8_scale, fl::u8 g8_scale, fl::u8 b8_scale,
30// fl::u8* out_r8,
31// fl::u8* out_g8,
32// fl::u8* out_b8,
33// fl::u8* out_power_5bit) {
34// cout << "hello world\n";
35// }
36// FASTLED_NAMESPACE_END
37
38// Force push
39
41 fl::u8 global_brightness,
42 CRGB *out_colors,
43 fl::u8 *out_power_5bit);
44
45// Exposed for testing.
46void five_bit_bitshift(u16 r16, u16 g16, u16 b16, fl::u8 brightness, CRGB *out,
47 fl::u8 *out_power_5bit);
48
49#ifdef FASTLED_FIVE_BIT_HD_BITSHIFT_FUNCTION_OVERRIDE
50// This function is located somewhere else in your project, so it's declared
51// extern here.
52extern void five_bit_hd_gamma_bitshift(CRGB colors, CRGB colors_scale,
53 fl::u8 global_brightness,
54 CRGB *out_colors,
55 fl::u8 *out_power_5bit);
56#else
57inline void five_bit_hd_gamma_bitshift(CRGB colors, CRGB colors_scale,
58 fl::u8 global_brightness,
59 CRGB *out_colors,
60 fl::u8 *out_power_5bit) {
62 colors, colors_scale, global_brightness, out_colors, out_power_5bit);
63}
64#endif // FASTLED_FIVE_BIT_HD_BITSHIFT_FUNCTION_OVERRIDE
65
66// Simple gamma correction function that converts from
67// 8-bit color component and converts it to gamma corrected 16-bit
68// color component. Fast and no memory overhead!
69// To override this function you'll need to define
70// FASTLED_FIVE_BIT_HD_GAMMA_BITSHIFT_FUNCTION_OVERRIDE in your build settings
71// and then define your own version anywhere in your project. Example:
72// FASTLED_NAMESPACE_BEGIN
73// void five_bit_hd_gamma_function(
74// fl::u8 r8, fl::u8 g8, fl::u8 b8,
75// u16* r16, u16* g16, u16* b16) {
76// cout << "hello world\n";
77// }
78// FASTLED_NAMESPACE_END
79#ifdef FASTLED_FIVE_BIT_HD_GAMMA_FUNCTION_OVERRIDE
80// This function is located somewhere else in your project, so it's declared
81// extern here.
82extern void five_bit_hd_gamma_function(CRGB color, u16 *r16, u16 *g16,
83 u16 *b16);
84#else
85inline void five_bit_hd_gamma_function(CRGB color, u16 *r16, u16 *g16,
86 u16 *b16) {
87
88 gamma16(color, r16, g16, b16);
89}
90#endif // FASTLED_FIVE_BIT_HD_GAMMA_FUNCTION_OVERRIDE
91
93 CRGB colors, CRGB colors_scale, fl::u8 global_brightness, CRGB *out_colors,
94 fl::u8 *out_power_5bit) {
95
96 if (global_brightness == 0) {
97 *out_colors = CRGB(0, 0, 0);
98 *out_power_5bit = 0;
99 return;
100 }
101
102 // Step 1: Gamma Correction
103 u16 r16, g16, b16;
104 five_bit_hd_gamma_function(colors, &r16, &g16, &b16);
105
106 // Step 2: Color correction step comes after gamma correction. These values
107 // are assumed to be be relatively close to 255.
108 if (colors_scale.r != 0xff) {
109 r16 = scale16by8(r16, colors_scale.r);
110 }
111 if (colors_scale.g != 0xff) {
112 g16 = scale16by8(g16, colors_scale.g);
113 }
114 if (colors_scale.b != 0xff) {
115 b16 = scale16by8(b16, colors_scale.b);
116 }
117
118 five_bit_bitshift(r16, g16, b16, global_brightness, out_colors,
119 out_power_5bit);
120}
121
122// Since the return value wasn't used, it has been omitted.
123// It's not clear what scale brightness is, or how it is to be applied,
124// so we assume 8 bits applied over the given rgb values.
125inline void five_bit_bitshift(uint16_t r16, uint16_t g16, uint16_t b16,
126 uint8_t brightness, CRGB *out,
127 uint8_t *out_power_5bit) {
128
129 // NEW in 3.10.2: A new closed form solution has been found!
130 // Thank you https://github.com/gwgill!
131 // It's okay if you don't know how this works, few do, but it tests
132 // very well and is better than the old iterative approach which had
133 // bad quantization issues (sudden jumps in brightness in certain intervals).
134
135 // ix/31 * 255/65536 * 256 scaling factors, valid for indexes 1..31
136 static uint32_t bright_scale[32] = {
137 0, 2023680, 1011840, 674560, 505920, 404736, 337280, 289097,
138 252960, 224853, 202368, 183971, 168640, 155668, 144549, 134912,
139 126480, 119040, 112427, 106509, 101184, 96366, 91985, 87986,
140 84320, 80947, 77834, 74951, 72274, 69782, 67456, 65280};
141
142 auto max3 = [](u16 a, u16 b, u16 c) { return fl_max(fl_max(a, b), c); };
143
144
145 if (brightness == 0) {
146 *out = CRGB(0, 0, 0);
147 *out_power_5bit = 0;
148 return;
149 }
150 if (r16 == 0 && g16 == 0 && b16 == 0) {
151 *out = CRGB(0, 0, 0);
152 *out_power_5bit = (brightness <= 31) ? brightness : 31;
153 return;
154 }
155
156 uint8_t r8 = 0, g8 = 0, b8 = 0;
157
158 // Apply any brightness setting (we assume brightness is 0..255)
159 if (brightness != 0xff) {
160 r16 = scale16by8(r16, brightness);
161 g16 = scale16by8(g16, brightness);
162 b16 = scale16by8(b16, brightness);
163 }
164
165 // Locate the largest value to set the brightness/scale factor
166 uint16_t scale = max3(r16, g16, b16);
167
168 if (scale == 0) {
169 *out = CRGB(0, 0, 0);
170 *out_power_5bit = 0;
171 return;
172 } else {
173 uint32_t scalef;
174
175 // Compute 5 bit quantized scale that is at or above the maximum value.
176 scale = (scale + (2047 - (scale >> 5))) >> 11;
177
178 // Adjust the 16 bit values to account for the scale, then round to 8
179 // bits
180 scalef = bright_scale[scale];
181 r8 = (r16 * scalef + 0x808000) >> 24;
182 g8 = (g16 * scalef + 0x808000) >> 24;
183 b8 = (b16 * scalef + 0x808000) >> 24;
184
185 *out = CRGB(r8, g8, b8);
186 *out_power_5bit = static_cast<uint8_t>(scale);
187 return;
188 }
189}
190
191} // namespace fl
uint16_t scale
Definition Noise.ino:74
UISlider brightness("Brightness", 128, 0, 255, 1)
Defines the red, green, and blue (RGB) pixel struct.
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:478
unsigned char u8
Definition int.h:17
void five_bit_hd_gamma_bitshift(CRGB colors, CRGB colors_scale, fl::u8 global_brightness, CRGB *out_colors, fl::u8 *out_power_5bit)
FiveBitGammaCorrectionMode
@ kFiveBitGammaCorrectionMode_Null
@ kFiveBitGammaCorrectionMode_BitShift
void gamma16(const CRGB &rgb, u16 *r16, u16 *g16, u16 *b16)
Definition gamma.h:13
common_type_t< T, U > fl_max(T a, U b)
Definition math_macros.h:29
void five_bit_hd_gamma_function(CRGB color, u16 *r16, u16 *g16, u16 *b16)
void five_bit_bitshift(u16 r16, u16 g16, u16 b16, fl::u8 brightness, CRGB *out, fl::u8 *out_power_5bit)
void internal_builtin_five_bit_hd_gamma_bitshift(CRGB colors, CRGB colors_scale, fl::u8 global_brightness, CRGB *out_colors, fl::u8 *out_power_5bit)
IMPORTANT!
Definition crgb.h:20
Fast, efficient 8-bit scaling functions specifically designed for high-performance LED programming.
Representation of an RGB pixel (Red, Green, Blue)
Definition crgb.h:86