From 78e8001aa8c30415b6a285132ad30f1dbf00347f Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Tue, 15 Jul 2025 12:09:18 +1000 Subject: [PATCH] [online_image] Support `byte_order` (#9502) --- esphome/components/online_image/__init__.py | 5 ++++- esphome/components/online_image/online_image.cpp | 16 +++++++++++----- esphome/components/online_image/online_image.h | 7 ++++++- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/esphome/components/online_image/__init__.py b/esphome/components/online_image/__init__.py index 3f15db6e50..7a6d25bc7d 100644 --- a/esphome/components/online_image/__init__.py +++ b/esphome/components/online_image/__init__.py @@ -2,7 +2,7 @@ import logging from esphome import automation import esphome.codegen as cg -from esphome.components.const import CONF_REQUEST_HEADERS +from esphome.components.const import CONF_BYTE_ORDER, CONF_REQUEST_HEADERS from esphome.components.http_request import CONF_HTTP_REQUEST_ID, HttpRequestComponent from esphome.components.image import ( CONF_INVERT_ALPHA, @@ -11,6 +11,7 @@ from esphome.components.image import ( Image_, get_image_type_enum, get_transparency_enum, + validate_settings, ) import esphome.config_validation as cv from esphome.const import ( @@ -161,6 +162,7 @@ CONFIG_SCHEMA = cv.Schema( rp2040_arduino=cv.Version(0, 0, 0), host=cv.Version(0, 0, 0), ), + validate_settings, ) ) @@ -213,6 +215,7 @@ async def to_code(config): get_image_type_enum(config[CONF_TYPE]), transparent, config[CONF_BUFFER_SIZE], + config.get(CONF_BYTE_ORDER) != "LITTLE_ENDIAN", ) await cg.register_component(var, config) await cg.register_parented(var, config[CONF_HTTP_REQUEST_ID]) diff --git a/esphome/components/online_image/online_image.cpp b/esphome/components/online_image/online_image.cpp index d0c743ef93..4e2ecc2c77 100644 --- a/esphome/components/online_image/online_image.cpp +++ b/esphome/components/online_image/online_image.cpp @@ -35,14 +35,15 @@ inline bool is_color_on(const Color &color) { } OnlineImage::OnlineImage(const std::string &url, int width, int height, ImageFormat format, ImageType type, - image::Transparency transparency, uint32_t download_buffer_size) + image::Transparency transparency, uint32_t download_buffer_size, bool is_big_endian) : Image(nullptr, 0, 0, type, transparency), buffer_(nullptr), download_buffer_(download_buffer_size), download_buffer_initial_size_(download_buffer_size), format_(format), fixed_width_(width), - fixed_height_(height) { + fixed_height_(height), + is_big_endian_(is_big_endian) { this->set_url(url); } @@ -296,7 +297,7 @@ void OnlineImage::draw_pixel_(int x, int y, Color color) { break; } case ImageType::IMAGE_TYPE_GRAYSCALE: { - uint8_t gray = static_cast(0.2125 * color.r + 0.7154 * color.g + 0.0721 * color.b); + auto gray = static_cast(0.2125 * color.r + 0.7154 * color.g + 0.0721 * color.b); if (this->transparency_ == image::TRANSPARENCY_CHROMA_KEY) { if (gray == 1) { gray = 0; @@ -314,8 +315,13 @@ void OnlineImage::draw_pixel_(int x, int y, Color color) { case ImageType::IMAGE_TYPE_RGB565: { this->map_chroma_key(color); uint16_t col565 = display::ColorUtil::color_to_565(color); - this->buffer_[pos + 0] = static_cast((col565 >> 8) & 0xFF); - this->buffer_[pos + 1] = static_cast(col565 & 0xFF); + if (this->is_big_endian_) { + this->buffer_[pos + 0] = static_cast((col565 >> 8) & 0xFF); + this->buffer_[pos + 1] = static_cast(col565 & 0xFF); + } else { + this->buffer_[pos + 0] = static_cast(col565 & 0xFF); + this->buffer_[pos + 1] = static_cast((col565 >> 8) & 0xFF); + } if (this->transparency_ == image::TRANSPARENCY_ALPHA_CHANNEL) { this->buffer_[pos + 2] = color.w; } diff --git a/esphome/components/online_image/online_image.h b/esphome/components/online_image/online_image.h index 6a2144538f..3326cbe8d6 100644 --- a/esphome/components/online_image/online_image.h +++ b/esphome/components/online_image/online_image.h @@ -50,7 +50,7 @@ class OnlineImage : public PollingComponent, * @param buffer_size Size of the buffer used to download the image. */ OnlineImage(const std::string &url, int width, int height, ImageFormat format, image::ImageType type, - image::Transparency transparency, uint32_t buffer_size); + image::Transparency transparency, uint32_t buffer_size, bool is_big_endian); void draw(int x, int y, display::Display *display, Color color_on, Color color_off) override; @@ -164,6 +164,11 @@ class OnlineImage : public PollingComponent, const int fixed_width_; /** height requested on configuration, or 0 if non specified. */ const int fixed_height_; + /** + * Whether the image is stored in big-endian format. + * This is used to determine how to store 16 bit colors in the buffer. + */ + bool is_big_endian_; /** * Actual width of the current image. If fixed_width_ is specified, * this will be equal to it; otherwise it will be set once the decoding