mirror of
https://github.com/esphome/esphome.git
synced 2024-11-26 17:05:21 +01:00
added RGB565 image type (#3229)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
This commit is contained in:
parent
ebf13a0ba0
commit
68dfaf238b
4 changed files with 74 additions and 0 deletions
|
@ -92,6 +92,29 @@ async def to_code(config):
|
||||||
data[pos] = pix[2]
|
data[pos] = pix[2]
|
||||||
pos += 1
|
pos += 1
|
||||||
|
|
||||||
|
elif config[CONF_TYPE] == "RGB565":
|
||||||
|
data = [0 for _ in range(height * width * 2 * frames)]
|
||||||
|
pos = 0
|
||||||
|
for frameIndex in range(frames):
|
||||||
|
image.seek(frameIndex)
|
||||||
|
frame = image.convert("RGB")
|
||||||
|
if CONF_RESIZE in config:
|
||||||
|
frame = frame.resize([width, height])
|
||||||
|
pixels = list(frame.getdata())
|
||||||
|
if len(pixels) != height * width:
|
||||||
|
raise core.EsphomeError(
|
||||||
|
f"Unexpected number of pixels in {path} frame {frameIndex}: ({len(pixels)} != {height*width})"
|
||||||
|
)
|
||||||
|
for pix in pixels:
|
||||||
|
R = pix[0] >> 3
|
||||||
|
G = pix[1] >> 2
|
||||||
|
B = pix[2] >> 3
|
||||||
|
rgb = (R << 11) | (G << 5) | B
|
||||||
|
data[pos] = rgb >> 8
|
||||||
|
pos += 1
|
||||||
|
data[pos] = rgb & 255
|
||||||
|
pos += 1
|
||||||
|
|
||||||
elif config[CONF_TYPE] == "BINARY":
|
elif config[CONF_TYPE] == "BINARY":
|
||||||
width8 = ((width + 7) // 8) * 8
|
width8 = ((width + 7) // 8) * 8
|
||||||
data = [0 for _ in range((height * width8 // 8) * frames)]
|
data = [0 for _ in range((height * width8 // 8) * frames)]
|
||||||
|
|
|
@ -242,6 +242,13 @@ void DisplayBuffer::image(int x, int y, Image *image, Color color_on, Color colo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case IMAGE_TYPE_RGB565:
|
||||||
|
for (int img_x = 0; img_x < image->get_width(); img_x++) {
|
||||||
|
for (int img_y = 0; img_y < image->get_height(); img_y++) {
|
||||||
|
this->draw_pixel_at(x + img_x, y + img_y, image->get_rgb565_pixel(img_x, img_y));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -497,6 +504,17 @@ Color Image::get_color_pixel(int x, int y) const {
|
||||||
(progmem_read_byte(this->data_start_ + pos + 0) << 16);
|
(progmem_read_byte(this->data_start_ + pos + 0) << 16);
|
||||||
return Color(color32);
|
return Color(color32);
|
||||||
}
|
}
|
||||||
|
Color Image::get_rgb565_pixel(int x, int y) const {
|
||||||
|
if (x < 0 || x >= this->width_ || y < 0 || y >= this->height_)
|
||||||
|
return Color::BLACK;
|
||||||
|
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);
|
||||||
|
auto r = (rgb565 & 0xF800) >> 11;
|
||||||
|
auto g = (rgb565 & 0x07E0) >> 5;
|
||||||
|
auto b = rgb565 & 0x001F;
|
||||||
|
return Color((r << 3) | (r >> 2), (g << 2) | (g >> 4), (b << 3) | (b >> 2));
|
||||||
|
}
|
||||||
Color Image::get_grayscale_pixel(int x, int y) const {
|
Color Image::get_grayscale_pixel(int x, int y) const {
|
||||||
if (x < 0 || x >= this->width_ || y < 0 || y >= this->height_)
|
if (x < 0 || x >= this->width_ || y < 0 || y >= this->height_)
|
||||||
return Color::BLACK;
|
return Color::BLACK;
|
||||||
|
@ -532,6 +550,20 @@ Color Animation::get_color_pixel(int x, int y) const {
|
||||||
(progmem_read_byte(this->data_start_ + pos + 0) << 16);
|
(progmem_read_byte(this->data_start_ + pos + 0) << 16);
|
||||||
return Color(color32);
|
return Color(color32);
|
||||||
}
|
}
|
||||||
|
Color Animation::get_rgb565_pixel(int x, int y) const {
|
||||||
|
if (x < 0 || x >= this->width_ || y < 0 || y >= this->height_)
|
||||||
|
return Color::BLACK;
|
||||||
|
const uint32_t frame_index = this->width_ * this->height_ * this->current_frame_;
|
||||||
|
if (frame_index >= (uint32_t)(this->width_ * this->height_ * this->animation_frame_count_))
|
||||||
|
return Color::BLACK;
|
||||||
|
const uint32_t pos = (x + y * this->width_ + frame_index) * 2;
|
||||||
|
uint16_t rgb565 =
|
||||||
|
progmem_read_byte(this->data_start_ + pos + 0) << 8 | progmem_read_byte(this->data_start_ + pos + 1);
|
||||||
|
auto r = (rgb565 & 0xF800) >> 11;
|
||||||
|
auto g = (rgb565 & 0x07E0) >> 5;
|
||||||
|
auto b = rgb565 & 0x001F;
|
||||||
|
return Color((r << 3) | (r >> 2), (g << 2) | (g >> 4), (b << 3) | (b >> 2));
|
||||||
|
}
|
||||||
Color Animation::get_grayscale_pixel(int x, int y) const {
|
Color Animation::get_grayscale_pixel(int x, int y) const {
|
||||||
if (x < 0 || x >= this->width_ || y < 0 || y >= this->height_)
|
if (x < 0 || x >= this->width_ || y < 0 || y >= this->height_)
|
||||||
return Color::BLACK;
|
return Color::BLACK;
|
||||||
|
|
|
@ -82,6 +82,7 @@ enum ImageType {
|
||||||
IMAGE_TYPE_GRAYSCALE = 1,
|
IMAGE_TYPE_GRAYSCALE = 1,
|
||||||
IMAGE_TYPE_RGB24 = 2,
|
IMAGE_TYPE_RGB24 = 2,
|
||||||
IMAGE_TYPE_TRANSPARENT_BINARY = 3,
|
IMAGE_TYPE_TRANSPARENT_BINARY = 3,
|
||||||
|
IMAGE_TYPE_RGB565 = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum DisplayRotation {
|
enum DisplayRotation {
|
||||||
|
@ -453,6 +454,7 @@ class Image {
|
||||||
Image(const uint8_t *data_start, int width, int height, ImageType type);
|
Image(const uint8_t *data_start, int width, int height, ImageType type);
|
||||||
virtual bool get_pixel(int x, int y) const;
|
virtual bool get_pixel(int x, int y) const;
|
||||||
virtual Color get_color_pixel(int x, int y) const;
|
virtual Color get_color_pixel(int x, int y) const;
|
||||||
|
virtual Color get_rgb565_pixel(int x, int y) const;
|
||||||
virtual Color get_grayscale_pixel(int x, int y) const;
|
virtual Color get_grayscale_pixel(int x, int y) const;
|
||||||
int get_width() const;
|
int get_width() const;
|
||||||
int get_height() const;
|
int get_height() const;
|
||||||
|
@ -470,6 +472,7 @@ class Animation : public Image {
|
||||||
Animation(const uint8_t *data_start, int width, int height, uint32_t animation_frame_count, ImageType type);
|
Animation(const uint8_t *data_start, int width, int height, uint32_t animation_frame_count, ImageType type);
|
||||||
bool get_pixel(int x, int y) const override;
|
bool get_pixel(int x, int y) const override;
|
||||||
Color get_color_pixel(int x, int y) const override;
|
Color get_color_pixel(int x, int y) const override;
|
||||||
|
Color get_rgb565_pixel(int x, int y) const override;
|
||||||
Color get_grayscale_pixel(int x, int y) const override;
|
Color get_grayscale_pixel(int x, int y) const override;
|
||||||
|
|
||||||
int get_animation_frame_count() const;
|
int get_animation_frame_count() const;
|
||||||
|
|
|
@ -25,6 +25,7 @@ IMAGE_TYPE = {
|
||||||
"GRAYSCALE": ImageType.IMAGE_TYPE_GRAYSCALE,
|
"GRAYSCALE": ImageType.IMAGE_TYPE_GRAYSCALE,
|
||||||
"RGB24": ImageType.IMAGE_TYPE_RGB24,
|
"RGB24": ImageType.IMAGE_TYPE_RGB24,
|
||||||
"TRANSPARENT_BINARY": ImageType.IMAGE_TYPE_TRANSPARENT_BINARY,
|
"TRANSPARENT_BINARY": ImageType.IMAGE_TYPE_TRANSPARENT_BINARY,
|
||||||
|
"RGB565": ImageType.IMAGE_TYPE_RGB565,
|
||||||
}
|
}
|
||||||
|
|
||||||
Image_ = display.display_ns.class_("Image")
|
Image_ = display.display_ns.class_("Image")
|
||||||
|
@ -89,6 +90,21 @@ async def to_code(config):
|
||||||
data[pos] = pix[2]
|
data[pos] = pix[2]
|
||||||
pos += 1
|
pos += 1
|
||||||
|
|
||||||
|
elif config[CONF_TYPE] == "RGB565":
|
||||||
|
image = image.convert("RGB")
|
||||||
|
pixels = list(image.getdata())
|
||||||
|
data = [0 for _ in range(height * width * 3)]
|
||||||
|
pos = 0
|
||||||
|
for pix in pixels:
|
||||||
|
R = pix[0] >> 3
|
||||||
|
G = pix[1] >> 2
|
||||||
|
B = pix[2] >> 3
|
||||||
|
rgb = (R << 11) | (G << 5) | B
|
||||||
|
data[pos] = rgb >> 8
|
||||||
|
pos += 1
|
||||||
|
data[pos] = rgb & 255
|
||||||
|
pos += 1
|
||||||
|
|
||||||
elif config[CONF_TYPE] == "BINARY":
|
elif config[CONF_TYPE] == "BINARY":
|
||||||
image = image.convert("1", dither=dither)
|
image = image.convert("1", dither=dither)
|
||||||
width8 = ((width + 7) // 8) * 8
|
width8 = ((width + 7) // 8) * 8
|
||||||
|
|
Loading…
Reference in a new issue