LVGL从SD卡读取图片并显示到MCU LCD屏详细笔记教程

1、前言

        在上一篇LVGL专题文章中已经讲解了如何将LVGL与FatFs链接起来,实现LVGL对SD卡中的数据进行读写操作。本文在上一文的基础上,将实现LVGL读取文件系统中的图片文件(BMP、PNG、JPG),并显示到MCU设备中的LCD屏中。

        LVGL配置FatFs文件系统,实现对STM32的SD卡数据读写-CSDN博客

        不得不吐槽一下,在MCU这类资源受限的设备上,需要刷一张图片,可谓是一波三折,属实头大。在试错,踩坑好几回后,总计归纳了这篇文章所呈现的笔记内容。如果本文讲解的方法有不合适的地方,欢迎在评论区或者私信交流探讨。

2、LVGL图片类型

(1)、解码器

        在LVGL中,支持如下4种格式的图片类型,分别是BMPPNGJPGGIF

        打开LVGL官网的文档,根据使用的LVGL选择了对应的文档版本后,点击3rd party libraries。可以看到官方对于使用这些第三方库资源内容的说明。

        BMP decoder — LVGL documentation

        除了使用本地图片解码器,LVGL官网也提供了在线图像转换器:Image Converter — LVGL

(2)、BMP

        BMP(Bitmap Image File)是一种图像文件格式,广泛应用于Windows操作系统中,用于存储数字图像。BMP图片是没有经过压缩的RGB图像数据。在使用的时候,不需要特定的解码器,直接读取文件的内容,简单处理后,就能进行显示。但因为其没有压缩,所以占用的内存空间较大。接下来所说的LVGL BMP解码器是指读取BMP文件处理像素的操作。

        而较多的MCU设备LCD显示屏仅支持16位RGB565格式的BMP图像显示。因此,对于目标设备LCD仅支持RGB565时,需要将24位BMP位图进行格式转换后,才能正常显示到LCD中。于是在这一篇文章中,将BMP的原理进行了深度的解析,同时也提供了位图格式转换的参考代码,要是有这个问题的困扰,可以参考一下。

        BMP位图原理深度解析及编程实现RGB565图片格式转换-CSDN博客

        在LVGL的BMP解码器中,像素是按需读取的(不是整个图像被加载),因此使用 BMP 图像需要很少的 RAM。

        在 lv_conf.h 中通过 LV_USE_BMP 可启用BMP解码器,并将 BMP 文件直接用作图像源。

(3)、PNG

        PNG(Portable Network Graphics)是一种广泛使用的图像文件格式,它采用无损压缩算法,旨在提供高质量的图像显示,同时保持文件大小相对较小。

        PNG图像解码时,其解码期间的RAM为: 图像宽度 x 图像高度 x 4字节

        在 lv_conf.h 中通过 LV_USE_PNG 可启用PNG解码器,并将 PNG 文件直接用作图像源。

(4)、JPG

        JPG文件,全称为JPEG(Joint Photographic Experts Group),是一种广泛使用的图像文件格式,它基于JPEG标准,该标准定义了一种有损压缩算法,用于减少图像文件的大小,同时尽可能保持图像质量。

        对于JPG图片的处理,LVGL提供的解码JPG库的实际上是SJPG,这是基于“普通”JPG 的自定义格式,专门用于LVGL。

        在LVGL中,解码普通 JPG 会消耗整个未压缩图像大小的 RAM,因此LVGL官方仅推荐用于具有更多 RAM 的设备。并且LVGL提供的JPG解码器,仅解码 JPG 和 SJPG 图像所需的部分,因此在使用过程中,无法对图片进行缩放或旋转。

        默认未修改的情况下,sjpg 图像占用的缓存空间为:图像宽度 * 2 * 16 字节

        在 lv_conf.h 中通过 LV_USE_SJPG 可启用JPG解码器,并将 JPG 文件直接用作图像源。

