Implements 5bit hd gamma correction using the bit shift method for APA102 and SK9822 chipsets
This commit is contained in:
parent
a36b331703
commit
73192ff41b
@ -1,6 +1,10 @@
|
||||
#include "FastLED.h"
|
||||
#include "five_bit_hd_gamma.h"
|
||||
|
||||
#ifndef FASTLED_FIVE_BIT_HD_GAMMA_LOW_END_LINEAR_RAMP
|
||||
#define FASTLED_FIVE_BIT_HD_GAMMA_LOW_END_LINEAR_RAMP 1
|
||||
#endif
|
||||
|
||||
FASTLED_NAMESPACE_BEGIN
|
||||
|
||||
|
||||
@ -31,113 +35,81 @@ void five_bit_hd_gamma_bitshift(
|
||||
|
||||
uint16_t nominator = 1;
|
||||
uint16_t denominator = 1;
|
||||
const uint16_t r16_const = r16;
|
||||
const uint16_t g16_const = g16;
|
||||
const uint16_t b16_const = b16;
|
||||
const uint32_t r16_const = r16;
|
||||
const uint32_t g16_const = g16;
|
||||
const uint32_t b16_const = b16;
|
||||
|
||||
// Step 3: Bit Shifting Loop, can probably replaced with a
|
||||
// single pass bit-twiddling hack.
|
||||
do {
|
||||
{
|
||||
uint32_t next_r16 = r16 * 31 / 15;
|
||||
uint32_t next_g16 = g16 * 31 / 15;
|
||||
uint32_t next_b16 = b16 * 31 / 15;
|
||||
if (next_r16 > 0xffff) {
|
||||
break;
|
||||
}
|
||||
if (next_g16 > 0xffff) {
|
||||
break;
|
||||
}
|
||||
if (next_b16 > 0xffff) {
|
||||
break;
|
||||
}
|
||||
nominator = nominator * 31;
|
||||
denominator = denominator * 15;
|
||||
v8 = v8 >> 1;
|
||||
r16 = next_r16;
|
||||
g16 = next_g16;
|
||||
b16 = next_b16;
|
||||
// Note that to avoid slow divisions, we multiply the max_value
|
||||
// by the denominator.
|
||||
uint32_t max_value = 0xfffful * 15;
|
||||
if (r16_const * 31 > max_value) {
|
||||
break;
|
||||
}
|
||||
{
|
||||
uint32_t next_r16 = r16 * 15 / 7;
|
||||
uint32_t next_g16 = g16 * 15 / 7;
|
||||
uint32_t next_b16 = b16 * 15 / 7;
|
||||
if (next_r16 > 0xffff) {
|
||||
break;
|
||||
}
|
||||
if (next_g16 > 0xffff) {
|
||||
break;
|
||||
}
|
||||
if (next_b16 > 0xffff) {
|
||||
break;
|
||||
}
|
||||
nominator = nominator * 15;
|
||||
denominator = denominator * 7;
|
||||
v8 = v8 >> 1;
|
||||
r16 = next_r16;
|
||||
g16 = next_g16;
|
||||
b16 = next_b16;
|
||||
if (g16_const * 31 > max_value) {
|
||||
break;
|
||||
}
|
||||
{
|
||||
uint32_t next_r16 = r16 * 7 / 3;
|
||||
uint32_t next_g16 = g16 * 7 / 3;
|
||||
uint32_t next_b16 = b16 * 7 / 3;
|
||||
if (next_r16 > 0xffff) {
|
||||
break;
|
||||
}
|
||||
if (next_g16 > 0xffff) {
|
||||
break;
|
||||
}
|
||||
if (next_b16 > 0xffff) {
|
||||
break;
|
||||
}
|
||||
nominator = nominator * 7;
|
||||
denominator = denominator * 3;
|
||||
v8 = v8 >> 1;
|
||||
r16 = next_r16;
|
||||
g16 = next_g16;
|
||||
b16 = next_b16;
|
||||
if (b16_const * 31 > max_value) {
|
||||
break;
|
||||
}
|
||||
{
|
||||
uint32_t next_r16 = r16 * 3;
|
||||
uint32_t next_g16 = g16 * 3;
|
||||
uint32_t next_b16 = b16 * 3;
|
||||
if (next_r16 > 0xffff) {
|
||||
break;
|
||||
}
|
||||
if (next_g16 > 0xffff) {
|
||||
break;
|
||||
}
|
||||
if (next_b16 > 0xffff) {
|
||||
break;
|
||||
}
|
||||
nominator = nominator * 3;
|
||||
v8 = v8 >> 1;
|
||||
r16 = next_r16;
|
||||
g16 = next_g16;
|
||||
b16 = next_b16;
|
||||
nominator = 31;
|
||||
denominator = 15;
|
||||
v8 = 15;
|
||||
|
||||
max_value = 0xfffful * 15 * 7;
|
||||
if (r16_const * 31 * 15 > max_value) {
|
||||
break;
|
||||
}
|
||||
if (g16_const * 31 * 15 > max_value) {
|
||||
break;
|
||||
}
|
||||
if (b16_const * 31 * 15 > max_value) {
|
||||
break;
|
||||
}
|
||||
nominator = 31 * 15;
|
||||
denominator = 15 * 7;
|
||||
v8 = 7;
|
||||
|
||||
max_value = 0xfffful * 15 * 7 * 3;
|
||||
if (r16_const * 31 * 15 * 7 > max_value) {
|
||||
break;
|
||||
}
|
||||
if (g16_const * 31 * 15 * 7 > max_value) {
|
||||
break;
|
||||
}
|
||||
if (b16_const * 31 * 15 * 7 > max_value) {
|
||||
break;
|
||||
}
|
||||
nominator = 31 * 15 * 7;
|
||||
denominator = 15 * 7 * 3;
|
||||
v8 = 3;
|
||||
|
||||
max_value = 0xfffful * 15 * 7 * 3;
|
||||
if (r16_const * 31 * 15 * 7 * 3 > max_value) {
|
||||
break;
|
||||
}
|
||||
if (g16_const * 31 * 15 * 7 * 3 > max_value) {
|
||||
break;
|
||||
}
|
||||
if (b16_const * 31 * 15 * 7 * 3 > max_value) {
|
||||
break;
|
||||
}
|
||||
nominator = 31 * 15 * 7 * 3;
|
||||
v8 = 1;
|
||||
} while(false);
|
||||
|
||||
r16 = r16_const * nominator / denominator;
|
||||
g16 = g16_const * nominator / denominator;
|
||||
b16 = b16_const * nominator / denominator;
|
||||
// protect against overflow
|
||||
if (r16 > 0xffff) {
|
||||
r16 = 0xffff;
|
||||
}
|
||||
if (g16 > 0xffff) {
|
||||
g16 = 0xffff;
|
||||
}
|
||||
if (b16 > 0xffff) {
|
||||
b16 = 0xffff;
|
||||
}
|
||||
r16 = uint16_t(r16_const * nominator / denominator);
|
||||
g16 = uint16_t(g16_const * nominator / denominator);
|
||||
b16 = uint16_t(b16_const * nominator / denominator);
|
||||
|
||||
// Step 4: Conversion Back to 8-bit.
|
||||
uint8_t r8_final = (r8 == 255 && uint8_t(r16 >> 8) >= 254) ? 255 : uint8_t(r16 >> 8);
|
||||
uint8_t g8_final = (g8 == 255 && uint8_t(g16 >> 8) >= 254) ? 255 : uint8_t(g16 >> 8);
|
||||
uint8_t b8_final = (b8 == 255 && uint8_t(b16 >> 8) >= 254) ? 255 : uint8_t(b16 >> 8);
|
||||
|
||||
#if FASTLED_FIVE_BIT_HD_GAMMA_LOW_END_LINEAR_RAMP == 1
|
||||
if (v8 == 1) {
|
||||
// Linear tuning for the lowest possible brightness. x=y until
|
||||
// the intersection point at 9.
|
||||
@ -151,6 +123,7 @@ void five_bit_hd_gamma_bitshift(
|
||||
b8_final = b8;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Step 5: Output
|
||||
*out_r8 = r8_final;
|
||||
|
Loading…
Reference in New Issue
Block a user