ESP32 LVGL:无法显示过大的GIF图片(修改VLGL RAM缓存大小)

问题描述:

使用LVGL可显示64 * 64的GIF,但是却无法显示120*120的GIF。

问题解决

更改LVGL RAM缓存大小

分析原因:在用LVGL显示GIF图片时,会用到LVGL的GIF解码器,该解码器要求的空间大小如下:
在这里插入图片描述
因此,对于6464的GIF图片,其需要的RAM空间为: 64 × 64 × 4 ÷ 1024 = 16 K b y t e s 64\times64 \times4\div1024=16K bytes 64×64×4÷1024=16Kbytes
对于120
120的GIF,其需要的RAM空间为: 120 × 120 × 4 ÷ 1024 = 56.25 K b y t e s 120 \times 120 \times4\div 1024=56.25K bytes 120×120×4÷1024=56.25Kbytes
按理来说,ESP32的RAM空间有512KB,是足够解码器使用的。
看LVGL的lv_conf.h文件我们可以发现,里面限制了LVGL可以使用的最大RAM空间,即通过malloc可以申请的最大空间:
在这里插入图片描述
其默认为48K,因此对于120*120的GIF,就无法进行解码,也就无法显示了。将其改为128K,问题就解决了。

看ESP32的RAM使用情况

在ESP32中,在总线上分为了数据内存总线(DRAM、DROM)和指令内存总线(IRAM、IROM),指令存储器是可执行的,只能通过4字节对齐的字来读写。数据内存是不可执行的,可以通过单个字节操作访问。
一般来说,DRAM用来存储可读可写的数据,IRAM用来存储只读数据。
在我们的程序中,数据一般被存在以下3个分区中:

  • 静态区(全局变量区):程序的全局变量和静态变量
  • 栈:函数内部的局部变量
  • 堆:即动态内存区,有malloc()和free()进行内存的申请释放,需要手动进行释放。

在我们使用LVGL时,所设置的LV_MEM_SIZE即为堆大小,其由DRAM的一部分和IRAM的一部分共同组成,上电时其会打印堆区信息如下:
在这里插入图片描述
其中D/IRAM是既可以做指令RAM又可以做数据RAM的区域。

我们可以通过idf.py来查看ESP32编译后的内存使用情况:
idf.py size

Total sizes:
Used static DRAM:  163500 bytes (  17236 remain, 90.5% used)
      .data size:    9476 bytes
      .bss  size:  154024 bytes
Used static IRAM:   58490 bytes (  72582 remain, 44.6% used)
      .text size:   57463 bytes
   .vectors size:    1027 bytes
Used Flash size :  443899 bytes
      .text     :  308963 bytes
      .rodata   :  134680 bytes
Total image size:  511865 bytes (.bin may be padded larger)

查看flash大小

如下:esptool.py -p COMx flash_id
在这里插入图片描述

参考链接

LVGL官网显示GIF教程
ESP32的内存学习
ESP32的堆区内存说明

  • 7
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
lvgl显示GIF可以使用IDF框架提供的GIF解码库和lvgl提供的动画资源管理器。以下是一个简单的示例代码: ```c #include "gif_lib.h" #include "lv_anim.h" // GIF文件解码回调函数 void gif_file_read(GifFileType *gif, GifByteType *buf, int size) { FILE *fp = (FILE *)gif->UserData; fread(buf, 1, size, fp); } // 在lvgl显示GIF void display_gif(lv_obj_t *parent, const char *filename) { // 打开GIF文件 FILE *fp = fopen(filename, "rb"); if (fp == NULL) { return; } // 读取GIF文件头 GifFileType *gif = DGifOpen(fp, gif_file_read); if (gif == NULL) { fclose(fp); return; } DGifSlurp(gif); // 创建动画资源 lv_anim_t anim; anim.var = NULL; anim.start = 0; anim.end = gif->ImageCount - 1; anim.exec_cb = lv_anim_cb_tic; anim.path_cb = lv_anim_path_linear; anim.ready_cb = NULL; anim.act_time = 0; anim.time = 1000 / gif->SuggestedDelayTime; anim.playback = 1; anim.repeat = LV_ANIM_REPEAT_INFINITE; lv_anim_timeline_create(&anim); // 创建动画对象 lv_img_dsc_t img_dsc; lv_img_dsc_init(&img_dsc); img_dsc.header.cf = LV_IMG_CF_TRUE_COLOR_ALPHA; img_dsc.header.w = gif->SWidth; img_dsc.header.h = gif->SHeight; img_dsc.data_size = gif->SWidth * gif->SHeight * gif->ImageCount * 4; img_dsc.data = (void *)lv_mem_alloc(img_dsc.data_size); if (img_dsc.data == NULL) { DGifCloseFile(gif, NULL); fclose(fp); return; } lv_img_set_src(parent, &img_dsc); lv_anim_set_var(&anim, img_dsc.data); // 解码GIF帧数据 int offset = 0; for (int i = 0; i < gif->ImageCount; i++) { SavedImage *image = &gif->SavedImages[i]; GifImageDesc *desc = &image->ImageDesc; GraphicsControlBlock *ctrl = &image->ExtensionBlock[0].Function.GC; int delay = ctrl->DelayTime * 10; for (int y = 0; y < desc->Height; y++) { for (int x = 0; x < desc->Width; x++) { GifByteType *src = image->RasterBits + y * desc->Width + x; uint32_t *dst = (uint32_t *)(img_dsc.data + offset + (y * gif->SWidth + x + desc->Left) * 4); *dst = lv_color_make(0, 0, 0, *src == ctrl->TransparentColor ? 0 : 255); } } offset += gif->SWidth * gif->SHeight * 4; lv_anim_set_values(&anim, i); lv_anim_set_time(&anim, delay); } // 关闭GIF文件 DGifCloseFile(gif, NULL); fclose(fp); } ``` 在这个示例中,我们首先打开GIF文件并读取其文件头。然后,我们使用lv_anim_timeline_create函数创建了一个动画资源,并使用lv_anim_set_var函数将其与lv_img对象关联起来。接下来,我们遍历GIF帧并将它们解码为RGBA格式的像素数据。最后,我们使用lv_anim_set_values和lv_anim_set_time函数定义了每一帧的播放时间,并关闭了GIF文件。 当您想要在lvgl显示GIF时,只需调用display_gif函数并传入要显示GIF文件名和父对象,lvgl将自动管理动画播放和内存分配。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天城寺电子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值