(5)、GIF

        GIF文件,全称Graphics Interchange Format,是一种无损压缩的图像文件格式,主要用于创建简单且颜色较少的图像,尤其是具有动画效果的图像。

        要解码和显示 GIF 动画,需要以下 RAM 量:

LV_COLOR_DEPTH 8: 3 x 图像宽度 x 图像高度

LV_COLOR_DEPTH 16:4 x 图像宽度 x 图像高度

LV_COLOR_DEPTH 32:5 x 图像宽度 x 图像高度

        在 lv_conf.h 中通过 LV_USE_GIF 中启用GIF解码器,并且可将GIF文件直接作为图像源。

3、LVGL显示图片

(1)、图片显示方案

        在LVGL中,将图片显示到LCD设备中,主要如下3种方法:

1、将图片转码成源代码,编译时,一起编译到程序代码中

2、将图片转码成二进制bin文件,将图片拷贝到SD卡中,程序运行时进行读取显示

3、将图片直接拷贝到SD卡中,通过LVGL的解码库解析显示图片

        在本文中,讲解的是,如何配置MCU工程及LVGL,实现利用LVGL的解码库,将各类图片解析出来,显示到LCD屏幕中。

        提醒:在显示BMP图片时,如果是直接将BMP原图片拷贝到SD卡中去显示时。需要对图片进行转码操作,否则BMP图片颜色深度位数不一致会无法显示

