ESPHome 2026.3.0-dev
Loading...
Searching...
No Matches
esp_color_correction.h
Go to the documentation of this file.
1#pragma once
2
4#include "esphome/core/hal.h"
5
6namespace esphome::light {
7
10inline uint8_t gamma_table_reverse_search(const uint16_t *table, uint16_t target) {
11 uint8_t lo = 0, hi = 255;
12 while (lo < hi) {
13 uint8_t mid = (lo + hi + 1) / 2;
14 if (progmem_read_uint16(&table[mid]) <= target) {
15 lo = mid;
16 } else {
17 hi = mid - 1;
18 }
19 }
20 return lo;
21}
22
24 public:
25 void set_max_brightness(const Color &max_brightness) { this->max_brightness_ = max_brightness; }
26 void set_local_brightness(uint8_t local_brightness) { this->local_brightness_ = local_brightness; }
27 void set_gamma_table(const uint16_t *table) { this->gamma_table_ = table; }
28 inline Color color_correct(Color color) const ESPHOME_ALWAYS_INLINE {
29 // corrected = (uncorrected * max_brightness * local_brightness) ^ gamma
30 return Color(this->color_correct_red(color.red), this->color_correct_green(color.green),
31 this->color_correct_blue(color.blue), this->color_correct_white(color.white));
32 }
33 inline uint8_t color_correct_red(uint8_t red) const ESPHOME_ALWAYS_INLINE {
34 uint8_t res = esp_scale8_twice(red, this->max_brightness_.red, this->local_brightness_);
35 return this->gamma_correct_(res);
36 }
37 inline uint8_t color_correct_green(uint8_t green) const ESPHOME_ALWAYS_INLINE {
38 uint8_t res = esp_scale8_twice(green, this->max_brightness_.green, this->local_brightness_);
39 return this->gamma_correct_(res);
40 }
41 inline uint8_t color_correct_blue(uint8_t blue) const ESPHOME_ALWAYS_INLINE {
42 uint8_t res = esp_scale8_twice(blue, this->max_brightness_.blue, this->local_brightness_);
43 return this->gamma_correct_(res);
44 }
45 inline uint8_t color_correct_white(uint8_t white) const ESPHOME_ALWAYS_INLINE {
46 uint8_t res = esp_scale8_twice(white, this->max_brightness_.white, this->local_brightness_);
47 return this->gamma_correct_(res);
48 }
49 inline Color color_uncorrect(Color color) const ESPHOME_ALWAYS_INLINE {
50 // uncorrected = corrected^(1/gamma) / (max_brightness * local_brightness)
51 return Color(this->color_uncorrect_red(color.red), this->color_uncorrect_green(color.green),
52 this->color_uncorrect_blue(color.blue), this->color_uncorrect_white(color.white));
53 }
54 inline uint8_t color_uncorrect_red(uint8_t red) const ESPHOME_ALWAYS_INLINE {
55 if (this->max_brightness_.red == 0 || this->local_brightness_ == 0)
56 return 0;
57 uint16_t uncorrected = this->gamma_uncorrect_(red) * 255UL;
58 uint16_t res = ((uncorrected / this->max_brightness_.red) * 255UL) / this->local_brightness_;
59 return (uint8_t) std::min(res, uint16_t(255));
60 }
61 inline uint8_t color_uncorrect_green(uint8_t green) const ESPHOME_ALWAYS_INLINE {
62 if (this->max_brightness_.green == 0 || this->local_brightness_ == 0)
63 return 0;
64 uint16_t uncorrected = this->gamma_uncorrect_(green) * 255UL;
65 uint16_t res = ((uncorrected / this->max_brightness_.green) * 255UL) / this->local_brightness_;
66 return (uint8_t) std::min(res, uint16_t(255));
67 }
68 inline uint8_t color_uncorrect_blue(uint8_t blue) const ESPHOME_ALWAYS_INLINE {
69 if (this->max_brightness_.blue == 0 || this->local_brightness_ == 0)
70 return 0;
71 uint16_t uncorrected = this->gamma_uncorrect_(blue) * 255UL;
72 uint16_t res = ((uncorrected / this->max_brightness_.blue) * 255UL) / this->local_brightness_;
73 return (uint8_t) std::min(res, uint16_t(255));
74 }
75 inline uint8_t color_uncorrect_white(uint8_t white) const ESPHOME_ALWAYS_INLINE {
76 if (this->max_brightness_.white == 0 || this->local_brightness_ == 0)
77 return 0;
78 uint16_t uncorrected = this->gamma_uncorrect_(white) * 255UL;
79 uint16_t res = ((uncorrected / this->max_brightness_.white) * 255UL) / this->local_brightness_;
80 return (uint8_t) std::min(res, uint16_t(255));
81 }
82
83 protected:
85 uint8_t gamma_correct_(uint8_t value) const;
87 uint8_t gamma_uncorrect_(uint8_t value) const;
88
89 const uint16_t *gamma_table_{nullptr};
90 Color max_brightness_{255, 255, 255, 255};
91 uint8_t local_brightness_{255};
92};
93
94} // 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_correct_blue(uint8_t blue) const ESPHOME_ALWAYS_INLINE
void set_max_brightness(const Color &max_brightness)
uint8_t color_correct_red(uint8_t red) const ESPHOME_ALWAYS_INLINE
void set_local_brightness(uint8_t local_brightness)
Color color_correct(Color color) const ESPHOME_ALWAYS_INLINE
uint8_t color_uncorrect_blue(uint8_t blue) const ESPHOME_ALWAYS_INLINE
void set_gamma_table(const uint16_t *table)
Color color_uncorrect(Color color) const ESPHOME_ALWAYS_INLINE
uint8_t color_uncorrect_green(uint8_t green) const ESPHOME_ALWAYS_INLINE
uint8_t color_correct_green(uint8_t green) const ESPHOME_ALWAYS_INLINE
uint8_t gamma_uncorrect_(uint8_t value) const
Reverse gamma: binary search the forward PROGMEM table.
uint8_t color_correct_white(uint8_t white) const ESPHOME_ALWAYS_INLINE
uint8_t color_uncorrect_white(uint8_t white) const ESPHOME_ALWAYS_INLINE
uint8_t gamma_table_reverse_search(const uint16_t *table, uint16_t target)
Binary search a monotonically increasing uint16[256] PROGMEM table.
uint16_t progmem_read_uint16(const uint16_t *addr)
Definition core.cpp:51
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