ESPHome  2025.2.0
jpeg_image.cpp
Go to the documentation of this file.
1 #include "jpeg_image.h"
2 #ifdef USE_ONLINE_IMAGE_JPEG_SUPPORT
3 
6 #include "esphome/core/helpers.h"
7 #include "esphome/core/log.h"
8 
9 #include "online_image.h"
10 static const char *const TAG = "online_image.jpeg";
11 
12 namespace esphome {
13 namespace online_image {
14 
21 static int draw_callback(JPEGDRAW *jpeg) {
22  ImageDecoder *decoder = (ImageDecoder *) jpeg->pUser;
23 
24  // Some very big images take too long to decode, so feed the watchdog on each callback
25  // to avoid crashing.
26  App.feed_wdt();
27  size_t position = 0;
28  for (size_t y = 0; y < jpeg->iHeight; y++) {
29  for (size_t x = 0; x < jpeg->iWidth; x++) {
30  auto rg = decode_value(jpeg->pPixels[position++]);
31  auto ba = decode_value(jpeg->pPixels[position++]);
32  Color color(rg[1], rg[0], ba[1], ba[0]);
33 
34  if (!decoder) {
35  ESP_LOGE(TAG, "Decoder pointer is null!");
36  return 0;
37  }
38  decoder->draw(jpeg->x + x, jpeg->y + y, 1, 1, color);
39  }
40  }
41  return 1;
42 }
43 
44 int JpegDecoder::prepare(size_t download_size) {
45  ImageDecoder::prepare(download_size);
46  auto size = this->image_->resize_download_buffer(download_size);
47  if (size < download_size) {
48  ESP_LOGE(TAG, "Download buffer resize failed!");
50  }
51  return 0;
52 }
53 
54 int HOT JpegDecoder::decode(uint8_t *buffer, size_t size) {
55  if (size < this->download_size_) {
56  ESP_LOGV(TAG, "Download not complete. Size: %d/%d", size, this->download_size_);
57  return 0;
58  }
59 
60  if (!this->jpeg_.openRAM(buffer, size, draw_callback)) {
61  ESP_LOGE(TAG, "Could not open image for decoding: %d", this->jpeg_.getLastError());
63  }
64  auto jpeg_type = this->jpeg_.getJPEGType();
65  if (jpeg_type == JPEG_MODE_INVALID) {
66  ESP_LOGE(TAG, "Unsupported JPEG image");
68  } else if (jpeg_type == JPEG_MODE_PROGRESSIVE) {
69  ESP_LOGE(TAG, "Progressive JPEG images not supported");
71  }
72  ESP_LOGD(TAG, "Image size: %d x %d, bpp: %d", this->jpeg_.getWidth(), this->jpeg_.getHeight(), this->jpeg_.getBpp());
73 
74  this->jpeg_.setUserPointer(this);
75  this->jpeg_.setPixelType(RGB8888);
76  if (!this->set_size(this->jpeg_.getWidth(), this->jpeg_.getHeight())) {
78  }
79  if (!this->jpeg_.decode(0, 0, 0)) {
80  ESP_LOGE(TAG, "Error while decoding.");
81  this->jpeg_.close();
83  }
84  this->decoded_bytes_ = size;
85  this->jpeg_.close();
86  return size;
87 }
88 
89 } // namespace online_image
90 } // namespace esphome
91 
92 #endif // USE_ONLINE_IMAGE_JPEG_SUPPORT
uint16_t x
Definition: tt21100.cpp:17
int prepare(size_t download_size) override
Definition: jpeg_image.cpp:44
virtual int prepare(size_t download_size)
Initialize the decoder.
Definition: image_decoder.h:34
uint16_t y
Definition: tt21100.cpp:18
constexpr14 std::array< uint8_t, sizeof(T)> decode_value(T val)
Decode a value into its constituent bytes (from most to least significant).
Definition: helpers.h:221
Application App
Global storage of Application pointer - only one Application can exist.
size_t resize_download_buffer(size_t size)
Resize the download buffer.
Definition: online_image.h:87
bool set_size(int width, int height)
Request the image to be resized once the actual dimensions are known.
Implementation of SPI Controller mode.
Definition: a01nyub.cpp:7
float position
Definition: cover.h:14
int HOT decode(uint8_t *buffer, size_t size) override
Definition: jpeg_image.cpp:54