Migrate ESPColor to Color (#1551)

* Migrate ESPColor to Color

* color.h constructor fix

* Updated componets to use Color
Added a using for ESPColor

* Lint fixes

* Fixed value error

* Update display components to use colorutil

* Updated to latest PR comments

* Fixed COLOR_WHITE

* Moved esp_scale to color_utils

* Rename color_utils to display_color_utils
This commit is contained in:
SenexCrenshaw 2021-03-02 09:08:57 -05:00 committed by GitHub
parent b17e0c298e
commit ac25b138f5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 272 additions and 369 deletions

View File

@ -42,11 +42,11 @@ void AdalightLightEffect::reset_frame_(light::AddressableLight &it) {
void AdalightLightEffect::blank_all_leds_(light::AddressableLight &it) {
for (int led = it.size(); led-- > 0;) {
it[led].set(light::ESPColor::BLACK);
it[led].set(COLOR_BLACK);
}
}
void AdalightLightEffect::apply(light::AddressableLight &it, const light::ESPColor &current_color) {
void AdalightLightEffect::apply(light::AddressableLight &it, const Color &current_color) {
const uint32_t now = millis();
if (now - this->last_ack_ >= ADALIGHT_ACK_INTERVAL) {
@ -130,7 +130,7 @@ AdalightLightEffect::Frame AdalightLightEffect::parse_frame_(light::AddressableL
for (int led = 0; led < accepted_led_count; led++, led_data += 3) {
auto white = std::min(std::min(led_data[0], led_data[1]), led_data[2]);
it[led].set(light::ESPColor(led_data[0], led_data[1], led_data[2], white));
it[led].set(Color(led_data[0], led_data[1], led_data[2], white));
}
return CONSUMED;

View File

@ -16,7 +16,7 @@ class AdalightLightEffect : public light::AddressableLightEffect, public uart::U
public:
void start() override;
void stop() override;
void apply(light::AddressableLight &it, const light::ESPColor &current_color) override;
void apply(light::AddressableLight &it, const Color &current_color) override;
protected:
enum Frame {

View File

@ -2,22 +2,58 @@ from esphome import config_validation as cv
from esphome import codegen as cg
from esphome.const import CONF_BLUE, CONF_GREEN, CONF_ID, CONF_RED, CONF_WHITE
ColorStruct = cg.esphome_ns.struct('Color')
ColorStruct = cg.esphome_ns.struct("Color")
MULTI_CONF = True
CONFIG_SCHEMA = cv.Schema({
cv.Required(CONF_ID): cv.declare_id(ColorStruct),
cv.Optional(CONF_RED, default=0.0): cv.percentage,
cv.Optional(CONF_GREEN, default=0.0): cv.percentage,
cv.Optional(CONF_BLUE, default=0.0): cv.percentage,
cv.Optional(CONF_WHITE, default=0.0): cv.percentage,
}).extend(cv.COMPONENT_SCHEMA)
CONF_RED_INT = "red_int"
CONF_GREEN_INT = "green_int"
CONF_BLUE_INT = "blue_int"
CONF_WHITE_INT = "white_int"
CONFIG_SCHEMA = cv.Schema(
{
cv.Required(CONF_ID): cv.declare_id(ColorStruct),
cv.Exclusive(CONF_RED, 'red'): cv.percentage,
cv.Exclusive(CONF_RED_INT, 'red'): cv.uint8_t,
cv.Exclusive(CONF_GREEN, 'green'): cv.percentage,
cv.Exclusive(CONF_GREEN_INT, 'green'): cv.uint8_t,
cv.Exclusive(CONF_BLUE, 'blue'): cv.percentage,
cv.Exclusive(CONF_BLUE_INT, 'blue'): cv.uint8_t,
cv.Exclusive(CONF_WHITE, 'white'): cv.percentage,
cv.Exclusive(CONF_WHITE_INT, 'white'): cv.uint8_t,
}
).extend(cv.COMPONENT_SCHEMA)
def to_code(config):
r = 0
if CONF_RED in config:
r = int(config[CONF_RED]*255)
elif CONF_RED_INT in config:
r = config[CONF_RED_INT]
g = 0
if CONF_GREEN in config:
g = int(config[CONF_GREEN]*255)
elif CONF_GREEN_INT in config:
g = config[CONF_GREEN_INT]
b = 0
if CONF_BLUE in config:
b = int(config[CONF_BLUE]*255)
elif CONF_BLUE_INT in config:
b = config[CONF_BLUE_INT]
w = 0
if CONF_WHITE in config:
w = int(config[CONF_WHITE]*255)
elif CONF_WHITE_INT in config:
w = config[CONF_WHITE_INT]
cg.variable(config[CONF_ID], cg.StructInitializer(
ColorStruct,
('r', config[CONF_RED]),
('g', config[CONF_GREEN]),
('b', config[CONF_BLUE]),
('w', config[CONF_WHITE])))
('r', r),
('g', g),
('b', b),
('w', w)))

View File

@ -3,7 +3,7 @@
#include "esphome/core/component.h"
#include "esphome/core/defines.h"
#include "esphome/core/automation.h"
#include "esphome/core/color.h"
#include "display_color_utils.h"
#ifdef USE_TIME
#include "esphome/components/time/real_time_clock.h"

View File

@ -0,0 +1,110 @@
#pragma once
#include "esphome/core/color.h"
namespace esphome {
namespace display {
enum ColorOrder : uint8_t { COLOR_ORDER_RGB = 0, COLOR_ORDER_BGR = 1, COLOR_ORDER_GRB = 2 };
enum ColorBitness : uint8_t { COLOR_BITNESS_888 = 0, COLOR_BITNESS_565 = 1, COLOR_BITNESS_332 = 2 };
inline static uint8_t esp_scale(uint8_t i, uint8_t scale, uint8_t max_value = 255) { return (max_value * i / scale); }
class ColorUtil {
public:
static Color to_color(uint32_t colorcode, ColorOrder color_order,
ColorBitness color_bitness = ColorBitness::COLOR_BITNESS_888, bool right_bit_aligned = true) {
uint8_t first_color, second_color, third_color;
uint8_t first_bits = 0;
uint8_t second_bits = 0;
uint8_t third_bits = 0;
switch (color_bitness) {
case COLOR_BITNESS_888:
first_bits = 8;
second_bits = 8;
third_bits = 8;
break;
case COLOR_BITNESS_565:
first_bits = 5;
second_bits = 6;
third_bits = 5;
break;
case COLOR_BITNESS_332:
first_bits = 3;
second_bits = 3;
third_bits = 2;
break;
}
first_color = right_bit_aligned ? esp_scale(((colorcode >> (second_bits + third_bits)) & ((1 << first_bits) - 1)),
((1 << first_bits) - 1))
: esp_scale(((colorcode >> 16) & 0xFF), (1 << first_bits) - 1);
second_color = right_bit_aligned
? esp_scale(((colorcode >> third_bits) & ((1 << second_bits) - 1)), ((1 << second_bits) - 1))
: esp_scale(((colorcode >> 8) & 0xFF), ((1 << second_bits) - 1));
third_color = (right_bit_aligned ? esp_scale(((colorcode >> 0) & 0xFF), ((1 << third_bits) - 1))
: esp_scale(((colorcode >> 0) & 0xFF), (1 << third_bits) - 1));
Color color_return;
switch (color_order) {
case COLOR_ORDER_RGB:
color_return.r = first_color;
color_return.g = second_color;
color_return.b = third_color;
break;
case COLOR_ORDER_BGR:
color_return.b = first_color;
color_return.g = second_color;
color_return.r = third_color;
break;
case COLOR_ORDER_GRB:
color_return.g = first_color;
color_return.r = second_color;
color_return.b = third_color;
break;
}
return color_return;
}
static uint8_t color_to_332(Color color, ColorOrder color_order = ColorOrder::COLOR_ORDER_RGB) {
uint16_t red_color, green_color, blue_color;
red_color = esp_scale8(color.red, ((1 << 3) - 1));
green_color = esp_scale8(color.green, ((1 << 3) - 1));
blue_color = esp_scale8(color.blue, (1 << 2) - 1);
switch (color_order) {
case COLOR_ORDER_RGB:
return red_color << 5 | green_color << 2 | blue_color;
case COLOR_ORDER_BGR:
return blue_color << 6 | green_color << 3 | red_color;
case COLOR_ORDER_GRB:
return green_color << 5 | red_color << 2 | blue_color;
}
return 0;
}
static uint16_t color_to_565(Color color, ColorOrder color_order = ColorOrder::COLOR_ORDER_RGB) {
uint16_t red_color, green_color, blue_color;
red_color = esp_scale8(color.red, ((1 << 5) - 1));
green_color = esp_scale8(color.green, ((1 << 6) - 1));
blue_color = esp_scale8(color.blue, (1 << 5) - 1);
switch (color_order) {
case COLOR_ORDER_RGB:
return red_color << 11 | green_color << 5 | blue_color;
case COLOR_ORDER_BGR:
return blue_color << 11 | green_color << 5 | red_color;
case COLOR_ORDER_GRB:
return green_color << 10 | red_color << 5 | blue_color;
}
return 0;
}
static uint32_t color_to_grayscale4(Color color) {
uint32_t gs4 = esp_scale8(color.white, 15);
return gs4;
}
};
} // namespace display
} // namespace esphome

View File

@ -40,7 +40,7 @@ void E131AddressableLightEffect::stop() {
AddressableLightEffect::stop();
}
void E131AddressableLightEffect::apply(light::AddressableLight &it, const light::ESPColor &current_color) {
void E131AddressableLightEffect::apply(light::AddressableLight &it, const Color &current_color) {
// ignore, it is run by `E131Component::update()`
}
@ -63,22 +63,22 @@ bool E131AddressableLightEffect::process_(int universe, const E131Packet &packet
case E131_MONO:
for (; output_offset < output_end; output_offset++, input_data++) {
auto output = (*it)[output_offset];
output.set(light::ESPColor(input_data[0], input_data[0], input_data[0], input_data[0]));
output.set(Color(input_data[0], input_data[0], input_data[0], input_data[0]));
}
break;
case E131_RGB:
for (; output_offset < output_end; output_offset++, input_data += 3) {
auto output = (*it)[output_offset];
output.set(light::ESPColor(input_data[0], input_data[1], input_data[2],
(input_data[0] + input_data[1] + input_data[2]) / 3));
output.set(
Color(input_data[0], input_data[1], input_data[2], (input_data[0] + input_data[1] + input_data[2]) / 3));
}
break;
case E131_RGBW:
for (; output_offset < output_end; output_offset++, input_data += 4) {
auto output = (*it)[output_offset];
output.set(light::ESPColor(input_data[0], input_data[1], input_data[2], input_data[3]));
output.set(Color(input_data[0], input_data[1], input_data[2], input_data[3]));
}
break;
}

View File

@ -18,7 +18,7 @@ class E131AddressableLightEffect : public light::AddressableLightEffect {
public:
void start() override;
void stop() override;
void apply(light::AddressableLight &it, const light::ESPColor &current_color) override;
void apply(light::AddressableLight &it, const Color &current_color) override;
public:
int get_data_per_universe() const;

View File

@ -130,7 +130,7 @@ uint8_t ILI9341Display::convert_to_8bit_color_(uint16_t color_16bit) {
}
void ILI9341Display::fill(Color color) {
auto color565 = color.to_rgb_565();
auto color565 = display::ColorUtil::color_to_565(color);
memset(this->buffer_, convert_to_8bit_color_(color565), this->get_buffer_length_());
this->x_low_ = 0;
this->y_low_ = 0;
@ -142,7 +142,7 @@ void ILI9341Display::fill_internal_(Color color) {
this->set_addr_window_(0, 0, this->get_width_internal(), this->get_height_internal());
this->start_data_();
auto color565 = color.to_rgb_565();
auto color565 = display::ColorUtil::color_to_565(color);
for (uint32_t i = 0; i < (this->get_width_internal()) * (this->get_height_internal()); i++) {
this->write_byte(color565 >> 8);
this->write_byte(color565);
@ -162,7 +162,7 @@ void HOT ILI9341Display::draw_absolute_pixel_internal(int x, int y, Color color)
this->y_high_ = (y > this->y_high_) ? y : this->y_high_;
uint32_t pos = (y * width_) + x;
auto color565 = color.to_rgb_565();
auto color565 = display::ColorUtil::color_to_565(color);
buffer_[pos] = convert_to_8bit_color_(color565);
}

View File

@ -6,10 +6,7 @@ namespace light {
static const char *TAG = "light.addressable";
const ESPColor ESPColor::BLACK = ESPColor(0, 0, 0, 0);
const ESPColor ESPColor::WHITE = ESPColor(255, 255, 255, 255);
ESPColor ESPHSVColor::to_rgb() const {
Color ESPHSVColor::to_rgb() const {
// based on FastLED's hsv rainbow to rgb
const uint8_t hue = this->hue;
const uint8_t sat = this->saturation;
@ -19,7 +16,7 @@ ESPColor ESPHSVColor::to_rgb() const {
// third of the offset, 255/3 = 85 (actually only up to 82; 164)
const uint8_t third = esp_scale8(offset8, 85);
const uint8_t two_thirds = esp_scale8(offset8, 170);
ESPColor rgb(255, 255, 255, 0);
Color rgb(255, 255, 255, 0);
switch (hue >> 5) {
case 0b000:
rgb.r = 255 - third;
@ -76,7 +73,7 @@ ESPColor ESPHSVColor::to_rgb() const {
return rgb;
}
void ESPRangeView::set(const ESPColor &color) {
void ESPRangeView::set(const Color &color) {
for (int32_t i = this->begin_; i < this->end_; i++) {
(*this->parent_)[i] = color;
}
@ -179,12 +176,12 @@ void AddressableLight::call_setup() {
#endif
}
ESPColor esp_color_from_light_color_values(LightColorValues val) {
Color esp_color_from_light_color_values(LightColorValues val) {
auto r = static_cast<uint8_t>(roundf(val.get_red() * 255.0f));
auto g = static_cast<uint8_t>(roundf(val.get_green() * 255.0f));
auto b = static_cast<uint8_t>(roundf(val.get_blue() * 255.0f));
auto w = static_cast<uint8_t>(roundf(val.get_white() * val.get_state() * 255.0f));
return ESPColor(r, g, b, w);
return Color(r, g, b, w);
}
void AddressableLight::write_state(LightState *state) {
@ -219,7 +216,7 @@ void AddressableLight::write_state(LightState *state) {
this->last_transition_progress_ = new_progress;
auto end_values = state->transformer_->get_end_values();
ESPColor target_color = esp_color_from_light_color_values(end_values);
Color target_color = esp_color_from_light_color_values(end_values);
// our transition will handle brightness, disable brightness in correction.
this->correction_.set_local_brightness(255);
@ -247,7 +244,7 @@ void AddressableLight::write_state(LightState *state) {
if (alpha8 != 0) {
uint8_t inv_alpha8 = 255 - alpha8;
ESPColor add = target_color * alpha8;
Color add = target_color * alpha8;
for (auto led : *this)
led = add + led.get() * inv_alpha8;

View File

@ -2,6 +2,7 @@
#include "esphome/core/component.h"
#include "esphome/core/defines.h"
#include "esphome/core/color.h"
#include "light_output.h"
#include "light_state.h"
@ -12,151 +13,7 @@
namespace esphome {
namespace light {
inline static uint8_t esp_scale8(uint8_t i, uint8_t scale) { return (uint16_t(i) * (1 + uint16_t(scale))) / 256; }
struct ESPColor {
union {
struct {
union {
uint8_t r;
uint8_t red;
};
union {
uint8_t g;
uint8_t green;
};
union {
uint8_t b;
uint8_t blue;
};
union {
uint8_t w;
uint8_t white;
};
};
uint8_t raw[4];
uint32_t raw_32;
};
inline ESPColor() ALWAYS_INLINE : r(0), g(0), b(0), w(0) {} // NOLINT
inline ESPColor(uint8_t red, uint8_t green, uint8_t blue, uint8_t white) ALWAYS_INLINE : r(red),
g(green),
b(blue),
w(white) {}
inline ESPColor(uint8_t red, uint8_t green, uint8_t blue) ALWAYS_INLINE : r(red), g(green), b(blue), w(0) {}
inline ESPColor(uint32_t colorcode) ALWAYS_INLINE : r((colorcode >> 16) & 0xFF),
g((colorcode >> 8) & 0xFF),
b((colorcode >> 0) & 0xFF),
w((colorcode >> 24) & 0xFF) {}
inline ESPColor(const ESPColor &rhs) ALWAYS_INLINE {
this->r = rhs.r;
this->g = rhs.g;
this->b = rhs.b;
this->w = rhs.w;
}
inline bool is_on() ALWAYS_INLINE { return this->raw_32 != 0; }
inline ESPColor &operator=(const ESPColor &rhs) ALWAYS_INLINE {
this->r = rhs.r;
this->g = rhs.g;
this->b = rhs.b;
this->w = rhs.w;
return *this;
}
inline ESPColor &operator=(uint32_t colorcode) ALWAYS_INLINE {
this->w = (colorcode >> 24) & 0xFF;
this->r = (colorcode >> 16) & 0xFF;
this->g = (colorcode >> 8) & 0xFF;
this->b = (colorcode >> 0) & 0xFF;
return *this;
}
inline uint8_t &operator[](uint8_t x) ALWAYS_INLINE { return this->raw[x]; }
inline ESPColor operator*(uint8_t scale) const ALWAYS_INLINE {
return ESPColor(esp_scale8(this->red, scale), esp_scale8(this->green, scale), esp_scale8(this->blue, scale),
esp_scale8(this->white, scale));
}
inline ESPColor &operator*=(uint8_t scale) ALWAYS_INLINE {
this->red = esp_scale8(this->red, scale);
this->green = esp_scale8(this->green, scale);
this->blue = esp_scale8(this->blue, scale);
this->white = esp_scale8(this->white, scale);
return *this;
}
inline ESPColor operator*(const ESPColor &scale) const ALWAYS_INLINE {
return ESPColor(esp_scale8(this->red, scale.red), esp_scale8(this->green, scale.green),
esp_scale8(this->blue, scale.blue), esp_scale8(this->white, scale.white));
}
inline ESPColor &operator*=(const ESPColor &scale) ALWAYS_INLINE {
this->red = esp_scale8(this->red, scale.red);
this->green = esp_scale8(this->green, scale.green);
this->blue = esp_scale8(this->blue, scale.blue);
this->white = esp_scale8(this->white, scale.white);
return *this;
}
inline ESPColor operator+(const ESPColor &add) const ALWAYS_INLINE {
ESPColor ret;
if (uint8_t(add.r + this->r) < this->r)
ret.r = 255;
else
ret.r = this->r + add.r;
if (uint8_t(add.g + this->g) < this->g)
ret.g = 255;
else
ret.g = this->g + add.g;
if (uint8_t(add.b + this->b) < this->b)
ret.b = 255;
else
ret.b = this->b + add.b;
if (uint8_t(add.w + this->w) < this->w)
ret.w = 255;
else
ret.w = this->w + add.w;
return ret;
}
inline ESPColor &operator+=(const ESPColor &add) ALWAYS_INLINE { return *this = (*this) + add; }
inline ESPColor operator+(uint8_t add) const ALWAYS_INLINE { return (*this) + ESPColor(add, add, add, add); }
inline ESPColor &operator+=(uint8_t add) ALWAYS_INLINE { return *this = (*this) + add; }
inline ESPColor operator-(const ESPColor &subtract) const ALWAYS_INLINE {
ESPColor ret;
if (subtract.r > this->r)
ret.r = 0;
else
ret.r = this->r - subtract.r;
if (subtract.g > this->g)
ret.g = 0;
else
ret.g = this->g - subtract.g;
if (subtract.b > this->b)
ret.b = 0;
else
ret.b = this->b - subtract.b;
if (subtract.w > this->w)
ret.w = 0;
else
ret.w = this->w - subtract.w;
return ret;
}
inline ESPColor &operator-=(const ESPColor &subtract) ALWAYS_INLINE { return *this = (*this) - subtract; }
inline ESPColor operator-(uint8_t subtract) const ALWAYS_INLINE {
return (*this) - ESPColor(subtract, subtract, subtract, subtract);
}
inline ESPColor &operator-=(uint8_t subtract) ALWAYS_INLINE { return *this = (*this) - subtract; }
static ESPColor random_color() {
uint32_t rand = random_uint32();
uint8_t w = rand >> 24;
uint8_t r = rand >> 16;
uint8_t g = rand >> 8;
uint8_t b = rand >> 0;
const uint16_t max_rgb = std::max(r, std::max(g, b));
return ESPColor(uint8_t((uint16_t(r) * 255U / max_rgb)), uint8_t((uint16_t(g) * 255U / max_rgb)),
uint8_t((uint16_t(b) * 255U / max_rgb)), w);
}
ESPColor fade_to_white(uint8_t amnt) const { return ESPColor(255, 255, 255, 255) - (*this * amnt); }
ESPColor fade_to_black(uint8_t amnt) const { return *this * amnt; }
ESPColor lighten(uint8_t delta) const { return *this + delta; }
ESPColor darken(uint8_t delta) const { return *this - delta; }
static const ESPColor BLACK;
static const ESPColor WHITE;
};
using ESPColor = Color;
struct ESPHSVColor {
union {
@ -181,19 +38,19 @@ struct ESPHSVColor {
inline ESPHSVColor(uint8_t hue, uint8_t saturation, uint8_t value) ALWAYS_INLINE : hue(hue),
saturation(saturation),
value(value) {}
ESPColor to_rgb() const;
Color to_rgb() const;
};
class ESPColorCorrection {
public:
ESPColorCorrection() : max_brightness_(255, 255, 255, 255) {}
void set_max_brightness(const ESPColor &max_brightness) { this->max_brightness_ = max_brightness; }
void set_max_brightness(const Color &max_brightness) { this->max_brightness_ = max_brightness; }
void set_local_brightness(uint8_t local_brightness) { this->local_brightness_ = local_brightness; }
void calculate_gamma_table(float gamma);
inline ESPColor color_correct(ESPColor color) const ALWAYS_INLINE {
inline Color color_correct(Color color) const ALWAYS_INLINE {
// corrected = (uncorrected * max_brightness * local_brightness) ^ gamma
return ESPColor(this->color_correct_red(color.red), this->color_correct_green(color.green),
this->color_correct_blue(color.blue), this->color_correct_white(color.white));
return Color(this->color_correct_red(color.red), this->color_correct_green(color.green),
this->color_correct_blue(color.blue), this->color_correct_white(color.white));
}
inline uint8_t color_correct_red(uint8_t red) const ALWAYS_INLINE {
uint8_t res = esp_scale8(esp_scale8(red, this->max_brightness_.red), this->local_brightness_);
@ -212,10 +69,10 @@ class ESPColorCorrection {
uint8_t res = esp_scale8(white, this->max_brightness_.white);
return this->gamma_table_[res];
}
inline ESPColor color_uncorrect(ESPColor color) const ALWAYS_INLINE {
inline Color color_uncorrect(Color color) const ALWAYS_INLINE {
// uncorrected = corrected^(1/gamma) / (max_brightness * local_brightness)
return ESPColor(this->color_uncorrect_red(color.red), this->color_uncorrect_green(color.green),
this->color_uncorrect_blue(color.blue), this->color_uncorrect_white(color.white));
return Color(this->color_uncorrect_red(color.red), this->color_uncorrect_green(color.green),
this->color_uncorrect_blue(color.blue), this->color_uncorrect_white(color.white));
}
inline uint8_t color_uncorrect_red(uint8_t red) const ALWAYS_INLINE {
if (this->max_brightness_.red == 0 || this->local_brightness_ == 0)
@ -249,13 +106,13 @@ class ESPColorCorrection {
protected:
uint8_t gamma_table_[256];
uint8_t gamma_reverse_table_[256];
ESPColor max_brightness_;
Color max_brightness_;
uint8_t local_brightness_{255};
};
class ESPColorSettable {
public:
virtual void set(const ESPColor &color) = 0;
virtual void set(const Color &color) = 0;
virtual void set_red(uint8_t red) = 0;
virtual void set_green(uint8_t green) = 0;
virtual void set_blue(uint8_t blue) = 0;
@ -267,7 +124,7 @@ class ESPColorSettable {
virtual void darken(uint8_t delta) = 0;
void set(const ESPHSVColor &color) { this->set_hsv(color); }
void set_hsv(const ESPHSVColor &color) {
ESPColor rgb = color.to_rgb();
Color rgb = color.to_rgb();
this->set_rgb(rgb.r, rgb.g, rgb.b);
}
void set_rgb(uint8_t red, uint8_t green, uint8_t blue) {
@ -291,7 +148,7 @@ class ESPColorView : public ESPColorSettable {
white_(white),
effect_data_(effect_data),
color_correction_(color_correction) {}
ESPColorView &operator=(const ESPColor &rhs) {
ESPColorView &operator=(const Color &rhs) {
this->set(rhs);
return *this;
}
@ -299,7 +156,7 @@ class ESPColorView : public ESPColorSettable {
this->set_hsv(rhs);
return *this;
}
void set(const ESPColor &color) override { this->set_rgbw(color.r, color.g, color.b, color.w); }
void set(const Color &color) override { this->set_rgbw(color.r, color.g, color.b, color.w); }
void set_red(uint8_t red) override { *this->red_ = this->color_correction_->color_correct_red(red); }
void set_green(uint8_t green) override { *this->green_ = this->color_correction_->color_correct_green(green); }
void set_blue(uint8_t blue) override { *this->blue_ = this->color_correction_->color_correct_blue(blue); }
@ -317,7 +174,7 @@ class ESPColorView : public ESPColorSettable {
void fade_to_black(uint8_t amnt) override { this->set(this->get().fade_to_black(amnt)); }
void lighten(uint8_t delta) override { this->set(this->get().lighten(delta)); }
void darken(uint8_t delta) override { this->set(this->get().darken(delta)); }
ESPColor get() const { return ESPColor(this->get_red(), this->get_green(), this->get_blue(), this->get_white()); }
Color get() const { return Color(this->get_red(), this->get_green(), this->get_blue(), this->get_white()); }
uint8_t get_red() const { return this->color_correction_->color_uncorrect_red(*this->red_); }
uint8_t get_red_raw() const { return *this->red_; }
uint8_t get_green() const { return this->color_correction_->color_uncorrect_green(*this->green_); }
@ -370,8 +227,8 @@ class ESPRangeView : public ESPColorSettable {
ESPRangeIterator begin();
ESPRangeIterator end();
void set(const ESPColor &color) override;
ESPRangeView &operator=(const ESPColor &rhs) {
void set(const Color &color) override;
ESPRangeView &operator=(const Color &rhs) {
this->set(rhs);
return *this;
}
@ -454,8 +311,8 @@ class AddressableLight : public LightOutput, public Component {
void set_effect_active(bool effect_active) { this->effect_active_ = effect_active; }
void write_state(LightState *state) override;
void set_correction(float red, float green, float blue, float white = 1.0f) {
this->correction_.set_max_brightness(ESPColor(uint8_t(roundf(red * 255.0f)), uint8_t(roundf(green * 255.0f)),
uint8_t(roundf(blue * 255.0f)), uint8_t(roundf(white * 255.0f))));
this->correction_.set_max_brightness(Color(uint8_t(roundf(red * 255.0f)), uint8_t(roundf(green * 255.0f)),
uint8_t(roundf(blue * 255.0f)), uint8_t(roundf(white * 255.0f))));
}
void setup_state(LightState *state) override {
this->correction_.calculate_gamma_table(state->get_gamma_correct());

View File

@ -34,13 +34,13 @@ class AddressableLightEffect : public LightEffect {
this->start();
}
void stop() override { this->get_addressable_()->set_effect_active(false); }
virtual void apply(AddressableLight &it, const ESPColor &current_color) = 0;
virtual void apply(AddressableLight &it, const Color &current_color) = 0;
void apply() override {
LightColorValues color = this->state_->remote_values;
// not using any color correction etc. that will be handled by the addressable layer
ESPColor current_color =
ESPColor(static_cast<uint8_t>(color.get_red() * 255), static_cast<uint8_t>(color.get_green() * 255),
static_cast<uint8_t>(color.get_blue() * 255), static_cast<uint8_t>(color.get_white() * 255));
Color current_color =
Color(static_cast<uint8_t>(color.get_red() * 255), static_cast<uint8_t>(color.get_green() * 255),
static_cast<uint8_t>(color.get_blue() * 255), static_cast<uint8_t>(color.get_white() * 255));
this->apply(*this->get_addressable_(), current_color);
}
@ -51,11 +51,11 @@ class AddressableLightEffect : public LightEffect {
class AddressableLambdaLightEffect : public AddressableLightEffect {
public:
AddressableLambdaLightEffect(const std::string &name,
const std::function<void(AddressableLight &, ESPColor, bool initial_run)> &f,
const std::function<void(AddressableLight &, Color, bool initial_run)> &f,
uint32_t update_interval)
: AddressableLightEffect(name), f_(f), update_interval_(update_interval) {}
void start() override { this->initial_run_ = true; }
void apply(AddressableLight &it, const ESPColor &current_color) override {
void apply(AddressableLight &it, const Color &current_color) override {
const uint32_t now = millis();
if (now - this->last_run_ >= this->update_interval_) {
this->last_run_ = now;
@ -65,7 +65,7 @@ class AddressableLambdaLightEffect : public AddressableLightEffect {
}
protected:
std::function<void(AddressableLight &, ESPColor, bool initial_run)> f_;
std::function<void(AddressableLight &, Color, bool initial_run)> f_;
uint32_t update_interval_;
uint32_t last_run_{0};
bool initial_run_;
@ -74,7 +74,7 @@ class AddressableLambdaLightEffect : public AddressableLightEffect {
class AddressableRainbowLightEffect : public AddressableLightEffect {
public:
explicit AddressableRainbowLightEffect(const std::string &name) : AddressableLightEffect(name) {}
void apply(AddressableLight &it, const ESPColor &current_color) override {
void apply(AddressableLight &it, const Color &current_color) override {
ESPHSVColor hsv;
hsv.value = 255;
hsv.saturation = 240;
@ -106,7 +106,7 @@ class AddressableColorWipeEffect : public AddressableLightEffect {
void set_colors(const std::vector<AddressableColorWipeEffectColor> &colors) { this->colors_ = colors; }
void set_add_led_interval(uint32_t add_led_interval) { this->add_led_interval_ = add_led_interval; }
void set_reverse(bool reverse) { this->reverse_ = reverse; }
void apply(AddressableLight &it, const ESPColor &current_color) override {
void apply(AddressableLight &it, const Color &current_color) override {
const uint32_t now = millis();
if (now - this->last_add_ < this->add_led_interval_)
return;
@ -116,7 +116,7 @@ class AddressableColorWipeEffect : public AddressableLightEffect {
else
it.shift_right(1);
const AddressableColorWipeEffectColor color = this->colors_[this->at_color_];
const ESPColor esp_color = ESPColor(color.r, color.g, color.b, color.w);
const Color esp_color = Color(color.r, color.g, color.b, color.w);
if (this->reverse_)
it[-1] = esp_color;
else
@ -126,7 +126,7 @@ class AddressableColorWipeEffect : public AddressableLightEffect {
this->at_color_ = (this->at_color_ + 1) % this->colors_.size();
AddressableColorWipeEffectColor &new_color = this->colors_[this->at_color_];
if (new_color.random) {
ESPColor c = ESPColor::random_color();
Color c = Color::random_color();
new_color.r = c.r;
new_color.g = c.g;
new_color.b = c.b;
@ -148,8 +148,8 @@ class AddressableScanEffect : public AddressableLightEffect {
explicit AddressableScanEffect(const std::string &name) : AddressableLightEffect(name) {}
void set_move_interval(uint32_t move_interval) { this->move_interval_ = move_interval; }
void set_scan_width(uint32_t scan_width) { this->scan_width_ = scan_width; }
void apply(AddressableLight &it, const ESPColor &current_color) override {
it.all() = ESPColor::BLACK;
void apply(AddressableLight &it, const Color &current_color) override {
it.all() = COLOR_BLACK;
for (auto i = 0; i < this->scan_width_; i++) {
it[this->at_led_ + i] = current_color;
@ -181,7 +181,7 @@ class AddressableScanEffect : public AddressableLightEffect {
class AddressableTwinkleEffect : public AddressableLightEffect {
public:
explicit AddressableTwinkleEffect(const std::string &name) : AddressableLightEffect(name) {}
void apply(AddressableLight &addressable, const ESPColor &current_color) override {
void apply(AddressableLight &addressable, const Color &current_color) override {
const uint32_t now = millis();
uint8_t pos_add = 0;
if (now - this->last_progress_ > this->progress_interval_) {
@ -199,7 +199,7 @@ class AddressableTwinkleEffect : public AddressableLightEffect {
else
view.set_effect_data(new_pos);
} else {
view = ESPColor::BLACK;
view = COLOR_BLACK;
}
}
while (random_float() < this->twinkle_probability_) {
@ -221,7 +221,7 @@ class AddressableTwinkleEffect : public AddressableLightEffect {
class AddressableRandomTwinkleEffect : public AddressableLightEffect {
public:
explicit AddressableRandomTwinkleEffect(const std::string &name) : AddressableLightEffect(name) {}
void apply(AddressableLight &it, const ESPColor &current_color) override {
void apply(AddressableLight &it, const Color &current_color) override {
const uint32_t now = millis();
uint8_t pos_add = 0;
if (now - this->last_progress_ > this->progress_interval_) {
@ -237,7 +237,7 @@ class AddressableRandomTwinkleEffect : public AddressableLightEffect {
if (color == 0) {
view = current_color * sine;
} else {
view = ESPColor(((color >> 2) & 1) * sine, ((color >> 1) & 1) * sine, ((color >> 0) & 1) * sine);
view = Color(((color >> 2) & 1) * sine, ((color >> 1) & 1) * sine, ((color >> 0) & 1) * sine);
}
const uint8_t new_x = x + pos_add;
if (new_x > 0b11111)
@ -245,7 +245,7 @@ class AddressableRandomTwinkleEffect : public AddressableLightEffect {
else
view.set_effect_data((new_x << 3) | color);
} else {
view = ESPColor(0, 0, 0, 0);
view = Color(0, 0, 0, 0);
}
}
while (random_float() < this->twinkle_probability_) {
@ -270,9 +270,9 @@ class AddressableFireworksEffect : public AddressableLightEffect {
explicit AddressableFireworksEffect(const std::string &name) : AddressableLightEffect(name) {}
void start() override {
auto &it = *this->get_addressable_();
it.all() = ESPColor::BLACK;
it.all() = COLOR_BLACK;
}
void apply(AddressableLight &it, const ESPColor &current_color) override {
void apply(AddressableLight &it, const Color &current_color) override {
const uint32_t now = millis();
if (now - this->last_update_ < this->update_interval_)
return;
@ -280,7 +280,7 @@ class AddressableFireworksEffect : public AddressableLightEffect {
// "invert" the fade out parameter so that higher values make fade out faster
const uint8_t fade_out_mult = 255u - this->fade_out_rate_;
for (auto view : it) {
ESPColor target = view.get() * fade_out_mult;
Color target = view.get() * fade_out_mult;
if (target.r < 64)
target *= 170;
view = target;
@ -294,7 +294,7 @@ class AddressableFireworksEffect : public AddressableLightEffect {
if (random_float() < this->spark_probability_) {
const size_t pos = random_uint32() % it.size();
if (this->use_random_color_) {
it[pos] = ESPColor::random_color();
it[pos] = Color::random_color();
} else {
it[pos] = current_color;
}
@ -316,7 +316,7 @@ class AddressableFireworksEffect : public AddressableLightEffect {
class AddressableFlickerEffect : public AddressableLightEffect {
public:
explicit AddressableFlickerEffect(const std::string &name) : AddressableLightEffect(name) {}
void apply(AddressableLight &it, const ESPColor &current_color) override {
void apply(AddressableLight &it, const Color &current_color) override {
const uint32_t now = millis();
const uint8_t intensity = this->intensity_;
const uint8_t inv_intensity = 255 - intensity;

View File

@ -1,6 +1,7 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome import automation
from esphome.const import CONF_NAME, CONF_LAMBDA, CONF_UPDATE_INTERVAL, CONF_TRANSITION_LENGTH, \
CONF_COLORS, CONF_STATE, CONF_DURATION, CONF_BRIGHTNESS, CONF_RED, CONF_GREEN, CONF_BLUE, \
CONF_WHITE, CONF_ALPHA, CONF_INTENSITY, CONF_SPEED, CONF_WIDTH, CONF_NUM_LEDS, CONF_RANDOM, \
@ -11,7 +12,7 @@ from .types import LambdaLightEffect, RandomLightEffect, StrobeLightEffect, \
FlickerLightEffect, AddressableRainbowLightEffect, AddressableColorWipeEffect, \
AddressableColorWipeEffectColor, AddressableScanEffect, AddressableTwinkleEffect, \
AddressableRandomTwinkleEffect, AddressableFireworksEffect, AddressableFlickerEffect, \
AutomationLightEffect, ESPColor
AutomationLightEffect, Color
CONF_ADD_LED_INTERVAL = 'add_led_interval'
CONF_REVERSE = 'reverse'
@ -162,7 +163,7 @@ def flicker_effect_to_code(config, effect_id):
}
)
def addressable_lambda_effect_to_code(config, effect_id):
args = [(AddressableLightRef, 'it'), (ESPColor, 'current_color'), (bool, 'initial_run')]
args = [(AddressableLightRef, 'it'), (Color, 'current_color'), (bool, 'initial_run')]
lambda_ = yield cg.process_lambda(config[CONF_LAMBDA], args, return_type=cg.void)
var = cg.new_Pvariable(effect_id, config[CONF_NAME], lambda_,
config[CONF_UPDATE_INTERVAL])

View File

@ -10,7 +10,7 @@ LightOutput = light_ns.class_('LightOutput')
AddressableLight = light_ns.class_('AddressableLight', cg.Component)
AddressableLightRef = AddressableLight.operator('ref')
ESPColor = light_ns.class_('ESPColor')
Color = cg.esphome_ns.class_('Color')
LightColorValues = light_ns.class_('LightColorValues')
# Actions

View File

@ -2,6 +2,7 @@
#include "esphome/core/component.h"
#include "esphome/core/helpers.h"
#include "esphome/core/color.h"
#include "esphome/components/light/light_output.h"
#include "esphome/components/light/addressable_light.h"
@ -73,7 +74,7 @@ class NeoPixelBusLightOutputBase : public light::AddressableLight {
// ========== INTERNAL METHODS ==========
void setup() override {
for (int i = 0; i < this->size(); i++) {
(*this)[i] = light::ESPColor(0, 0, 0, 0);
(*this)[i] = Color(0, 0, 0, 0);
}
this->effect_data_ = new uint8_t[this->size()];

View File

@ -162,7 +162,7 @@ size_t SSD1322::get_buffer_length_() {
void HOT SSD1322::draw_absolute_pixel_internal(int x, int y, Color color) {
if (x >= this->get_width_internal() || x < 0 || y >= this->get_height_internal() || y < 0)
return;
uint32_t color4 = color.to_grayscale4();
uint32_t color4 = display::ColorUtil::color_to_grayscale4(color);
// where should the bits go in the big buffer array? math...
uint16_t pos = (x / SSD1322_PIXELSPERBYTE) + (y * this->get_width_internal() / SSD1322_PIXELSPERBYTE);
uint8_t shift = (1u - (x % SSD1322_PIXELSPERBYTE)) * SSD1322_COLORSHIFT;
@ -174,7 +174,7 @@ void HOT SSD1322::draw_absolute_pixel_internal(int x, int y, Color color) {
this->buffer_[pos] |= color4;
}
void SSD1322::fill(Color color) {
const uint32_t color4 = color.to_grayscale4();
const uint32_t color4 = display::ColorUtil::color_to_grayscale4(color);
uint8_t fill = (color4 & SSD1322_COLORMASK) | ((color4 & SSD1322_COLORMASK) << SSD1322_COLORSHIFT);
for (uint32_t i = 0; i < this->get_buffer_length_(); i++)
this->buffer_[i] = fill;

View File

@ -192,7 +192,7 @@ size_t SSD1325::get_buffer_length_() {
void HOT SSD1325::draw_absolute_pixel_internal(int x, int y, Color color) {
if (x >= this->get_width_internal() || x < 0 || y >= this->get_height_internal() || y < 0)
return;
uint32_t color4 = color.to_grayscale4();
uint32_t color4 = display::ColorUtil::color_to_grayscale4(color);
// where should the bits go in the big buffer array? math...
uint16_t pos = (x / SSD1325_PIXELSPERBYTE) + (y * this->get_width_internal() / SSD1325_PIXELSPERBYTE);
uint8_t shift = (x % SSD1325_PIXELSPERBYTE) * SSD1325_COLORSHIFT;
@ -204,7 +204,7 @@ void HOT SSD1325::draw_absolute_pixel_internal(int x, int y, Color color) {
this->buffer_[pos] |= color4;
}
void SSD1325::fill(Color color) {
const uint32_t color4 = color.to_grayscale4();
const uint32_t color4 = display::ColorUtil::color_to_grayscale4(color);
uint8_t fill = (color4 & SSD1325_COLORMASK) | ((color4 & SSD1325_COLORMASK) << SSD1325_COLORSHIFT);
for (uint32_t i = 0; i < this->get_buffer_length_(); i++)
this->buffer_[i] = fill;

View File

@ -136,7 +136,7 @@ size_t SSD1327::get_buffer_length_() {
void HOT SSD1327::draw_absolute_pixel_internal(int x, int y, Color color) {
if (x >= this->get_width_internal() || x < 0 || y >= this->get_height_internal() || y < 0)
return;
uint32_t color4 = color.to_grayscale4();
uint32_t color4 = display::ColorUtil::color_to_grayscale4(color);
// where should the bits go in the big buffer array? math...
uint16_t pos = (x / SSD1327_PIXELSPERBYTE) + (y * this->get_width_internal() / SSD1327_PIXELSPERBYTE);
uint8_t shift = (x % SSD1327_PIXELSPERBYTE) * SSD1327_COLORSHIFT;
@ -148,7 +148,7 @@ void HOT SSD1327::draw_absolute_pixel_internal(int x, int y, Color color) {
this->buffer_[pos] |= color4;
}
void SSD1327::fill(Color color) {
const uint32_t color4 = color.to_grayscale4();
const uint32_t color4 = display::ColorUtil::color_to_grayscale4(color);
uint8_t fill = (color4 & SSD1327_COLORMASK) | ((color4 & SSD1327_COLORMASK) << SSD1327_COLORSHIFT);
for (uint32_t i = 0; i < this->get_buffer_length_(); i++)
this->buffer_[i] = fill;

View File

@ -123,14 +123,14 @@ size_t SSD1331::get_buffer_length_() {
void HOT SSD1331::draw_absolute_pixel_internal(int x, int y, Color color) {
if (x >= this->get_width_internal() || x < 0 || y >= this->get_height_internal() || y < 0)
return;
const uint32_t color565 = color.to_rgb_565();
const uint32_t color565 = display::ColorUtil::color_to_565(color);
// where should the bits go in the big buffer array? math...
uint16_t pos = (x + y * this->get_width_internal()) * SSD1331_BYTESPERPIXEL;
this->buffer_[pos++] = (color565 >> 8) & 0xff;
this->buffer_[pos] = color565 & 0xff;
}
void SSD1331::fill(Color color) {
const uint32_t color565 = color.to_rgb_565();
const uint32_t color565 = display::ColorUtil::color_to_565(color);
for (uint32_t i = 0; i < this->get_buffer_length_(); i++)
if (i & 1) {
this->buffer_[i] = color565 & 0xff;

View File

@ -151,14 +151,14 @@ size_t SSD1351::get_buffer_length_() {
void HOT SSD1351::draw_absolute_pixel_internal(int x, int y, Color color) {
if (x >= this->get_width_internal() || x < 0 || y >= this->get_height_internal() || y < 0)
return;
const uint32_t color565 = color.to_rgb_565();
const uint32_t color565 = display::ColorUtil::color_to_565(color);
// where should the bits go in the big buffer array? math...
uint16_t pos = (x + y * this->get_width_internal()) * SSD1351_BYTESPERPIXEL;
this->buffer_[pos++] = (color565 >> 8) & 0xff;
this->buffer_[pos] = color565 & 0xff;
}
void SSD1351::fill(Color color) {
const uint32_t color565 = color.to_rgb_565();
const uint32_t color565 = display::ColorUtil::color_to_565(color);
for (uint32_t i = 0; i < this->get_buffer_length_(); i++)
if (i & 1) {
this->buffer_[i] = color565 & 0xff;

View File

@ -308,11 +308,11 @@ void HOT ST7735::draw_absolute_pixel_internal(int x, int y, Color color) {
return;
if (this->eightbitcolor_) {
const uint32_t color332 = color.to_332();
const uint32_t color332 = display::ColorUtil::color_to_332(color);
uint16_t pos = (x + y * this->get_width_internal());
this->buffer_[pos] = color332;
} else {
const uint32_t color565 = color.to_565();
const uint32_t color565 = display::ColorUtil::color_to_565(color);
uint16_t pos = (x + y * this->get_width_internal()) * 2;
this->buffer_[pos++] = (color565 >> 8) & 0xff;
this->buffer_[pos] = color565 & 0xff;
@ -444,9 +444,11 @@ void HOT ST7735::write_display_data_() {
if (this->eightbitcolor_) {
for (int line = 0; line < this->get_buffer_length(); line = line + this->get_width_internal()) {
for (int index = 0; index < this->get_width_internal(); ++index) {
auto color = Color(this->buffer_[index + line], Color::ColorOrder::COLOR_ORDER_RGB,
Color::ColorBitness::COLOR_BITNESS_332, true)
.to_565();
auto color332 = display::ColorUtil::to_color(this->buffer_[index + line], display::ColorOrder::COLOR_ORDER_RGB,
display::ColorBitness::COLOR_BITNESS_332, true);
auto color = display::ColorUtil::color_to_565(color332);
this->write_byte((color >> 8) & 0xff);
this->write_byte(color & 0xff);
}

View File

@ -263,7 +263,7 @@ void HOT ST7789V::draw_absolute_pixel_internal(int x, int y, Color color) {
if (x >= this->get_width_internal() || x < 0 || y >= this->get_height_internal() || y < 0)
return;
auto color565 = color.to_rgb_565();
auto color565 = display::ColorUtil::color_to_565(color);
uint16_t pos = (x + y * this->get_width_internal()) * 2;
this->buffer_[pos++] = (color565 >> 8) & 0xff;

View File

@ -40,11 +40,11 @@ void WLEDLightEffect::stop() {
void WLEDLightEffect::blank_all_leds_(light::AddressableLight &it) {
for (int led = it.size(); led-- > 0;) {
it[led].set(light::ESPColor::BLACK);
it[led].set(COLOR_BLACK);
}
}
void WLEDLightEffect::apply(light::AddressableLight &it, const light::ESPColor &current_color) {
void WLEDLightEffect::apply(light::AddressableLight &it, const Color &current_color) {
// Init UDP lazily
if (!udp_) {
udp_.reset(new WiFiUDP());
@ -152,7 +152,7 @@ bool WLEDLightEffect::parse_warls_frame_(light::AddressableLight &it, const uint
uint8_t b = payload[3];
if (led < max_leds) {
it[led].set(light::ESPColor(r, g, b));
it[led].set(Color(r, g, b));
}
}
@ -174,7 +174,7 @@ bool WLEDLightEffect::parse_drgb_frame_(light::AddressableLight &it, const uint8
uint8_t b = payload[2];
if (led < max_leds) {
it[led].set(light::ESPColor(r, g, b));
it[led].set(Color(r, g, b));
}
}
@ -197,7 +197,7 @@ bool WLEDLightEffect::parse_drgbw_frame_(light::AddressableLight &it, const uint
uint8_t w = payload[3];
if (led < max_leds) {
it[led].set(light::ESPColor(r, g, b, w));
it[led].set(Color(r, g, b, w));
}
}
@ -228,7 +228,7 @@ bool WLEDLightEffect::parse_dnrgb_frame_(light::AddressableLight &it, const uint
uint8_t b = payload[2];
if (led < max_leds) {
it[led].set(light::ESPColor(r, g, b));
it[led].set(Color(r, g, b));
}
}

View File

@ -18,7 +18,7 @@ class WLEDLightEffect : public light::AddressableLightEffect {
public:
void start() override;
void stop() override;
void apply(light::AddressableLight &it, const light::ESPColor &current_color) override;
void apply(light::AddressableLight &it, const Color &current_color) override;
void set_port(uint16_t port) { this->port_ = port; }
protected:

View File

@ -6,7 +6,6 @@
namespace esphome {
inline static uint8_t esp_scale8(uint8_t i, uint8_t scale) { return (uint16_t(i) * (1 + uint16_t(scale))) / 256; }
inline static uint8_t esp_scale(uint8_t i, uint8_t scale, uint8_t max_value = 255) { return (max_value * i / scale); }
struct Color {
union {
@ -31,75 +30,19 @@ struct Color {
uint8_t raw[4];
uint32_t raw_32;
};
enum ColorOrder : uint8_t { COLOR_ORDER_RGB = 0, COLOR_ORDER_BGR = 1, COLOR_ORDER_GRB = 2 };
enum ColorBitness : uint8_t { COLOR_BITNESS_888 = 0, COLOR_BITNESS_565 = 1, COLOR_BITNESS_332 = 2 };
inline Color() ALWAYS_INLINE : r(0), g(0), b(0), w(0) {} // NOLINT
inline Color(float red, float green, float blue) ALWAYS_INLINE : r(uint8_t(red * 255)),
g(uint8_t(green * 255)),
b(uint8_t(blue * 255)),
w(0) {}
inline Color(float red, float green, float blue, float white) ALWAYS_INLINE : r(uint8_t(red * 255)),
g(uint8_t(green * 255)),
b(uint8_t(blue * 255)),
w(uint8_t(white * 255)) {}
inline Color(uint8_t red, uint8_t green, uint8_t blue) ALWAYS_INLINE : r(red), g(green), b(blue), w(0) {}
inline Color(uint8_t red, uint8_t green, uint8_t blue, uint8_t white) ALWAYS_INLINE : r(red),
g(green),
b(blue),
w(white) {}
inline Color(uint32_t colorcode) ALWAYS_INLINE : r((colorcode >> 16) & 0xFF),
g((colorcode >> 8) & 0xFF),
b((colorcode >> 0) & 0xFF),
w((colorcode >> 24) & 0xFF) {}
inline Color(uint32_t colorcode, ColorOrder color_order, ColorBitness color_bitness = ColorBitness::COLOR_BITNESS_888,
bool right_bit_aligned = true) {
uint8_t first_color, second_color, third_color;
uint8_t first_bits = 0;
uint8_t second_bits = 0;
uint8_t third_bits = 0;
switch (color_bitness) {
case COLOR_BITNESS_888:
first_bits = 8;
second_bits = 8;
third_bits = 8;
break;
case COLOR_BITNESS_565:
first_bits = 5;
second_bits = 6;
third_bits = 5;
break;
case COLOR_BITNESS_332:
first_bits = 3;
second_bits = 3;
third_bits = 2;
break;
}
first_color = right_bit_aligned ? esp_scale(((colorcode >> (second_bits + third_bits)) & ((1 << first_bits) - 1)),
((1 << first_bits) - 1))
: esp_scale(((colorcode >> 16) & 0xFF), (1 << first_bits) - 1);
second_color = right_bit_aligned
? esp_scale(((colorcode >> third_bits) & ((1 << second_bits) - 1)), ((1 << second_bits) - 1))
: esp_scale(((colorcode >> 8) & 0xFF), ((1 << second_bits) - 1));
third_color = (right_bit_aligned ? esp_scale(((colorcode >> 0) & 0xFF), ((1 << third_bits) - 1))
: esp_scale(((colorcode >> 0) & 0xFF), (1 << third_bits) - 1));
switch (color_order) {
case COLOR_ORDER_RGB:
this->r = first_color;
this->g = second_color;
this->b = third_color;
break;
case COLOR_ORDER_BGR:
this->b = first_color;
this->g = second_color;
this->r = third_color;
break;
case COLOR_ORDER_GRB:
this->g = first_color;
this->r = second_color;
this->b = third_color;
break;
}
}
inline bool is_on() ALWAYS_INLINE { return this->raw_32 != 0; }
inline Color &operator=(const Color &rhs) ALWAYS_INLINE {
this->r = rhs.r;
@ -187,65 +130,21 @@ struct Color {
}
inline Color &operator-=(uint8_t subtract) ALWAYS_INLINE { return *this = (*this) - subtract; }
static Color random_color() {
float r = float(random_uint32()) / float(UINT32_MAX);
float g = float(random_uint32()) / float(UINT32_MAX);
float b = float(random_uint32()) / float(UINT32_MAX);
float w = float(random_uint32()) / float(UINT32_MAX);
return Color(r, g, b, w);
uint32_t rand = random_uint32();
uint8_t w = rand >> 24;
uint8_t r = rand >> 16;
uint8_t g = rand >> 8;
uint8_t b = rand >> 0;
const uint16_t max_rgb = std::max(r, std::max(g, b));
return Color(uint8_t((uint16_t(r) * 255U / max_rgb)), uint8_t((uint16_t(g) * 255U / max_rgb)),
uint8_t((uint16_t(b) * 255U / max_rgb)), w);
}
Color fade_to_white(uint8_t amnt) { return Color(1, 1, 1, 1) - (*this * amnt); }
Color fade_to_white(uint8_t amnt) { return Color(255, 255, 255, 255) - (*this * amnt); }
Color fade_to_black(uint8_t amnt) { return *this * amnt; }
Color lighten(uint8_t delta) { return *this + delta; }
Color darken(uint8_t delta) { return *this - delta; }
uint8_t to_332(ColorOrder color_order = ColorOrder::COLOR_ORDER_RGB) const {
uint16_t red_color, green_color, blue_color;
red_color = esp_scale8(this->red, ((1 << 3) - 1));
green_color = esp_scale8(this->green, ((1 << 3) - 1));
blue_color = esp_scale8(this->blue, (1 << 2) - 1);
switch (color_order) {
case COLOR_ORDER_RGB:
return red_color << 5 | green_color << 2 | blue_color;
case COLOR_ORDER_BGR:
return blue_color << 6 | green_color << 3 | red_color;
case COLOR_ORDER_GRB:
return green_color << 5 | red_color << 2 | blue_color;
}
return 0;
}
uint16_t to_565(ColorOrder color_order = ColorOrder::COLOR_ORDER_RGB) const {
uint16_t red_color, green_color, blue_color;
red_color = esp_scale8(this->red, ((1 << 5) - 1));
green_color = esp_scale8(this->green, ((1 << 6) - 1));
blue_color = esp_scale8(this->blue, (1 << 5) - 1);
switch (color_order) {
case COLOR_ORDER_RGB:
return red_color << 11 | green_color << 5 | blue_color;
case COLOR_ORDER_BGR:
return blue_color << 11 | green_color << 5 | red_color;
case COLOR_ORDER_GRB:
return green_color << 10 | red_color << 5 | blue_color;
}
return 0;
}
uint32_t to_rgb_565() const {
uint32_t color565 =
(esp_scale8(this->red, 31) << 11) | (esp_scale8(this->green, 63) << 5) | (esp_scale8(this->blue, 31) << 0);
return color565;
}
uint32_t to_bgr_565() const {
uint32_t color565 =
(esp_scale8(this->blue, 31) << 11) | (esp_scale8(this->green, 63) << 5) | (esp_scale8(this->red, 31) << 0);
return color565;
}
uint32_t to_grayscale4() const {
uint32_t gs4 = esp_scale8(this->white, 15);
return gs4;
}
};
static const Color COLOR_BLACK(0, 0, 0);
static const Color COLOR_WHITE(1, 1, 1);
static const Color COLOR_WHITE(255, 255, 255, 255);
}; // namespace esphome

View File

@ -1693,7 +1693,7 @@ interval:
color:
- id: kbx_red
red: 100%
green: 1%
green_int: 123
blue: 2%
- id: kbx_blue
red: 0%