Changed gamma correction to adaptative resolution from 8 to 11 bits

This commit is contained in:
Stephan Hadinger 2019-04-30 23:03:08 +02:00
parent 875c33ea19
commit e98acd5c40
2 changed files with 101 additions and 22 deletions

View File

@ -102,23 +102,70 @@ struct LCwColor {
const uint8_t MAX_FIXED_COLD_WARM = 4; const uint8_t MAX_FIXED_COLD_WARM = 4;
const LCwColor kFixedColdWarm[MAX_FIXED_COLD_WARM] PROGMEM = { 0,0, 255,0, 0,255, 128,128 }; const LCwColor kFixedColdWarm[MAX_FIXED_COLD_WARM] PROGMEM = { 0,0, 255,0, 0,255, 128,128 };
const uint8_t ledTable[] = { // New version of Gamma correction table, with adaptative resolution
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // from 11 bits (lower values) to 8 bits (upper values).
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // We're using the fact that lower values are small and can fit within 8 bits
1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, // To save flash space, the array is only 8 bits uint
4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, const uint8_t _ledTable[] = {
8, 8, 9, 9, 9, 10, 10, 10, 11, 11, 12, 12, 12, 13, 13, 14, // 11 bits resolution
14, 15, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 22, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, // 11 bits, 0..2047
22, 23, 23, 24, 25, 25, 26, 26, 27, 28, 28, 29, 30, 30, 31, 32, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, // 11 bits, 0..2047
33, 33, 34, 35, 36, 36, 37, 38, 39, 40, 40, 41, 42, 43, 44, 45, 7, 8, 8, 9, 10, 10, 11, 12, 12, 13, 14, 15, 16, 17, 18, 19, // 11 bits, 0..2047
46, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 20, 21, 22, 24, 25, 26, 28, 29, 30, 32, 33, 35, 37, 38, 40, 42, // 11 bits, 0..2047
61, 62, 63, 64, 65, 67, 68, 69, 70, 71, 72, 73, 75, 76, 77, 78, // 10 bits resolution
80, 81, 82, 83, 85, 86, 87, 89, 90, 91, 93, 94, 95, 97, 98, 99, 22, 23, 24, 25, 26, 27, 28, 30, 31, 32, 33, 34, 36, 37, 38, 39, // 10 bits, 0..1023
101,102,104,105,107,108,110,111,113,114,116,117,119,121,122,124, 41, 42, 44, 45, 47, 48, 50, 51, 53, 55, 56, 58, 60, 62, 64, 65, // 10 bits, 0..1023
125,127,129,130,132,134,135,137,139,141,142,144,146,148,150,151, 67, 69, 71, 73, 75, 78, 80, 82, 84, 86, 89, 91, 93, 96, 98,101, // 10 bits, 0..1023
153,155,157,159,161,163,165,166,168,170,172,174,176,178,180,182, 103,106,108,111,114,116,119,122,125,128,131,134,137,140,143,146, // 10 bits, 0..1023
184,186,189,191,193,195,197,199,201,204,206,208,210,212,215,217, // 9 bits resolution
219,221,224,226,228,231,233,235,238,240,243,245,248,250,253,255 }; 75, 77, 78, 80, 82, 84, 85, 87, 89, 91, 93, 94, 96, 98,100,102, // 9 bits, 0..511
104,106,108,110,112,115,117,119,121,123,125,128,130,132,135,137, // 9 bits, 0..511
140,142,144,147,149,152,155,157,160,163,165,168,171,173,176,179, // 9 bits, 0..511
182,185,188,191,194,197,200,203,206,209,212,215,219,222,225,229, // 9 bits, 0..511
// 8 bits resolution
116,118,120,121,123,125,127,128,130,132,134,136,138,139,141,143, // 8 bits, 0..255
145,147,149,151,153,155,157,159,161,163,165,168,170,172,174,176, // 8 bits, 0..255
178,181,183,185,187,190,192,194,197,199,201,204,206,209,211,214, // 8 bits, 0..255
216,219,221,224,226,229,232,234,237,240,242,245,248,250,253,255 // 8 bits, 0..255
};
// For reference, below are the computed gamma tables, via ledGamma()
// for 8 bits output:
// 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
// 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
// 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3,
// 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6,
// 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10,
// 11, 11, 11, 12, 12, 12, 13, 13, 14, 14, 14, 15, 15, 16, 16, 17,
// 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 23, 23, 24, 24, 25, 26,
// 26, 27, 27, 28, 29, 29, 30, 31, 32, 32, 33, 34, 35, 35, 36, 37,
// 38, 39, 39, 40, 41, 42, 43, 44, 45, 46, 47, 47, 48, 49, 50, 51,
// 52, 53, 54, 55, 56, 58, 59, 60, 61, 62, 63, 64, 65, 66, 68, 69,
// 70, 71, 72, 74, 75, 76, 78, 79, 80, 82, 83, 84, 86, 87, 88, 90,
// 91, 93, 94, 96, 97, 99,100,102,103,105,106,108,110,111,113,115,
//116,118,120,121,123,125,127,128,130,132,134,136,138,139,141,143,
//145,147,149,151,153,155,157,159,161,163,165,168,170,172,174,176,
//178,181,183,185,187,190,192,194,197,199,201,204,206,209,211,214,
//216,219,221,224,226,229,232,234,237,240,242,245,248,250,253,255
//
// and for 10 bits output:
// 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
// 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 4,
// 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 8, 8, 9, 9, 10,
// 10, 11, 11, 12, 13, 13, 14, 15, 15, 16, 17, 18, 19, 19, 20, 21,
// 22, 23, 24, 25, 26, 27, 28, 30, 31, 32, 33, 34, 36, 37, 38, 39,
// 41, 42, 44, 45, 47, 48, 50, 51, 53, 55, 56, 58, 60, 62, 64, 65,
// 67, 69, 71, 73, 75, 78, 80, 82, 84, 86, 89, 91, 93, 96, 98,101,
//103,106,108,111,114,116,119,122,125,128,131,134,137,140,143,146,
//151,155,157,161,165,169,171,175,179,183,187,189,193,197,201,205,
//209,213,217,221,225,231,235,239,243,247,251,257,261,265,271,275,
//281,285,289,295,299,305,311,315,321,327,331,337,343,347,353,359,
//365,371,377,383,389,395,401,407,413,419,425,431,439,445,451,459,
//467,475,483,487,495,503,511,515,523,531,539,547,555,559,567,575,
//583,591,599,607,615,623,631,639,647,655,663,675,683,691,699,707,
//715,727,735,743,751,763,771,779,791,799,807,819,827,839,847,859,
//867,879,887,899,907,919,931,939,951,963,971,983,995,1003,1015,1023
uint8_t light_entry_color[5]; uint8_t light_entry_color[5];
uint8_t light_current_color[5]; uint8_t light_current_color[5];
@ -747,6 +794,38 @@ public:
LightStateClass light_state = LightStateClass(); LightStateClass light_state = LightStateClass();
LightControllerClass light_controller = LightControllerClass(light_state); LightControllerClass light_controller = LightControllerClass(light_state);
/*********************************************************************************************\
* Gamma correction
\*********************************************************************************************/
// uint16_t ledGamma(uint8_t v, uint16_t max_range = 255) {
// uint16_t slot = 3 - (v / 64); // 0..3
// uint16_t uncorrected_value = _ledTable[v];
// uint16_t range = (0x100 << slot) - 1;
// return changeUIntScale(uncorrected_value, 0, range, 0, max_range);
// }
// bits can be 8,9,10,11
uint16_t ledGamma(uint8_t v, uint16_t bits_out = 8) {
uint16_t result;
// bits_resolution: the resolution of _ledTable[v], between 8 and 11
uint32_t bits_resolution = 11 - (v / 64); // 8..11
int32_t bits_correction = bits_out - bits_resolution; // -3..3
uint32_t uncorrected_value = _ledTable[v]; // 0..255
if (0 == bits_correction) {
// we already match the required resolution, no change
result = uncorrected_value;
} else if (bits_correction > 0) {
// the output resolution is higher than our value, we need to extrapolate
// we shift by bits_correction, and force last bits to 1
uint32_t bits_mask = (1 << bits_correction) - 1; // 1, 3, 7
result = (uncorrected_value << bits_correction) | bits_mask;
} else { // bits_correction < 0
// our resolution is too high, we need to remove bits
// we add 1, 3 or 7 to force rouding to the nearest high value
uint32_t bits_mask = (1 << -bits_correction) - 1; // 1, 3, 7
result = ((uncorrected_value + bits_mask) >> -bits_correction);
}
return result;
}
#ifdef USE_ARILUX_RF #ifdef USE_ARILUX_RF
/*********************************************************************************************\ /*********************************************************************************************\
@ -1531,7 +1610,7 @@ void LightAnimate(void)
for (uint8_t i = 0; i < light_subtype; i++) { for (uint8_t i = 0; i < light_subtype; i++) {
light_last_color[i] = light_new_color[i]; light_last_color[i] = light_new_color[i];
cur_col[i] = light_last_color[i]*Settings.rgbwwTable[i]/255; cur_col[i] = light_last_color[i]*Settings.rgbwwTable[i]/255;
cur_col[i] = (Settings.light_correction) ? ledTable[cur_col[i]] : cur_col[i]; cur_col[i] = (Settings.light_correction) ? ledGamma(cur_col[i]) : cur_col[i];
} }
// color remapping // color remapping

View File

@ -99,11 +99,11 @@ void Ws2812StripShow(void)
if (Settings.light_correction) { if (Settings.light_correction) {
for (uint16_t i = 0; i < Settings.light_pixels; i++) { for (uint16_t i = 0; i < Settings.light_pixels; i++) {
c = strip->GetPixelColor(i); c = strip->GetPixelColor(i);
c.R = ledTable[c.R]; c.R = ledGamma(c.R);
c.G = ledTable[c.G]; c.G = ledGamma(c.G);
c.B = ledTable[c.B]; c.B = ledGamma(c.B);
#if (USE_WS2812_CTYPE > NEO_3LED) #if (USE_WS2812_CTYPE > NEO_3LED)
c.W = ledTable[c.W]; c.W = ledGamma(c.W);
#endif #endif
strip->SetPixelColor(i, c); strip->SetPixelColor(i, c);
} }