ESPHome's online_image component loads a picture from a URL and shows it on a display, for example a camera snapshot, album art or a weather map. On 22 and 23 October 2026 three related changes by Clyde Stubbs were merged into the development branch (2026.11.0-dev). Together they cut the memory a JPEG download needs and let a display show how far the download has got. They should ship in ESPHome 2026.11.
Less RAM for the same picture
Until now, online_image first downloaded the whole file into a buffer and only then started decoding. A 200 KB JPEG needed 200 KB of contiguous RAM on top of the buffer for the decoded image, and decoding ran as one long call. On an ESP32 without much free RAM, that can decide whether a large image loads at all.
With #21342, a JPEG whose server sends a Content-Length header is decoded as it arrives. The download buffer only has to hold the image headers, and the decoder works in short steps of at most 20 ms per pass of the main loop, so the rest of the device keeps running. If the headers do not fit in the buffer, the log says to increase buffer_size. A JPEG without Content-Length is still downloaded completely before decoding.
A new JPEG library
The groundwork is in #21341. ESPHome now takes the JPEGDEC library from its own fork, esphome-libs/JPEGDEC. The pull request says the original project has had no release since 1.8.4 and outside fixes sit unmerged. The fork adds decoding one row of blocks at a time, waiting for more data instead of decoding garbage, and fixes for short reads and grayscale images. It also turns on the ESP32-S3 SIMD colour conversion for ESP-IDF builds, which until now JPEGDEC used only with Arduino. On an ESP32-S3, full-size decodes are 12-19% faster, and building the library with -O2 adds another 3-5%. The fixes have also been offered upstream.
Download progress on screen
The third change, #21355, adds two triggers:
on_download_startedruns when the server accepts the request, but not on a 304 response or an HTTP error.on_download_progressreportsprogressas a percentage andbytes_read. It runs with 0 at the start, at most every 100 ms while data arrives, and once more for the last bytes, so a progress bar always reaches 100%. WithoutContent-Length,progressisNAN.
The author tested the triggers on a LilyGo T-Display S3 Pro, driving an LVGL progress bar during six downloads. The whole set of changes was also tested on an ESP32-S3 display and with unit tests. Decoding during the download applies only to JPEG, not to other image formats.