ESPHome 2026.3.0-dev
Loading...
Searching...
No Matches
jpeg_decoder.cpp
Go to the documentation of this file.
1#include "jpeg_decoder.h"
2#ifdef USE_RUNTIME_IMAGE_JPEG
3
8#include "esphome/core/log.h"
9
10#ifdef USE_ESP_IDF
11#include "esp_task_wdt.h"
12#endif
13
14static const char *const TAG = "image_decoder.jpeg";
15
16namespace esphome::runtime_image {
17
24static int draw_callback(JPEGDRAW *jpeg) {
25 ImageDecoder *decoder = (ImageDecoder *) jpeg->pUser;
26
27 // Some very big images take too long to decode, so feed the watchdog on each callback
28 // to avoid crashing if the executing task has a watchdog enabled.
29#ifdef USE_ESP_IDF
30 if (esp_task_wdt_status(nullptr) == ESP_OK) {
31#endif
32 App.feed_wdt();
33#ifdef USE_ESP_IDF
34 }
35#endif
36 size_t position = 0;
37 size_t height = static_cast<size_t>(jpeg->iHeight);
38 size_t width = static_cast<size_t>(jpeg->iWidth);
39 for (size_t y = 0; y < height; y++) {
40 for (size_t x = 0; x < width; x++) {
41 auto rg = decode_value(jpeg->pPixels[position++]);
42 auto ba = decode_value(jpeg->pPixels[position++]);
43 Color color(rg[1], rg[0], ba[1], ba[0]);
44
45 if (!decoder) {
46 ESP_LOGE(TAG, "Decoder pointer is null!");
47 return 0;
48 }
49 decoder->draw(jpeg->x + x, jpeg->y + y, 1, 1, color);
50 }
51 }
52 return 1;
53}
54
55int JpegDecoder::prepare(size_t expected_size) {
56 ImageDecoder::prepare(expected_size);
57 // JPEG decoder needs complete data before decoding
58 return 0;
59}
60
61int HOT JpegDecoder::decode(uint8_t *buffer, size_t size) {
62 // JPEG decoder requires complete data
63 // If we know the expected size, wait for it
65 ESP_LOGV(TAG, "Download not complete. Size: %zu/%zu", size, this->expected_size_);
66 return 0;
67 }
68
69 // If size unknown, try to decode and see if it's valid
70 // The JPEGDEC library will fail gracefully if data is incomplete
71
72 if (!this->jpeg_.openRAM(buffer, size, draw_callback)) {
73 ESP_LOGE(TAG, "Could not open image for decoding: %d", this->jpeg_.getLastError());
75 }
76 auto jpeg_type = this->jpeg_.getJPEGType();
77 if (jpeg_type == JPEG_MODE_INVALID) {
78 ESP_LOGE(TAG, "Unsupported JPEG image");
80 } else if (jpeg_type == JPEG_MODE_PROGRESSIVE) {
81 ESP_LOGE(TAG, "Progressive JPEG images not supported");
83 }
84 ESP_LOGD(TAG, "Image size: %d x %d, bpp: %d", this->jpeg_.getWidth(), this->jpeg_.getHeight(), this->jpeg_.getBpp());
85
86 this->jpeg_.setUserPointer(this);
87 this->jpeg_.setPixelType(RGB8888);
88 if (!this->set_size(this->jpeg_.getWidth(), this->jpeg_.getHeight())) {
90 }
91 if (!this->jpeg_.decode(0, 0, 0)) {
92 ESP_LOGE(TAG, "Error while decoding.");
93 this->jpeg_.close();
95 }
96 this->decoded_bytes_ = size;
97 this->jpeg_.close();
98 return size;
99}
100
101} // namespace esphome::runtime_image
102
103#endif // USE_RUNTIME_IMAGE_JPEG
void feed_wdt(uint32_t time=0)
bool set_size(int width, int height)
Request the image to be resized once the actual dimensions are known.
virtual int prepare(size_t expected_size)
Initialize the decoder.
int prepare(size_t expected_size) override
int HOT decode(uint8_t *buffer, size_t size) override
float position
Definition cover.h:0
size_t size
Definition helpers.h:729
constexpr 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:557
Application App
Global storage of Application pointer - only one Application can exist.
uint16_t x
Definition tt21100.cpp:5
uint16_t y
Definition tt21100.cpp:6