源代码变更: - 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
47 lines
791 B
C
47 lines
791 B
C
/**
|
||
* sprite_demo.h — Sprite Sheet PoC
|
||
*
|
||
* 从 SPIFFS 加载 RGB565 raw sprite pack 到 PSRAM,
|
||
* 通过 DMA 直接写 LCD GRAM 实现零 CPU 解码的动画播放。
|
||
*/
|
||
#pragma once
|
||
|
||
#include "esp_err.h"
|
||
#include <stdbool.h>
|
||
|
||
#ifdef __cplusplus
|
||
extern "C" {
|
||
#endif
|
||
|
||
/**
|
||
* 加载并开始播放 sprite pack
|
||
*
|
||
* @param path SPIFFS 路径,例如 "/spiflash/sprite_test.bin"
|
||
* @return ESP_OK 成功
|
||
*/
|
||
esp_err_t sprite_demo_start(const char *path);
|
||
|
||
/**
|
||
* 暂停播放(停止帧定时器,但保留 PSRAM 数据)
|
||
*/
|
||
void sprite_demo_pause(void);
|
||
|
||
/**
|
||
* 恢复播放
|
||
*/
|
||
void sprite_demo_resume(void);
|
||
|
||
/**
|
||
* 停止播放并释放 PSRAM
|
||
*/
|
||
void sprite_demo_stop(void);
|
||
|
||
/**
|
||
* 检查是否正在播放
|
||
*/
|
||
bool sprite_demo_is_playing(void);
|
||
|
||
#ifdef __cplusplus
|
||
}
|
||
#endif
|