源代码变更: - main/dzbj/bg_gif_demo.c/h: 方案 C 最终实现 - JPG 背景图(lv_img) + 透明 GIF(lv_gif) 叠加 - main/dzbj/dual_gif_demo.c/h: 方案 B 中间产物 - 双 GIF 循环切换 - main/dzbj/sprite_demo.c/h: 方案 A 已弃用 - DMA 直写 GRAM 与 LVGL 争抢 LCD IO 失败 - main/dzbj/ai_chat_ui.c: 集成 USE_BG_GIF_POC 开关,加载背景图+透明 GIF - main/dzbj/lcd.c: panel_handle 移除 static,便于其他模块访问 - main/CMakeLists.txt: 新增 3 个 dzbj 模块编译 资源新增: - spiffs_image/Background_360x360.jpg: 设备背景图(20KB) - spiffs_image/hiyori_m05.gif: Cubism Editor 直接导出的透明 GIF(2.3MB) - docs/Rtc_AIavatar/: Live2D 模型(Hiyori/Haru) + 32 段 Haru GIF + 方案文档第18章 PoC 实战记录 - tools/sprite_poc/: Python GIF→RGB565 转换脚本 踩坑要点(详见 docs/Rtc_AIavatar 第18章): - PIL Image.quantize() 会破坏 RGBA 透明度,必须改用 gifsicle - PIL 保存动画 GIF 仅第1帧有透明,后续帧不透明 - LVGL gifdec 按帧读取 - Cubism Editor 直接导出 GIF 才能逐帧保留透明信息(FREE 版限制部分模型) - gifsicle --lossy 会严重锯齿化,去掉只保留 --colors 256 + -O3 即可 - 裁剪居中需用全帧 bbox 不能只看第1帧(Live2D 角色每帧位置有偏移) - LVGL 默认不支持 PNG,背景图用 JPG + esp_jpeg 解码到 RGB565 buffer - 透明 GIF 显示黑色背景: gifdec.c canvas 初始化 alpha 须改为 0x00
37 lines
933 B
C
37 lines
933 B
C
/**
|
||
* bg_gif_demo.h — 背景图 + 透明 GIF 叠加显示(方案 C)
|
||
*
|
||
* 数据流:
|
||
* - 背景图(JPG)→ esp_jpeg 解码 RGB565 → lv_img(底层)
|
||
* - Hiyori GIF(带 Alpha 透明)→ PSRAM → lv_gif(上层叠加)
|
||
*
|
||
* 优势:
|
||
* - 背景图加载一次,常驻 PSRAM,不刷新
|
||
* - GIF 切换时仅刷新 GIF 区域,背景透出
|
||
* - 与 LVGL 字幕/UI 完美共存
|
||
*/
|
||
#pragma once
|
||
|
||
#include "esp_err.h"
|
||
#include <stdbool.h>
|
||
|
||
#ifdef __cplusplus
|
||
extern "C" {
|
||
#endif
|
||
|
||
/**
|
||
* 启动背景 + GIF 叠加显示
|
||
*
|
||
* @param bg_jpg_path 背景图 JPG 文件路径,例如 "/spiflash/Background_360x360.jpg"
|
||
* @param gif_path 透明 GIF 文件路径,例如 "/spiflash/hiyori_m05.gif"
|
||
* @return ESP_OK 成功
|
||
*/
|
||
esp_err_t bg_gif_demo_start(const char *bg_jpg_path, const char *gif_path);
|
||
|
||
void bg_gif_demo_stop(void);
|
||
bool bg_gif_demo_is_running(void);
|
||
|
||
#ifdef __cplusplus
|
||
}
|
||
#endif
|