From 3e412f8231bcd24c24781ad5eee8463bb685e7ec Mon Sep 17 00:00:00 2001 From: patri Date: Fri, 23 Oct 2026 00:27:33 +0200 Subject: [PATCH] Fix LVGL GIF decoder: start with transparent canvas LVGL 8.3.11 gifdec filled the initial canvas opaque with the GIF background color, so transparent-background GIFs (loligod.gif) showed dark gray until 'restore to background' frames cleared each area to the screen color. Co-Authored-By: Claude Opus 5.5 --- .../library/lvgl/src/extra/libs/gif/gifdec.c | 12 ++++++++---- CLAUDE.md | 4 +++- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/2-Program Example/Demo_Arduino/library/lvgl/src/extra/libs/gif/gifdec.c b/2-Program Example/Demo_Arduino/library/lvgl/src/extra/libs/gif/gifdec.c index 3ee9b71..0a20f8f 100644 --- a/2-Program Example/Demo_Arduino/library/lvgl/src/extra/libs/gif/gifdec.c +++ b/2-Program Example/Demo_Arduino/library/lvgl/src/extra/libs/gif/gifdec.c @@ -138,25 +138,29 @@ static gd_GIF * gif_open(gd_GIF * gif_base) } bgcolor = &gif->palette->colors[gif->bgindex*3]; + /* LOCAL PATCH (JC3636W518 project): start with a fully transparent canvas (alpha 0x00 + * instead of 0xff). Upstream filled it opaque with the background color, so GIFs with a + * transparent background showed that color until a "restore to background" frame cleared + * each area. Non-transparent GIFs are unaffected: their first frame paints every pixel. */ for (i = 0; i < gif->width * gif->height; i++) { #if LV_COLOR_DEPTH == 32 gif->canvas[i*4 + 0] = *(bgcolor + 2); gif->canvas[i*4 + 1] = *(bgcolor + 1); gif->canvas[i*4 + 2] = *(bgcolor + 0); - gif->canvas[i*4 + 3] = 0xff; + gif->canvas[i*4 + 3] = 0x00; #elif LV_COLOR_DEPTH == 16 lv_color_t c = lv_color_make(*(bgcolor + 0), *(bgcolor + 1), *(bgcolor + 2)); gif->canvas[i*3 + 0] = c.full & 0xff; gif->canvas[i*3 + 1] = (c.full >> 8) & 0xff; - gif->canvas[i*3 + 2] = 0xff; + gif->canvas[i*3 + 2] = 0x00; #elif LV_COLOR_DEPTH == 8 lv_color_t c = lv_color_make(*(bgcolor + 0), *(bgcolor + 1), *(bgcolor + 2)); gif->canvas[i*2 + 0] = c.full; - gif->canvas[i*2 + 1] = 0xff; + gif->canvas[i*2 + 1] = 0x00; #elif LV_COLOR_DEPTH == 1 lv_color_t c = lv_color_make(*(bgcolor + 0), *(bgcolor + 1), *(bgcolor + 2)); gif->canvas[i*2 + 0] = c.ch.red > 128 ? 1 : 0; - gif->canvas[i*2 + 1] = 0xff; + gif->canvas[i*2 + 1] = 0x00; #endif } gif->anim_start = f_gif_seek(gif, 0, LV_FS_SEEK_CUR); diff --git a/CLAUDE.md b/CLAUDE.md index 66d06ec..1530ba1 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -94,7 +94,9 @@ AliExpress "ELM327 Mini V2.1 Bluetooth OBD **Dual Mode** 5.1" — dual mode = Bl Cheap dual-mode clones typically expose BLE service `FFF0` (notify `FFF1`, write `FFF2`) — **not yet verified** on this adapter; scan it first. Adapter is powered from the car's OBD port (pin 16, 12 V). ## Gotchas / observations -- **GIF transparency → black background:** almost all GIFs in `10-OBD-Display-2024/assets/gifs` are *optimized* (frames mark unchanged pixels transparent, disposal 1/2). LVGL 8.3's gifdec shows the screen background (black in the sketches) wherever no frame has painted yet. Fix by using un-optimized GIFs (full frames, no transparency) or a non-black screen background. +- **LVGL GIF bug (patched locally):** LVGL 8.3.11 `gifdec.c` (`gd_open_gif`) filled the canvas *opaque* with the GIF's background color. GIFs with a transparent background (e.g. `loligod.gif`, bg = RGB 28,29,49) showed that dark gray except where "restore to background" frames had cleared to transparent (→ screen black). **Patched** in the vendor copy `2-Program Example/Demo_Arduino/library/lvgl/src/extra/libs/gif/gifdec.c`: initial canvas alpha 0x00 (marked `LOCAL PATCH`). Re-apply if LVGL is ever replaced/upgraded. +- Most GIFs in `assets/gifs` are optimized (transparent unchanged pixels, disposal 1/2); `loligod.gif` has a fully transparent background (~84 % of each frame). +- LVGL version: all JC3636W518 projects use the vendor-bundled **LVGL 8.3.11**. LVGL 9 would require porting `scr_st77916.h` (display/touch driver glue). - Display is round: corners of the 360×360 framebuffer are not visible — design UI within a 360 px circle. - Compiling a 13.9 MB GIF into the firmware will not fit "Huge APP" (3 MB); large media should live on SD (or in a custom partition). - The top-level demo `setup()` returns early if no SD card is present, before showing anything.