PapyriX converts supported EPUB images for the active display.
EPUB HTML → ChapterHtmlSlimParser → ImageConverter → BMP Cache → GfxRenderer
- HTML Parsing: Finds
<img>tags. Getssrcandaltattributes. - Data URI Stripping: Removes embedded base64 images before XML parse (prevents OOM).
- Image Extraction: Gets the image from the EPUB ZIP to a temporary file.
- Conversion: Converts JPEG/PNG to BMP format.
- Caching: Stores the converted BMP on the SD card.
- Rendering: Shows the image in the center of the page.
An external cover image beside the book takes priority. Inside the EPUB, the reader checks explicit cover declarations before common filenames. It supports cover images, cover pages, guide references, and EPUB 3 cover landmarks. If memory is too low to read cover declarations, the reader tries common filenames.
A cover page can contain several images. The reader prefers the largest usable image and continues past missing or damaged candidates. Embedded cover images must not exceed 512 KiB. Cover pages must not exceed 64 KiB.
Valid cached covers and thumbnails remain available. A temporary cover read, write, or memory failure does not prevent a later attempt.
- JPEG (
.jpg,.jpeg) — Baseline on all devices; progressive on X4 Pro, X4 v2 Classic, and Sticky - PNG (
.png) — Transparency shown as opaque - BMP (
.bmp) — Direct display. No conversion is necessary.
The converter detects the format from the file contents. Filename extension case does not select the decoder.
All devices support baseline DCT (SOF0) and extended sequential DCT (SOF1).
X4 Pro, X4 v2 Classic, and Sticky also support progressive DCT (SOF2). Progressive images must use 8-bit grayscale or YCbCr samples. The compressed file must not exceed 512 KiB. Conversion requires sufficient PSRAM.
X3 and original X4 show a placeholder for progressive JPEGs. All devices reject arithmetic-coded JPEGs. Unsupported or damaged images show a placeholder.
To convert a progressive JPEG to baseline for X3 or original X4, use ImageMagick:
convert progressive.jpg -interlace none baseline.jpg- Max parse width: 2048px — Memory limit during decode
- Max parse height: 3072px — Memory limit during decode
- Max render height: viewport — Images taller than half the viewport get one page
- Min dimension: 20px — Images with width or height less than 20px are skipped. They are decorative.
- Min free heap: 8KB — Parse stops if memory goes below this
Images that are wider than the viewport are scaled down. Aspect ratio stays the same.
Images are shown when all these conditions are true:
- The
showImagessetting is on - The source path is valid and not empty
- The source is not a data URI
- The format is supported (JPEG/PNG/BMP)
- The file is in the EPUB archive
- Conversion completes
- Sufficient memory is available (8KB free or more)
- Fewer than 3 failures one after the other in the current chapter
- Unsupported format — Not JPEG/PNG/BMP (for example GIF, SVG, WebP, TIFF). Found by file extension before processing.
- Tiny decorative images — Width or height less than 20px (for example, 1px-tall JPEG line separators, small spacer PNGs, decorative borders). These are not visible on e-paper. They only use vertical space.
showImagesdisabled — User preference- Empty/malformed source — Invalid HTML
- Data URI source — Memory protection (see below)
- Unsupported JPEG encoding — Progressive on X3 or original X4; arithmetic coding on all devices
- File not found — Missing from the EPUB archive
- Conversion failure — Damaged file or I/O error
- Insufficient memory — Less than 8KB free heap
- Failure rate limit — 3 or more failures one after the other
Some EPUBs put images in as base64 data URIs:
<img src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEASABIAAD..." />DataUriStripper removes image data URIs before XML parsing. It replaces each matching src value with #. It accepts single quotes and double quotes. It matches the prefix without case sensitivity. It handles values that cross input buffer boundaries. The XML parser does not allocate the embedded image data.
lib/Epub/src/Epub/parsers/DataUriStripper.h
Images use <device-cache>/epub_<hash>/images/ on the SD card. The device cache root depends on the device.
<device-cache>/
└── epub_12345678/
└── images/
├── a1b2c3d4.bmp # Converted image
├── e5f6g7h8.bmp # Another converted image
└── i9j0k1l2.failed # Failed conversion marker
Cache filenames use an FNV-1a hash of the resolved image path:
- Input: Full path in the EPUB (for example,
OEBPS/images/cover.jpg) - Output: 8-character hex hash (for example,
a1b2c3d4.bmp)
The cache:
- Reuses one BMP for repeated references to the same resolved image path.
- Uses filenames that need no path escaping.
- Uses fixed-length filenames.
The image cache records a conversion error in an empty .failed marker. The marker prevents another conversion attempt on later loads. Clearing the book cache removes the marker.
To prevent a damaged EPUB from causing long delays, image processing uses a failure rate limit:
- Threshold: 3 failures one after the other
- Scope: For each chapter (resets when you go to a new spine item)
- Behavior: After the threshold, remaining images in the chapter show as placeholders
The converter checks the current free stack from the CPU stack pointer and the task's stack base. It stops below 4096 bytes on both ESP32-S3 and ESP32-C3. An earlier low stack watermark does not block conversion after the stack space becomes available again. BMP conversion also checks row-buffer memory when it needs more than 1024 bytes. It stops if the estimated buffers need more than 80% of the largest free 8-bit heap block.
The ESP32-S3 reader and cache tasks each use a 20 KiB stack. The ESP32-C3 reader and cache tasks each use a 12 KiB stack.
Image extraction uses a temporary file on the SD card:
- Extract from ZIP to a temporary file.
- Convert the temporary file to BMP.
- Delete the temporary file.
- Cache the BMP result.
This prevents the full source image from staying in RAM.
Settings > Reader > Show Images
- On (default): Images are shown in the text
- Off: All images show as
[Image: alt-text]placeholders
If you set images to off:
- Memory use decreases
- Page rendering is faster
- This is useful for reading that is mostly text
- Enable Settings > Reader > Show Images.
- Check that the image uses JPEG, PNG, or BMP format.
- Check the free space on the SD card.
- Clear the book cache (Settings > Cleanup > Clear Book Cache) after a conversion failure. A
.failedmarker prevents automatic retry.
- The first load converts images (slower).
- Later loads use the cache (faster).
- You can set images to off for faster reading.
- Large images can go above available RAM.
- Try a different EPUB with smaller images.
- Use xteink-epub-optimizer to change the image size.