| Supported Targets | ESP32-P4 | ESP32-S3 | ESP32-C3 | | ----------------- | -------- | -------- | -------- | # LVGL Image Decoder Example This example demonstrates how to decode and display multiple image formats using LVGL with the `esp_lv_decoder` component. It showcases efficient image handling for embedded displays, including memory-optimized split formats and hardware-accelerated decoding. ## Overview The example showcases: - **Multiple image format support**: JPG, PNG, QOI, Split-PNG (SPNG), Split-JPEG (SJPG), and PNG-JPEG (PJPG) - **Memory-mapped assets**: Store images in flash partitions for efficient access - **Split image formats**: Reduce RAM usage by decoding images in strips (SPNG/SJPG) - **Hardware acceleration**: Hardware JPEG decoding on ESP32-P4 - **Interactive format switching**: Cycle through different formats using button or encoder - **Automatic animation**: Images play continuously with format information display - **Responsive UI**: Adapts to various screen sizes (240x240 to 1024x600) ## Supported Image Formats | Format | Description | Chip Support | Memory Usage | Decode Speed | |--------|-------------|--------------|--------------|--------------| | **JPG** | Standard JPEG | ESP32-S3, ESP32-P4 | Medium | Fast | | **PNG** | Standard PNG | ESP32-S3, ESP32-P4 | High | Medium | | **QOI** | Quite OK Image | ESP32-S3, ESP32-P4 | Low | Very Fast | | **SPNG** | Split PNG (16-line strips) | All | Very Low | Medium | | **SJPG** | Split JPEG (16-line strips) | All | Very Low | Fast | | **PJPG** | PNG-JPEG | ESP32-P4 only | Low | Very Fast | ### Format Details **Standard Formats (JPG/PNG/QOI):** - Full image decoded into RAM buffer - Higher memory requirements - Faster rendering once decoded **Split Formats (SPNG/SJPG):** - Image divided into horizontal strips (16 pixels height) - Only one strip in RAM at a time - ~40x less RAM usage compared to full decode - Ideal for memory-constrained applications - Slight performance trade-off **Hardware-Accelerated (PJPG):** - Hardware JPEG decoding - Much faster than software decoding - Lower CPU usage ## How to Use the Example ### Hardware Required * A development board with: - **ESP32-P4**: All formats supported - **ESP32-S3**: All except PJPG - **ESP32-C3**: Only SPNG and SJPG (limited RAM) * A LCD panel with supported interface (MIPI DSI / RGB / QSPI / SPI) * (Optional) Touch panel or rotary encoder for interaction * A USB cable for power supply and programming **Recommended Hardware Combinations:** | Chip | LCD Interface | Development Board | |------|---------------|-------------------| | ESP32-P4 | MIPI DSI | [ESP32-P4-Function-EV-Board](https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32p4/esp32-p4-function-ev-board/index.html) | | ESP32-S3 | RGB | [ESP32-S3-LCD-EV-Board](https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32s3/esp32-s3-lcd-ev-board/index.html) | | ESP32-S3 | QSPI | [EchoEar](https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32s3/echoear/index.html) | | ESP32-S3 | SPI | [ESP32-S3-BOX-3](https://github.com/espressif/esp-box/blob/master/docs/hardware_overview/esp32_s3_box_3/hardware_overview_for_box_3.md) | | ESP32-C3 | SPI | [ESP32-C3-LCDkit](https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32c3/esp32-c3-lcdkit/index.html) | ### Hardware Connection This example uses the `hw_init` component for hardware abstraction. Refer to your board's documentation for LCD and touch panel connections. ### Image Asset Preparation This example includes sample images (8 frames of animation) in the `assets/` directory: - `assets/jpg/`: JPEG images (frame_0000.jpg to frame_0007.jpg) - `assets/png/`: PNG images (frame_0000.png to frame_0007.png) **The build system automatically:** 1. Converts images to various formats (QOI, SPNG, SJPG, PJPG) 2. Creates partition images for each format 3. Generates metadata headers (e.g., `mmap_generate_jpg.h`) 4. Flashes all partitions during `idf.py flash` **No manual conversion required!** Just provide the source JPG and PNG files. #### Adding Your Own Images To use custom images: 1. Place your images in `assets/jpg/` or `assets/png/` 2. Use consistent naming (e.g., `frame_XXXX.jpg`) 3. Recommended image properties: - Resolution: Match your LCD or smaller - Color depth: 24-bit RGB - File size: <50KB per image for best performance 4. The build system will automatically: - Generate split format variants - Update partition images - Regenerate metadata headers **Partition sizes:** - Each format partition: 100KB (defined in `partitions.csv`) - Adjust if you have many/large images ### Configure the Project Run `idf.py menuconfig` and navigate to `Example Configuration`: **LCD Interface:** - Select interface type (MIPI DSI / RGB / QSPI / SPI) - Configure resolution and GPIO pins **Display Settings:** - Choose rotation (0°/90°/180°/270°) **Input Device:** - Enable touch or encoder input **Image Decoder:** - Options are automatically selected based on target chip ### Build and Flash 1. Set the target chip: ```bash idf.py set-target esp32p4 # or esp32s3, esp32c3 ``` 2. Build and flash: ```bash idf.py -p PORT build flash monitor ``` **Build process:** - Compiles application - Generates image format partitions from assets - Creates metadata headers - Flashes application + all image partitions (6 partitions total) **First build takes longer** due to image processing and component downloads. (To exit the serial monitor, type ``Ctrl-]``.) See the [Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html) for full steps to configure and use ESP-IDF. ### Expected Output **LCD Display:** The screen shows: - **Top label**: Current format name and file count (e.g., "SPNG (8 files)") - **Center**: Animated image cycling through 8 frames - **Bottom button**: "Next Format" to switch image formats Images auto-play with smooth transitions (~50ms per frame). **Serial Console:** ``` I (xxx) decode_demo: LCD: MIPI DSI I (xxx) decode_demo: Init LCD 1024x600 I (xxx) decode_demo: Init touch I (xxx) decode_demo: SPNG ready (8 files) I (xxx) decode_demo: SJPG ready (8 files) I (xxx) decode_demo: PJPG ready (8 files) // ESP32-P4 only ``` **Interaction:** - **Touch**: Tap "Next Format" button to switch formats - **Encoder**: Rotate encoder (accumulate 3 clicks) then press button to switch - Format cycles through available options based on chip **Chip-Specific Behavior:** - **ESP32-P4**: All formats available (JPG → PNG → QOI → SPNG → SJPG → PJPG) - **ESP32-S3**: 5 formats (JPG → PNG → QOI → SPNG → SJPG) - **ESP32-C3**: 2 formats only (SPNG → SJPG) ## Code Structure **Main Components:** 1. **Format Context** (`image_format_ctx_t`): - Each format has: label, partition name, drive letter, file count - Tracks current playback index - Manages mmap assets and filesystem handles 2. **Image Player** (`image_player_ctx_t`): - Controls format switching - Updates UI labels - Manages playback timer - Handles encoder accumulation 3. **Format Mounting** (`mount_format()`): - Initializes mmap_assets for partition - Mounts virtual filesystem (drive letters: J, P, Q, S, T, U) - Validates stored files 4. **UI Creation** (`start_image_player()`): - Creates LVGL image widget - Sets up format label and button - Configures encoder group - Starts 50ms timer for frame updates **Key Functions:** - `show_next_frame()`: Updates image widget source (e.g., "S:frame_0001.png") - `next_available_format()`: Cycles to next valid format - `prepare_formats()`: Mounts all available format partitions ## Partition Layout ``` Partition Table (partitions.csv): ┌──────────────────────────────────────┐ │ nvs (24KB) │ │ phy_init (4KB) │ │ factory (1000KB) - Application │ │ jpg (100KB) - JPEG images │ ← 8 JPG files │ png (100KB) - PNG images │ ← 8 PNG files │ qoi (100KB) - QOI images │ ← 8 QOI (converted) │ spng (100KB) - Split PNG │ ← 8 SPNG (converted) │ sjpg (100KB) - Split JPEG │ ← 8 SJPG (converted) │ pjpg (100KB) - PJPEG │ ← 8 PJPG (converted, ESP32-P4) └──────────────────────────────────────┘ ``` **Total flash usage**: ~1.6MB (adjust partition sizes if needed) ## Technical Details ### Split Image Format SPNG/SJPG splits images horizontally: ``` Original Image (480x320) ┌─────────────────────┐ │ Strip 0 (480x16) │ ← Decoded to RAM ├─────────────────────┤ │ Strip 1 (480x16) │ ← Decoded when needed ├─────────────────────┤ │ Strip 2 (480x16) │ │ ... │ │ Strip 19 (480x16) │ └─────────────────────┘ ``` **Configuration:** - `MMAP_SPLIT_HEIGHT 16`: Each strip is 16 pixels tall - Smaller strips = less RAM, more decode operations - Optimal for most embedded displays ### Virtual Filesystem Mapping Each format gets a drive letter: ```c 'J' → JPG partition → "J:frame_0000.jpg" 'P' → PNG partition → "P:frame_0000.png" 'Q' → QOI partition → "Q:frame_0000.png" 'S' → SPNG partition → "S:frame_0000.png" 'T' → SJPG partition → "T:frame_0000.jpg" 'U' → PJPG partition → "U:frame_0000.png" ``` LVGL image widget loads from virtual path. ## Troubleshooting **Images not showing:** - Check serial logs for "Failed to mount" errors - Verify partition table flashed: `idf.py partition-table` - Ensure assets exist in `assets/jpg/` and `assets/png/` - Rebuild to regenerate partition images **Build error: "Partition too small":** - Images exceed 100KB per partition - Reduce image sizes or increase partition size in `partitions.csv` - Use compression (JPEG quality 85-90) **Poor animation performance:** - Reduce image resolution - Increase timer interval in code (currently 50ms) - Enable PSRAM if available **Format switching doesn't work:** - Check that partitions flashed successfully - Verify touch/encoder input works - Look for "No other format available" in logs - Some formats may be unavailable on your chip **PJPG not available:** - Only supported on ESP32-P4 **Memory allocation failures:** - Enable PSRAM for large displays - Use split formats (SPNG/SJPG) instead - Reduce LVGL buffer sizes **Encoder not switching formats:** - Requires 3 rotation steps (threshold) - Adjust `ENCODER_THRESHOLD` if too sensitive - Check encoder GPIO configuration ## Choosing the Right Format **For ESP32-P4:** - Use **PJPG** for best performance (hardware accelerated) - Use **SJPG** if PJPG not available **For ESP32-S3:** - Use **SJPG** for good balance (low RAM, fast) - Use **JPG** if you have PSRAM and need speed **For ESP32-C3:** - Use **SJPG** for save memory resources - Keep images small For any technical queries, please open an [issue](https://github.com/espressif/esp-iot-solution/issues) on GitHub. We will get back to you soon.
To create a project from this example, run:
idf.py create-project-from-example "espressif/esp_lvgl_adapter=0.1.0-beta.1:lvgl_decode_image"