I4 Format Canvas Implementation: Best Practices and Buffer Requirements

Hi @kisvegabor,

I’m working on memory optimization for a 128x128 SSD1327 grayscale OLED display using ESP32-S3 with LVGL 9.3. Currently using RGB565 format but exploring I4 (4-bit indexed) format for significant memory savings.

Context:

I’ve successfully implemented a hybrid approach where LVGL uses standard RGB565 canvas with partial double buffering (8KB total), and my display driver converts RGB565 → I4 during transmission. This works perfectly and gives me the memory savings I need.

However, I’m curious about implementing native I4 canvas support for even greater memory efficiency, and ran into some questions during our experiments.

Questions for the community:

  1. Official I4 Support: Is LV_COLOR_FORMAT_I4 fully supported for canvas creation in LVGL 9.3? The documentation mentions it exists, but I’m unclear about canvas-specific usage.

  2. Buffer Sizing: When creating I4 canvas, what’s the exact buffer size formula? I calculated (width × height ÷ 2) + palette_size, but want to confirm the palette storage requirements.

  3. Palette Setup: What’s the proper way to set up the 16-color palette for I4 format? I used lv_canvas_set_palette() but encountered some inconsistencies.

  4. Software Renderer: Does the default software renderer support I4 → RGB565 blending? I noticed LV_DRAW_SW_SUPPORT_I4 configuration but it’s unclear if it’s fully implemented.

  5. Canvas Pixel Functions: Are lv_canvas_set_px_color() and similar functions compatible with I4 canvas, or do they require special handling for indexed formats?

What I’ve observed:

  • I4 canvas creation sometimes falls back to other formats silently
  • Buffer allocation occasionally fails even with correctly calculated sizes
  • Compilation issues with certain canvas pixel manipulation functions

Goal:

I’d love to understand the “official” way to implement I4 canvas if it’s a supported use case, or confirmation that my hybrid RGB565 → I4 approach is the recommended pattern for memory-constrained applications.

Worth mentioning that we’ve long-since committed to a local project fork of LVGL specifically so that we can experiment with this kind of optimization.

Any insights, examples, or documentation pointers would be greatly appreciated. Happy to expand at length on any point above that could be helpful.

Thanks,
Pete

Hardware: ESP32-S3, 128x128 SSD1327 OLED, LVGL 9.3

Hi,

Sorry for the late reply. The short answer is I! is not supported by the SW renderer directly.

LVGL can render I4 images though, but it converts them to ARGB8888 at runtime. That is indexed images are supported as source buffer, but not as destination buffer.

In I1 is supported as destination buffer format to support monochrome displays.

I4 canvas creation sometimes falls back to other formats silently

Yes, that’s what I mentioned above (fallback to ARGB8888)

Buffer allocation occasionally fails even with correctly calculated sizes

Can it be a simple out of memory issue? Is it better if you increase LV_MEM_SIZE?

Compilation issues with certain canvas pixel manipulation functions

Can you share more details about it? Which functions fail?