5 static const char *
const TAG =
"online_image";
9 #ifdef USE_ONLINE_IMAGE_BMP_SUPPORT 12 #ifdef USE_ONLINE_IMAGE_JPEG_SUPPORT 15 #ifdef USE_ONLINE_IMAGE_PNG_SUPPORT 20 namespace online_image {
30 return ((color.
r >> 2) + (color.
g >> 1) + (color.
b >> 2)) & 0x80;
35 : Image(nullptr, 0, 0, type, transparency),
37 download_buffer_(download_buffer_size),
38 download_buffer_initial_size_(download_buffer_size),
41 fixed_height_(height) {
47 Image::draw(x, y, display, color_on, color_off);
55 ESP_LOGV(TAG,
"Deallocating old buffer...");
82 ESP_LOGD(TAG,
"Allocating new buffer of %zu bytes", new_size);
85 ESP_LOGE(TAG,
"allocation of %zu bytes failed. Biggest block in heap: %zu Bytes", new_size,
93 ESP_LOGV(TAG,
"New size: (%d, %d)", width, height);
99 ESP_LOGW(TAG,
"Image already being updated.");
102 ESP_LOGI(TAG,
"Updating image %s", this->
url_.c_str());
104 std::list<http_request::Header> headers = {};
107 accept_header.
name =
"Accept";
108 std::string accept_mime_type;
110 #ifdef USE_ONLINE_IMAGE_BMP_SUPPORT 112 accept_mime_type =
"image/bmp";
114 #endif // ONLINE_IMAGE_BMP_SUPPORT 115 #ifdef USE_ONLINE_IMAGE_JPEG_SUPPORT 117 accept_mime_type =
"image/jpeg";
119 #endif // USE_ONLINE_IMAGE_JPEG_SUPPORT 120 #ifdef USE_ONLINE_IMAGE_PNG_SUPPORT 122 accept_mime_type =
"image/png";
124 #endif // ONLINE_IMAGE_PNG_SUPPORT 126 accept_mime_type =
"image/*";
128 accept_header.
value = accept_mime_type +
",*/*;q=0.8";
130 headers.push_back(accept_header);
135 ESP_LOGE(TAG,
"Download failed.");
142 if (http_code == HTTP_CODE_NOT_MODIFIED) {
147 if (http_code != HTTP_CODE_OK) {
148 ESP_LOGE(TAG,
"HTTP result: %d", http_code);
154 ESP_LOGD(TAG,
"Starting download");
155 size_t total_size = this->
downloader_->content_length;
157 #ifdef USE_ONLINE_IMAGE_BMP_SUPPORT 159 ESP_LOGD(TAG,
"Allocating BMP decoder");
160 this->
decoder_ = make_unique<BmpDecoder>(
this);
162 #endif // ONLINE_IMAGE_BMP_SUPPORT 163 #ifdef USE_ONLINE_IMAGE_JPEG_SUPPORT 165 ESP_LOGD(TAG,
"Allocating JPEG decoder");
166 this->
decoder_ = esphome::make_unique<JpegDecoder>(
this);
168 #endif // USE_ONLINE_IMAGE_JPEG_SUPPORT 169 #ifdef USE_ONLINE_IMAGE_PNG_SUPPORT 171 ESP_LOGD(TAG,
"Allocating PNG decoder");
172 this->
decoder_ = make_unique<PngDecoder>(
this);
174 #endif // ONLINE_IMAGE_PNG_SUPPORT 177 ESP_LOGE(TAG,
"Could not instantiate decoder. Image format unsupported: %d", this->
format_);
182 auto prepare_result = this->
decoder_->prepare(total_size);
183 if (prepare_result < 0) {
188 ESP_LOGI(TAG,
"Downloading image (Size: %d)", total_size);
201 ESP_LOGD(TAG,
"Image fully downloaded, read %zu bytes, width/height = %d/%d", this->
downloader_->get_bytes_read(),
203 ESP_LOGD(TAG,
"Total time: %lds", ::time(
nullptr) - this->
start_time_);
209 ESP_LOGE(TAG,
"Downloader not instantiated; cannot download");
223 ESP_LOGE(TAG,
"Error when decoding image.");
235 if (color.
g == 1 && color.
r == 0 && color.
b == 0) {
238 if (color.
w < 0x80) {
248 ESP_LOGE(TAG,
"Buffer not allocated!");
252 ESP_LOGE(TAG,
"Tried to paint a pixel (%d,%d) outside the image!", x, y);
256 switch (this->
type_) {
258 const uint32_t width_8 = ((this->
width_ + 7u) / 8u) * 8u;
259 pos = x + y * width_8;
260 auto bitno = 0x80 >> (pos % 8u);
273 uint8_t gray =
static_cast<uint8_t
>(0.2125 * color.
r + 0.7154 * color.
g + 0.0721 * color.
b);
278 if (color.
w < 0x80) {
291 this->
buffer_[pos + 0] =
static_cast<uint8_t
>((col565 >> 8) & 0xFF);
292 this->
buffer_[pos + 1] =
static_cast<uint8_t
>(col565 & 0xFF);
321 if ((url.length() < 8) || (url.find(
"http") != 0) || (url.find(
"://") == std::string::npos)) {
322 ESP_LOGE(TAG,
"URL is invalid and/or must be prefixed with 'http://' or 'https://'");
bool has_transparency() const
bool validate_url_(const std::string &url)
void draw_pixel_(int x, int y, Color color)
Draw a pixel into the buffer.
size_t get_max_free_block_size() const
Return the maximum size block this allocator could allocate.
std::shared_ptr< HttpContainer > get(std::string url)
int buffer_width_
Actual width of the current image.
void add_on_finished_callback(std::function< void()> &&callback)
static uint16_t color_to_565(Color color, ColorOrder color_order=ColorOrder::COLOR_ORDER_RGB)
OnlineImage(const std::string &url, int width, int height, ImageFormat format, image::ImageType type, image::Transparency transparency, uint32_t buffer_size)
Construct a new OnlineImage object.
const int fixed_height_
height requested on configuration, or 0 if non specified.
std::unique_ptr< ImageDecoder > decoder_
void set_url(const std::string &url)
Set the URL to download the image from.
int buffer_height_
Actual height of the current image.
const int fixed_width_
width requested on configuration, or 0 if non specified.
DownloadBuffer download_buffer_
std::shared_ptr< http_request::HttpContainer > downloader_
void add_on_error_callback(std::function< void()> &&callback)
esphome::http_request::HttpRequestComponent * parent_
bool is_color_on(const Color &color)
size_t free_capacity() const
CallbackManager< void()> download_error_callback_
size_t download_buffer_initial_size_
This is the initial size of the download buffer, not the current size.
size_t resize_(int width, int height)
Resize the image buffer to the requested dimensions.
void map_chroma_key(Color &color)
const uint8_t * data_start_
void deallocate(T *p, size_t n)
uint8_t * data(size_t offset=0)
CallbackManager< void()> download_finished_callback_
void release()
Release the buffer storing the image.
int get_position_(int x, int y) const
Transparency transparency_
image::Image * placeholder_
void draw(int x, int y, display::Display *display, Color color_on, Color color_off) override
Implementation of SPI Controller mode.
const ImageFormat format_
void draw(int x, int y, display::Display *display, Color color_on, Color color_off) override
ImageFormat
Format that the image is encoded with.
RAMAllocator< uint8_t > allocator_
uint32_t get_buffer_size_() const
ESPHOME_ALWAYS_INLINE bool is_auto_resize_() const