[image] Blend grayscale alpha with Color::gradient (#19356)

This commit is contained in:
J. Nick Koston
2026-09-17 08:17:28 -05:00
committed by GitHub
parent 508c24c5e3
commit 05bba3fdc2
3 changed files with 19 additions and 20 deletions
+5 -7
View File
@@ -48,14 +48,12 @@ void Image::draw(int x, int y, display::Display *display, Color color_on, Color
continue; // skip drawing
}
break;
case TRANSPARENCY_ALPHA_CHANNEL: {
auto on = (float) gray / 255.0f;
auto off = 1.0f - on;
// blend color_on and color_off
color = Color(color_on.r * on + color_off.r * off, color_on.g * on + color_off.g * off,
color_on.b * on + color_off.b * off, 0xFF);
case TRANSPARENCY_ALPHA_CHANNEL:
// gray is the alpha: blend from color_off to color_on, drawn opaque
color = Color(Color::blend_channel(color_off.r, color_on.r, gray),
Color::blend_channel(color_off.g, color_on.g, gray),
Color::blend_channel(color_off.b, color_on.b, gray), 0xFF);
break;
}
default:
break;
}
+5 -10
View File
@@ -6,18 +6,13 @@ namespace esphome {
constinit const Color Color::BLACK(0, 0, 0, 0);
constinit const Color Color::WHITE(255, 255, 255, 255);
Color Color::gradient(const Color &to_color, uint8_t amnt) {
uint8_t inv = 255 - amnt;
Color new_color;
new_color.r = (uint16_t(this->r) * inv + uint16_t(to_color.r) * amnt) / 255;
new_color.g = (uint16_t(this->g) * inv + uint16_t(to_color.g) * amnt) / 255;
new_color.b = (uint16_t(this->b) * inv + uint16_t(to_color.b) * amnt) / 255;
new_color.w = (uint16_t(this->w) * inv + uint16_t(to_color.w) * amnt) / 255;
return new_color;
Color Color::gradient(const Color &to_color, uint8_t amnt) const {
return Color(blend_channel(this->r, to_color.r, amnt), blend_channel(this->g, to_color.g, amnt),
blend_channel(this->b, to_color.b, amnt), blend_channel(this->w, to_color.w, amnt));
}
Color Color::fade_to_white(uint8_t amnt) { return this->gradient(Color::WHITE, amnt); }
Color Color::fade_to_white(uint8_t amnt) const { return this->gradient(Color::WHITE, amnt); }
Color Color::fade_to_black(uint8_t amnt) { return this->gradient(Color::BLACK, amnt); }
Color Color::fade_to_black(uint8_t amnt) const { return this->gradient(Color::BLACK, amnt); }
} // namespace esphome
+9 -3
View File
@@ -174,9 +174,15 @@ struct Color {
uint8_t((uint16_t(b) * 255U / max_rgb)), w);
}
Color gradient(const Color &to_color, uint8_t amnt);
Color fade_to_white(uint8_t amnt);
Color fade_to_black(uint8_t amnt);
/// One channel of gradient(): from at amnt 0 to to at amnt 255. Inline so a
/// per pixel loop can blend without a call; gradient() itself stays out of
/// line so the light effects and fade_to_*() share one copy.
static inline uint8_t blend_channel(uint8_t from, uint8_t to, uint8_t amnt) ESPHOME_ALWAYS_INLINE {
return (uint16_t(from) * (255 - amnt) + uint16_t(to) * amnt) / 255;
}
Color gradient(const Color &to_color, uint8_t amnt) const;
Color fade_to_white(uint8_t amnt) const;
Color fade_to_black(uint8_t amnt) const;
Color lighten(uint8_t delta) { return *this + delta; }
Color darken(uint8_t delta) { return *this - delta; }