16 Bit Gamma improvements (#645)

* Gamma for 16bit Table Method
This commit is contained in:
Michael Miller
2023-02-09 16:33:34 -08:00
committed by GitHub
parent fff81b9a15
commit d6ccd6da61
4 changed files with 89 additions and 24 deletions

View File

@@ -22,11 +22,11 @@ RgbColor white(255, 255, 255);
// for your NeoPixels // for your NeoPixels
NeoPixelBusLg<NeoRgbFeature, NeoWs2812xMethod> strip(PixelCount, PixelPin); NeoPixelBusLg<NeoRgbFeature, NeoWs2812xMethod> strip(PixelCount, PixelPin);
// If speed is an issue and memory is not, then you can use the gama table variant // If speed is an issue and memory is not, then you can use the gamma table variant
// which is much faster but uses 256 bytes of RAM // which is much faster but uses 256 bytes of RAM
// NeoPixelBusLg<NeoRgbFeature, NeoWs2812xMethod, NeoGammaTableMethod> strip(PixelCount, PixelPin); // NeoPixelBusLg<NeoRgbFeature, NeoWs2812xMethod, NeoGammaTableMethod> strip(PixelCount, PixelPin);
// If you want to turn gama correction off, then you can use the null gama method // If you want to turn gamma correction off, then you can use the null gamma method
// NeoPixelBusLg<NeoRgbFeature, NeoWs2812xMethod, NeoGammaNullMethod> strip(PixelCount, PixelPin); // NeoPixelBusLg<NeoRgbFeature, NeoWs2812xMethod, NeoGammaNullMethod> strip(PixelCount, PixelPin);
void setup() void setup()

View File

@@ -74,7 +74,7 @@ public:
{ {
// does NOT affect current pixel data as there is no safe way // does NOT affect current pixel data as there is no safe way
// to reconstruct the original color values after being // to reconstruct the original color values after being
// modified with both luminance and gama without storing them // modified with both luminance and gamma without storing them
_luminance = luminance; _luminance = luminance;
} }

View File

@@ -28,20 +28,20 @@ License along with NeoPixel. If not, see
#include "NeoPixelBus.h" #include "NeoPixelBus.h"
const uint8_t NeoGammaTableMethod::_table[] = { const uint8_t NeoGammaTableMethod::_table[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, // 32
3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, // 48
6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 11, 11, 11, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 11, 11, 11, // 64
12, 12, 13, 13, 14, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 12, 12, 13, 13, 14, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, // 80
19, 20, 20, 21, 22, 22, 23, 23, 24, 25, 25, 26, 26, 27, 28, 28, 19, 20, 20, 21, 22, 22, 23, 23, 24, 25, 25, 26, 26, 27, 28, 28, // 96
29, 30, 30, 31, 32, 33, 33, 34, 35, 35, 36, 37, 38, 39, 39, 40, 29, 30, 30, 31, 32, 33, 33, 34, 35, 35, 36, 37, 38, 39, 39, 40, // 112
41, 42, 43, 43, 44, 45, 46, 47, 48, 49, 50, 50, 51, 52, 53, 54, 41, 42, 43, 43, 44, 45, 46, 47, 48, 49, 50, 50, 51, 52, 53, 54, // 128
55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 71, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, // 144
72, 73, 74, 75, 76, 77, 78, 80, 81, 82, 83, 84, 86, 87, 88, 89, 71, 73, 74, 75, 76, 77, 78, 79, 81, 82, 83, 84, 85, 87, 88, 89, // 160
91, 92, 93, 94, 96, 97, 98, 100, 101, 102, 104, 105, 106, 108, 109, 110, 90, 91, 93, 94, 95, 97, 98, 99, 101, 102, 103, 105, 106, 107, 109, 110, // 176
112, 113, 115, 116, 118, 119, 121, 122, 123, 125, 126, 128, 130, 131, 133, 134, 111, 113, 114, 116, 117, 119, 120, 122, 123, 125, 126, 128, 129, 131, 132, 134, // 192
136, 137, 139, 140, 142, 144, 145, 147, 149, 150, 152, 154, 155, 157, 159, 160, 135, 137, 138, 140, 142, 143, 145, 146, 148, 150, 151, 153, 155, 156, 158, 160, // 208
162, 164, 166, 167, 169, 171, 173, 175, 176, 178, 180, 182, 184, 186, 187, 189, 162, 163, 165, 167, 168, 170, 172, 174, 176, 177, 179, 181, 183, 185, 187, 189, // 224
191, 193, 195, 197, 199, 201, 203, 205, 207, 209, 211, 213, 215, 217, 219, 221, 190, 192, 194, 196, 198, 200, 202, 203, 206, 207, 210, 212, 214, 216, 218, 220, // 240
223, 225, 227, 229, 231, 233, 235, 238, 240, 242, 244, 246, 248, 251, 253, 255 222, 224, 226, 228, 230, 232, 234, 237, 239, 241, 243, 245, 247, 250, 251, 255 // 256
}; };

View File

@@ -40,6 +40,12 @@ public:
} }
}; };
struct NeoGamma16LowHint
{
uint8_t pos;
uint8_t count;
};
// NeoGammaTableMethod uses 256 bytes of memory, but is significantly faster // NeoGammaTableMethod uses 256 bytes of memory, but is significantly faster
class NeoGammaTableMethod class NeoGammaTableMethod
{ {
@@ -48,16 +54,75 @@ public:
{ {
return _table[value]; return _table[value];
} }
/*
static uint16_t Correct(uint16_t value) static uint16_t Correct(uint16_t value)
{ {
// NOTE: 16 bit color elements not supported with NeoGammaTableMethod, use NeoGammaEquationMethod // since a single monolithic table would be an unreasonable memory usage
return 0; // this will use a hybrid of two tables, the base 255 table for the hibyte
// and a smaller table with hints on how to use the table for certain values
// and the left over values some simple calculations to approximate the final
// 16 bit value as compared to the equation
static const NeoGamma16LowHint _hints[] = {
{0,16}, {1,16}, {2,16}, {3,16}, {4,16}, {5,16}, {6,16}, {7,16}, {8,16}, {9,16}, {10,16}, {11,16}, {12,16}, {13,16}, {14,16}, {15,16},
{0,10}, {1,10}, {2,10}, {3,10}, {4,10}, {5,10}, {6,10}, {7,10}, {8,10}, {9,10}, {0,6}, {1,6}, {2,6}, {3,6}, {4,6}, {5,6},
{0,6}, {1,6}, {2,6}, {3,6}, {4,6}, {5,6}, {0,4}, {1,4}, {2,4}, {3,4}, {0,4}, {1,4}, {2,4}, {3,4}, {0,3}, {1,3},
{2,3}, {0,4}, {1,4}, {2,4}, {3,4}, {0,3}, {1,3}, {2,3}, {0,3}, {1,3}, {2,3}, {0,2}, {1,2}, {0,3}, {1,3}, {2,3},
{0,2}, {1,2}, {0,2}, {1,2}, {0,3}, {1,3}, {2,3}, {0,2}, {1,2}
};
uint8_t hi = (value >> 8);
uint16_t lo = (value & 0x00ff);
uint8_t hiResult = _table[hi];
uint16_t lowResult = 0;
if (hi < countof(_hints))
{
// use _hints table to calculate a reasonable lowbyte
lowResult = (lo + _hints[hi].pos * 256) / _hints[hi].count;
}
else if (hi == 255)
{
// last entry is always linear
lowResult = lo;
}
else
{
// check the _table for duplicate or jumps to adjust the range of lowbyte
if (hiResult == _table[hi - 1])
{
// this result is an upper duplicate
lowResult = (lo >> 1) | 0x80; // lo / 2 + 128
}
else
{
uint8_t delta = _table[hi + 1] - hiResult;
if (delta == 0)
{
// this result is a lower duplicate
lowResult = (lo >> 1); // lo / 2
}
else if (delta == 1)
{
// this result is incremental and thus linear
lowResult = lo;
}
else
{
// this result jumps by more than one, so need to spread across
lowResult = delta * lo;
}
}
}
return (static_cast<uint16_t>(hiResult) << 8) + lowResult;
} }
*/
private: private:
static const uint8_t _table[256]; static const uint8_t _table[256];
}; };
// no gamma correction at all // no gamma correction at all