1. 完成了gif的显示测试(使用lvgl当中的gif解码器),测试通过
This commit is contained in:
@@ -0,0 +1,178 @@
|
||||
//
|
||||
// Created by misaki on 2025/8/25.
|
||||
//
|
||||
|
||||
|
||||
#include "lvgl.h"
|
||||
#include "SD_MMC.h"
|
||||
#include "I2C_Driver.h"
|
||||
#include "ST77916.h"
|
||||
|
||||
#include <esp_log.h>
|
||||
static const char *tTAG = "GIF_TEST";
|
||||
|
||||
/* 把 GIF 完整读进 RAM,返回 malloc 得到的指针;用完 free */
|
||||
static uint8_t *read_whole_file(const char *path, size_t *out_len)
|
||||
{
|
||||
ESP_LOGI(tTAG, "开始读取文件: %s", path);
|
||||
FILE *fp = Open_File(path);
|
||||
if (!fp) {
|
||||
ESP_LOGE(tTAG, "Open_File 失败");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fseek(fp, 0, SEEK_END);
|
||||
*out_len = ftell(fp);
|
||||
fseek(fp, 0, SEEK_SET);
|
||||
ESP_LOGI(tTAG, "文件大小 %zu 字节", *out_len);
|
||||
|
||||
uint8_t *buf = malloc(*out_len);
|
||||
if (!buf) {
|
||||
ESP_LOGE(tTAG, "malloc 失败,需要 %zu 字节", *out_len);
|
||||
fclose(fp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t readed = fread(buf, 1, *out_len, fp);
|
||||
fclose(fp);
|
||||
if (readed != *out_len) {
|
||||
ESP_LOGE(tTAG, "fread 只读了 %zu/%zu 字节", readed, *out_len);
|
||||
free(buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* 打印文件头 8 字节,确认是 GIF */
|
||||
ESP_LOG_BUFFER_HEX_LEVEL(tTAG, buf, 8, ESP_LOG_INFO);
|
||||
return buf;
|
||||
}
|
||||
|
||||
uint8_t * get_gif_data(const char *filename, size_t *gif_len)
|
||||
{
|
||||
char full_path[64];
|
||||
snprintf(full_path, sizeof(full_path), "/sdcard/%s", filename);
|
||||
|
||||
uint8_t *gif_data = read_whole_file(full_path, gif_len);
|
||||
if (!gif_data) {
|
||||
ESP_LOGE(tTAG, "读取 GIF 数据失败");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return gif_data;
|
||||
}
|
||||
|
||||
/* 显示 GIF 并返回对象句柄,便于后续调试 */
|
||||
static lv_obj_t *show_gif_from_sd(const char *filename)
|
||||
{
|
||||
size_t gif_len = 0;
|
||||
char full_path[64];
|
||||
snprintf(full_path, sizeof(full_path), "/sdcard/%s", filename);
|
||||
|
||||
ESP_LOGI(tTAG, "准备显示 GIF: %s", full_path);
|
||||
|
||||
uint8_t *gif_data = read_whole_file(full_path, &gif_len);
|
||||
if (!gif_data) {
|
||||
ESP_LOGE(tTAG, "读取 GIF 数据失败");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* 确认 LVGL 版本支持内存指针 */
|
||||
#if LV_VERSION_CHECK(8, 1, 0)
|
||||
lv_obj_t *gif = lv_gif_create(lv_scr_act());
|
||||
lv_gif_set_src(gif, gif_data); // 传内存指针
|
||||
ESP_LOGI(tTAG, "GIF 对象创建成功,指针 %p", gif);
|
||||
#else
|
||||
lv_obj_t *gif = NULL;
|
||||
ESP_LOGE(tTAG, "LVGL 版本过低或 GIF 解码器未启用");
|
||||
#endif
|
||||
|
||||
if (gif) {
|
||||
lv_obj_center(gif);
|
||||
ESP_LOGI(tTAG, "GIF 已显示");
|
||||
} else {
|
||||
ESP_LOGE(tTAG, "GIF 对象创建失败");
|
||||
}
|
||||
|
||||
/* 如内存紧张,可在这里 free(gif_data);
|
||||
但注意:循环播放时需要保持 data 有效 */
|
||||
return gif;
|
||||
}
|
||||
|
||||
void gif_macro_check(void)
|
||||
{
|
||||
ESP_LOGI("GIF", "LV_USE_GIF=%d (必须是 1)", LV_USE_GIF);
|
||||
ESP_LOGI("GIF", "LVGL_VERSION=%d.%d.%d",
|
||||
LVGL_VERSION_MAJOR, LVGL_VERSION_MINOR, LVGL_VERSION_PATCH);
|
||||
}
|
||||
static bool get_gif_wh(const uint8_t *raw, uint32_t *w, uint32_t *h)
|
||||
{
|
||||
if (memcmp(raw, "GIF", 3) != 0) /* 简单校验 */
|
||||
return false;
|
||||
|
||||
*w = raw[6] | (raw[7] << 8); /* 小端转主机字节序 */
|
||||
*h = raw[8] | (raw[9] << 8);
|
||||
|
||||
ESP_LOGI("GIF", "GIF size: %ldx%ld", *w, *h);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void red_gif_test(void)
|
||||
{
|
||||
size_t gif_len = 0;
|
||||
uint8_t *gif_data = get_gif_data("xwzy_m.gif", &gif_len);
|
||||
|
||||
ESP_LOGI("GIF", "GIF 文件大小 %zu 字节", gif_len);
|
||||
if (!gif_data) return;
|
||||
|
||||
uint32_t w = 0, h = 0;
|
||||
if (!get_gif_wh(gif_data, &w, &h)) {
|
||||
ESP_LOGE("GIF", "非法 GIF 文件");
|
||||
free(gif_data);
|
||||
return;
|
||||
}
|
||||
|
||||
lv_img_dsc_t gif_desc = {
|
||||
.header.cf = LV_IMG_CF_RAW_CHROMA_KEYED,
|
||||
.header.always_zero = 0,
|
||||
.header.reserved = 0,
|
||||
.header.w = (lv_coord_t)w,
|
||||
.header.h = (lv_coord_t)h,
|
||||
.data_size = gif_len,
|
||||
.data = gif_data,
|
||||
};
|
||||
|
||||
gif_macro_check();
|
||||
lv_obj_t *gif = lv_gif_create(lv_scr_act());
|
||||
lv_gif_set_src(gif, &gif_desc);
|
||||
lv_obj_center(gif);
|
||||
}
|
||||
|
||||
|
||||
/* 带有完整日志的主测试函数 */
|
||||
void gif_display_test(void)
|
||||
{
|
||||
ESP_LOGI(tTAG, "======== GIF 显示测试开始 ========");
|
||||
|
||||
/* 1. 初始化 SD 卡 */
|
||||
ESP_LOGI(tTAG, "1. 初始化 SD 卡...");
|
||||
SD_Init(); // 你的挂载函数
|
||||
ESP_LOGI(tTAG, " SD 卡挂载完成");
|
||||
|
||||
|
||||
/* 2. 初始化硬件 */
|
||||
ESP_LOGI(tTAG, "2. 初始化硬件...");
|
||||
I2C_Init();
|
||||
LCD_Init();
|
||||
LVGL_Init();
|
||||
ESP_LOGI(tTAG, " 硬件初始化完成");
|
||||
|
||||
/* 3. 显示 GIF */
|
||||
ESP_LOGI(tTAG, "3. 开始显示 GIF...");
|
||||
|
||||
red_gif_test();
|
||||
/* 4. 主循环 */
|
||||
while (1) {
|
||||
vTaskDelay(pdMS_TO_TICKS(10));
|
||||
lv_timer_handler();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user