ESPHome 2026.11.0-dev
Loading...
Searching...
No Matches
esp_color_correction.cpp
Go to the documentation of this file.
2
3namespace esphome::light {
4
5uint8_t ESPColorCorrection::gamma_correct_(uint8_t value) const {
6 if (this->gamma_table_ == nullptr)
7 return value;
8 uint16_t table_value = progmem_read_uint16(&this->gamma_table_[value]);
9 uint8_t result = (table_value + 128) / 257;
10 if (result == 0 && table_value != 0)
11 return 1;
12 return result;
13}
14
15uint8_t ESPColorCorrection::gamma_uncorrect_(uint8_t value) const {
16 if (this->gamma_table_ == nullptr)
17 return value;
18 if (value == 0)
19 return 0;
20 uint16_t target = value * 257; // Scale 0-255 to 0-65535
21 uint8_t lo = gamma_table_reverse_search(this->gamma_table_, target);
22 if (lo >= 255)
23 return 255;
24 uint16_t a = progmem_read_uint16(&this->gamma_table_[lo]);
25 uint16_t b = progmem_read_uint16(&this->gamma_table_[lo + 1]);
26 return (target - a <= b - target) ? lo : lo + 1;
27}
28
30 // uncorrected = corrected^(1/gamma) / (max_brightness * local_brightness)
31 return Color(this->color_uncorrect_red(color.red), this->color_uncorrect_green(color.green),
32 this->color_uncorrect_blue(color.blue), this->color_uncorrect_white(color.white));
33}
34
35// Under the limit, gamma and the limit are undone together: the largest level that encodes to at most the
36// stored one, so a read, change and write of a pixel re-encodes to what was stored
37uint8_t ESPColorCorrection::uncorrect_level_(uint8_t value) const {
38#ifdef USE_LIGHT_POWER_ESTIMATION
39 if (this->power_brightness_ == 255)
40 return this->gamma_uncorrect_(value);
41 uint8_t lo = 0;
42 uint8_t hi = 255;
43 while (lo < hi) {
44 const uint8_t mid = (lo + hi + 1) / 2;
45 if (this->limit_(this->gamma_correct_(mid)) <= value) {
46 lo = mid;
47 } else {
48 hi = mid - 1;
49 }
50 }
51 return lo;
52#else
53 return this->gamma_uncorrect_(value);
54#endif
55}
56
57uint8_t ESPColorCorrection::color_uncorrect_channel_(uint8_t value, uint8_t max_brightness) const {
58 if (max_brightness == 0 || this->local_brightness_ == 0)
59 return 0;
60 // Use 32-bit intermediates: when max_brightness and local_brightness_ are small but non-zero,
61 // (uncorrected / max_brightness) * 255 can exceed 65535 before the std::min(255) clamp runs.
62 uint32_t uncorrected = this->uncorrect_level_(value) * 255UL;
63 uint32_t res = ((uncorrected / max_brightness) * 255UL) / this->local_brightness_;
64 return static_cast<uint8_t>(std::min(res, uint32_t(255)));
65}
66
67} // namespace esphome::light
uint8_t gamma_correct_(uint8_t value) const
Forward gamma: read uint16 PROGMEM table, convert to uint8.
uint8_t color_uncorrect_red(uint8_t red) const ESPHOME_ALWAYS_INLINE
uint8_t color_uncorrect_channel_(uint8_t value, uint8_t max_brightness) const
Shared body of color_uncorrect_{red,green,blue,white}.
uint8_t uncorrect_level_(uint8_t value) const
Reverse gamma and limit for one stored level.
uint8_t limit_(uint8_t res) const ESPHOME_ALWAYS_INLINE
uint8_t gamma_uncorrect_(uint8_t value) const
Reverse gamma: binary search the forward PROGMEM table.
uint8_t gamma_table_reverse_search(const uint16_t *table, uint16_t target)
Binary search a monotonically increasing uint16[256] PROGMEM table.
static float float b
uint16_t progmem_read_uint16(const uint16_t *addr)
Definition hal.h:53
uint8_t red
Definition color.h:31
uint8_t white
Definition color.h:43
uint8_t green
Definition color.h:35
uint8_t blue
Definition color.h:39