[Warn]    (0.484, +484)     decoder_open: LV_COLOR_DEPTH == 16 but bpp is 24 (should be 16)     (in lv_bmp.c line #160)
[Warn]    (0.495, +11)     _lv_img_cache_open: Image draw cannot open the image resource     (in lv_img_cache.c line #125)
[Warn]    (0.506, +11)     lv_draw_img: Image draw error     (in lv_draw_img.c line #84)
[Warn]    (0.515, +9)     decoder_open: LV_COLOR_DEPTH == 16 but bpp is 24 (should be 16)     (in lv_bmp.c line #160)
[Warn]    (0.525, +10)     _lv_img_cache_open: Image draw cannot open the image resource     (in lv_img_cache.c line #125)
[Warn]    (0.536, +11)     lv_draw_img: Image draw error     (in lv_draw_img.c line #84)

        BMP位图原理深度解析及编程实现RGB565图片格式转换-CSDN博客

(2)、MCU工程配置

①、修改内存大小

        根据自己所用开发的芯片,找到其启动文件,修改其堆、栈空间。如果堆栈空间不足,运行LVGL程序时,会出现各种莫名其妙的问题,因此,在能芯片容量范围内的情况下,能多大就多大。

        打开lv_conf.h文件,需要为LVGL分配多一些的内存空间,找到LV_MEM_SIZE这个宏,将其值设置的大一些。

        如下所示为在程序代码调试过程中,堆栈空间值过小,打开图片失败时,产生的错误提示,将启动文件的堆栈空间和LV_MEM_SIZE设置到合适值时,如下所示的错误消失,图片正常显示。

[Warn]    (0.693, +693)     _lv_img_cache_open: Image draw cannot open the image resource     (in lv_img_cache.c line #125)
[Warn]    (0.704, +11)     lv_draw_img: Image draw error     (in lv_draw_img.c line #84)
[Warn]    (0.715, +11)     _lv_img_cache_open: Image draw cannot open the image resource     (in lv_img_cache.c line #125)
[Warn]    (0.726, +11)     lv_draw_img: Image draw error     (in lv_draw_img.c line #84)
[Warn]    (0.737, +11)     _lv_img_cache_open: Image draw cannot open the image resource     (in lv_img_cache.c line #125)
[Warn]    (0.748, +11)     lv_draw_img: Image draw error     (in lv_draw_img.c line #84)

        如果MCU设备的内存空间告急严重,可以尝试使用微库,这也能节省一定的内存空间。如下所示是开启微库前后,编译出来的程序内存变化情况。

②、修改LVGL配置文件

        在LVGL中,如果需要读取SD卡中的原始图片文件,并显示到LCD中,需要开启宏定义配置。

        打开lv_conf.h文件,找到文件系统部分的配置,检查LV_USE_FS_FATFS是否开启,如果还未配置LVGL的文件系统,请查看本文开始部分的内容,进行文件系统的适配。

        找到如下图所示的LV_USE_PNG、LV_USE_BMP、LV_USE_SJPG、LV_USE_GIF,根据实际的使用需要,对这些宏定义开关进行配置。

(3)、参考程序源码

#include "lvgl.h"
#include "lv_port_disp.h"
#include "lv_port_indev.h"
#include "lv_conf.h"

#include "diskio.h"
#include "ff.h"
#include "ffconf.h"

void FatFs_Init(void)
{
    FATFS fs;                        
    FRESULT res_sd;
    
    while(SD_Init())
    {
        LED_RED_ON;
        delay_ms(500);
        LED_RED_OFF;
        delay_ms(500);
    }
    

    res_sd = f_mount(&fs,"0:", 1);
    if (res_sd!=FR_OK)
    {
        printf("SD Mount FatFs Failed! %d\r\n",res_sd);
        while (1);
    } else {
        printf("SD Mount FatFs Success!\r\n");
    }
}

void LVGL_Show_Images(void)
{
    FatFs_Init();//初始化文件系统,并且将SD卡挂载
    
    lv_init(); 
    lv_port_disp_init();
    lv_port_indev_init();
            
    lv_obj_t *label_1 = lv_label_create(lv_scr_act());
    lv_obj_t *label_2 = lv_label_create(lv_scr_act());
    lv_obj_t *label_3 = lv_label_create(lv_scr_act());
    const lv_font_t *font_txt;
    font_txt = &lv_font_montserrat_14;
    
    lv_obj_set_style_text_font(label_1, font_txt, LV_PART_MAIN);
    lv_obj_set_style_text_font(label_2, font_txt, LV_PART_MAIN);
    lv_obj_set_style_text_font(label_3, font_txt, LV_PART_MAIN);
    
    lv_label_set_text(label_1, "PNG");
    lv_label_set_text(label_2, "BMP");
    lv_label_set_text(label_3, "JPG");
        
    lv_obj_t *img1 = lv_img_create(lv_scr_act());
    lv_img_set_src(img1, "0:/images/1.png");//jpg 11.2K以内,png 11.2K以内
    lv_obj_center(img1);
    lv_obj_align_to(label_1 ,img1, LV_ALIGN_OUT_LEFT_MID, -10, 0);
        
    
    lv_obj_t *img2 = lv_img_create(lv_scr_act());
    lv_img_set_src(img2, "0:/images/2.bmp");
    lv_obj_align_to(img2, img1, LV_ALIGN_OUT_TOP_MID, 0, -40);
    lv_obj_align_to(label_2 ,img2, LV_ALIGN_OUT_LEFT_MID, -10, 0);
    
    lv_obj_t *img3 = lv_img_create(lv_scr_act());
    lv_img_set_src(img3, "0:/images/3.jpg");
    lv_obj_align_to(img3, img1, LV_ALIGN_OUT_BOTTOM_MID, 0, 40);
    lv_obj_align_to(label_3 ,img3, LV_ALIGN_OUT_LEFT_MID, -10, 0);
}

(4)、LCD显示效果

### 回答1: 在使用STM32和LVGL时,我们可以通过调用文件系统中的图片来实现图像显示。 首先,我们需要在STM32上实现一个文件系统。常用的文件系统有FATFS和LITTLEFS等,它们可以通过SPI Flash或SD等外部存储器来实现。在文件系统中,我们需要将图片文件存储在适当的目录下。 接下来,我们需要使用LVGL的图像对象来显示文件系统中的图片。首先,在代码中引入LVGL的头文件,初始化LVGL库。然后,我们可以创建一个图像对象,设置其大小和位置。例如,使用`lv_img_create()`函数创建一个图像对象,然后使用`lv_img_set_src()`函数将其连接到文件系统中的图片文件。最后,使用`lv_obj_align()`函数将图像对象对齐放置在需要显示的位置上。 例如,以下是一个简单的示例代码: ```c #include "lvgl.h" void main() { // 初始化LVGL库 // 创建一个图像对象 lv_obj_t *img = lv_img_create(lv_scr_act(), NULL); // 设置图像对象的大小和位置 lv_obj_set_width(img, 100); lv_obj_set_height(img, 100); lv_obj_align(img, NULL, LV_ALIGN_CENTER, 0, 0); // 连接图像对象到文件系统中的图片文件 lv_img_set_src(img, "S:/images/test.png"); // 假设图片文件存储在S盘下的images目录中,文件名为test.png while(1) { // 循环刷新界面 lv_task_handler(); delay_ms(10); // 延时10毫秒,可以调整延时时间来改变刷新速度 } } ``` 需要注意的是,具体的文件路径和图像对象的大小、位置等参数需要根据实际情况进行调整,以确保图像可以正确地显示LVGL界面上。 通过以上步骤,我们就可以实现在STM32中使用LVGL调用文件系统中的图片进行显示了。 ### 回答2: 在STM32中使用LVGL库调用文件系统中的图片,首先要确保文件系统已经正确地安装和配置。接下来,我们可以按照以下步骤进行操作: 1. 首先,我们需要在STM32上配置一个适当的文件系统,例如FatFs。在配置文件系统之前,需要根据具体的文件系统类型选择正确的驱动程序和文件系统实例。 2. 当文件系统配置完成后,在代码中使用相应的文件系统库进行初始化。这通常包括挂载和打开文件系统。 3. 通过文件系统库提供的函数,可以打开需要调用的图片文件。将文件句柄保存起来,以便在需要的时候使用。 4. 在LVGL库中,可以使用`lv_img_create`函数创建一个图像对象。该函数接受一个图像的指针作为参数,我们可以使用文件系统的读取函数读取图片数据,将其作为参数传递给该函数。 5. 图片对象创建完成后,可以使用LVGL库中提供的其他函数设置图像对象的位置、大小等属性。 6. 最后,将图像对象添加到需要显示的界面(幕)上,使用`lv_obj_add_protect`函数将其添加为保护对象,以防止被其它对象覆盖。 通过以上步骤,我们就可以成功调用文件系统中的图片在STM32上显示出来。需要注意的是,具体的实现细节可能因不同的硬件平台和软件库而有所差异,因此需要根据具体的环境进行适配和调试。 ### 回答3: 在STM32上使用LVGL库调用文件系统中的图片,可以通过以下几个步骤实现: 首先,需要在STM32上配置好文件系统,确保能够正常读取文件。可以使用FatFS等开源库进行文件系统的配置和管理。 接下来,将图片文件保存到文件系统中,确保文件路径和文件名的正确性。可以将图片文件以适当的格式(如BMP、PNG等)保存到SD或FLASH等存储介质上。 然后,在STM32上使用LVGL库的函数来调用文件系统中的图片LVGL提供了Image对象用于显示和处理图像。可以使用lv_img_create函数创建一个Image对象,使用lv_img_set_src函数指定图片的路径和文件名。 在代码中,需要根据具体的文件系统和文件路径进行相应的配置和初始化。例如,使用FatFS时,需要调用f_mount函数挂载文件系统,使用f_open函数打开图片文件。然后,通过读取文件内容,将图片数据传递给Image对象。 最后,将创建的Image对象添加到LVGL的画布中,即可以在STM32上正常显示文件系统中的图片了。可以使用lv_scr_load函数加载画布,更新显示。 需要注意的是,调用文件系统中的图片可能涉及到数据读取和处理的速度问题。为保证图片能够正确显示,可能需要根据具体的应用需求进行优化,例如通过异步方式加载图片,加入缓存机制等。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值