mirror of
https://github.com/esphome/esphome.git
synced 2025-10-29 22:24:26 +00:00
[image][online_image][animation] Fix transparency in RGB565 (#7631)
This commit is contained in:
@@ -361,24 +361,21 @@ async def to_code(config):
|
||||
elif config[CONF_TYPE] in ["RGB565"]:
|
||||
image = image.convert("RGBA")
|
||||
pixels = list(image.getdata())
|
||||
data = [0 for _ in range(height * width * 2)]
|
||||
bytes_per_pixel = 3 if transparent else 2
|
||||
data = [0 for _ in range(height * width * bytes_per_pixel)]
|
||||
pos = 0
|
||||
for r, g, b, a in pixels:
|
||||
R = r >> 3
|
||||
G = g >> 2
|
||||
B = b >> 3
|
||||
rgb = (R << 11) | (G << 5) | B
|
||||
|
||||
if transparent:
|
||||
if rgb == 0x0020:
|
||||
rgb = 0
|
||||
if a < 0x80:
|
||||
rgb = 0x0020
|
||||
|
||||
data[pos] = rgb >> 8
|
||||
pos += 1
|
||||
data[pos] = rgb & 0xFF
|
||||
pos += 1
|
||||
if transparent:
|
||||
data[pos] = a
|
||||
pos += 1
|
||||
|
||||
elif config[CONF_TYPE] in ["BINARY", "TRANSPARENT_BINARY"]:
|
||||
if transparent:
|
||||
|
||||
@@ -88,7 +88,7 @@ lv_img_dsc_t *Image::get_lv_img_dsc() {
|
||||
this->dsc_.header.reserved = 0;
|
||||
this->dsc_.header.w = this->width_;
|
||||
this->dsc_.header.h = this->height_;
|
||||
this->dsc_.data_size = image_type_to_width_stride(this->dsc_.header.w * this->dsc_.header.h, this->get_type());
|
||||
this->dsc_.data_size = this->get_width_stride() * this->get_height();
|
||||
switch (this->get_type()) {
|
||||
case IMAGE_TYPE_BINARY:
|
||||
this->dsc_.header.cf = LV_IMG_CF_ALPHA_1BIT;
|
||||
@@ -104,17 +104,17 @@ lv_img_dsc_t *Image::get_lv_img_dsc() {
|
||||
|
||||
case IMAGE_TYPE_RGB565:
|
||||
#if LV_COLOR_DEPTH == 16
|
||||
this->dsc_.header.cf = this->has_transparency() ? LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED : LV_IMG_CF_TRUE_COLOR;
|
||||
this->dsc_.header.cf = this->has_transparency() ? LV_IMG_CF_TRUE_COLOR_ALPHA : LV_IMG_CF_TRUE_COLOR;
|
||||
#else
|
||||
this->dsc_.header.cf = LV_IMG_CF_RGB565;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case image::IMAGE_TYPE_RGBA:
|
||||
case IMAGE_TYPE_RGBA:
|
||||
#if LV_COLOR_DEPTH == 32
|
||||
this->dsc_.header.cf = LV_IMG_CF_TRUE_COLOR;
|
||||
#else
|
||||
this->dsc_.header.cf = LV_IMG_CF_RGBA8888;
|
||||
this->dsc_.header.cf = LV_IMG_CF_TRUE_COLOR_ALPHA;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
@@ -147,21 +147,21 @@ Color Image::get_rgb24_pixel_(int x, int y) const {
|
||||
return color;
|
||||
}
|
||||
Color Image::get_rgb565_pixel_(int x, int y) const {
|
||||
const uint32_t pos = (x + y * this->width_) * 2;
|
||||
uint16_t rgb565 =
|
||||
progmem_read_byte(this->data_start_ + pos + 0) << 8 | progmem_read_byte(this->data_start_ + pos + 1);
|
||||
const uint8_t *pos = this->data_start_;
|
||||
if (this->transparent_) {
|
||||
pos += (x + y * this->width_) * 3;
|
||||
} else {
|
||||
pos += (x + y * this->width_) * 2;
|
||||
}
|
||||
uint16_t rgb565 = encode_uint16(progmem_read_byte(pos), progmem_read_byte(pos + 1));
|
||||
auto r = (rgb565 & 0xF800) >> 11;
|
||||
auto g = (rgb565 & 0x07E0) >> 5;
|
||||
auto b = rgb565 & 0x001F;
|
||||
Color color = Color((r << 3) | (r >> 2), (g << 2) | (g >> 4), (b << 3) | (b >> 2));
|
||||
if (rgb565 == 0x0020 && transparent_) {
|
||||
// darkest green has been defined as transparent color for transparent RGB565 images.
|
||||
color.w = 0;
|
||||
} else {
|
||||
color.w = 0xFF;
|
||||
}
|
||||
auto a = this->transparent_ ? progmem_read_byte(pos + 2) : 0xFF;
|
||||
Color color = Color((r << 3) | (r >> 2), (g << 2) | (g >> 4), (b << 3) | (b >> 2), a);
|
||||
return color;
|
||||
}
|
||||
|
||||
Color Image::get_grayscale_pixel_(int x, int y) const {
|
||||
const uint32_t pos = (x + y * this->width_);
|
||||
const uint8_t gray = progmem_read_byte(this->data_start_ + pos);
|
||||
|
||||
@@ -17,24 +17,6 @@ enum ImageType {
|
||||
IMAGE_TYPE_RGBA = 4,
|
||||
};
|
||||
|
||||
inline int image_type_to_bpp(ImageType type) {
|
||||
switch (type) {
|
||||
case IMAGE_TYPE_BINARY:
|
||||
return 1;
|
||||
case IMAGE_TYPE_GRAYSCALE:
|
||||
return 8;
|
||||
case IMAGE_TYPE_RGB565:
|
||||
return 16;
|
||||
case IMAGE_TYPE_RGB24:
|
||||
return 24;
|
||||
case IMAGE_TYPE_RGBA:
|
||||
return 32;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline int image_type_to_width_stride(int width, ImageType type) { return (width * image_type_to_bpp(type) + 7u) / 8u; }
|
||||
|
||||
class Image : public display::BaseImage {
|
||||
public:
|
||||
Image(const uint8_t *data_start, int width, int height, ImageType type);
|
||||
@@ -44,6 +26,25 @@ class Image : public display::BaseImage {
|
||||
const uint8_t *get_data_start() const { return this->data_start_; }
|
||||
ImageType get_type() const;
|
||||
|
||||
int get_bpp() const {
|
||||
switch (this->type_) {
|
||||
case IMAGE_TYPE_BINARY:
|
||||
return 1;
|
||||
case IMAGE_TYPE_GRAYSCALE:
|
||||
return 8;
|
||||
case IMAGE_TYPE_RGB565:
|
||||
return this->transparent_ ? 24 : 16;
|
||||
case IMAGE_TYPE_RGB24:
|
||||
return 24;
|
||||
case IMAGE_TYPE_RGBA:
|
||||
return 32;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// Return the stride of the image in bytes, that is, the distance in bytes
|
||||
/// between two consecutive rows of pixels.
|
||||
uint32_t get_width_stride() const { return (this->width_ * this->get_bpp() + 7u) / 8u; }
|
||||
void draw(int x, int y, display::Display *display, Color color_on, Color color_off) override;
|
||||
|
||||
void set_transparency(bool transparent) { transparent_ = transparent; }
|
||||
|
||||
Reference in New Issue
Block a user