解码LVGL图片

图像控件(lv_img):操作 RGB 像素数据

LVGL 不直接支持 PNG/JPG,需通过 “C 数组编译” 或 “第三方库解析” 实现,核心是绑定 RGB 像素数据。

场景 1:有限图像(固定图标 / 按钮,数量少)

适用于 APP 图标、功能按钮等固定内容,通过 LVGL 图像生成器转 C 数组。

图像控件与基础显示相关宏

用于启用 LVGL 中直接承载图片的控件,是图片显示的基础。

宏名 配置值 功能说明
LV_USE_IMAGE 1 启用图像控件(lv_image),是 LVGL 显示图片的核心控件(支持 PNG/BMP/JPG 等格式)。
LV_USE_IMAGEBUTTON 1 启用图像按钮控件,支持用图片作为按钮的背景 / 前景(如按下 / 释放状态显示不同图片)。
  • Step1:图像转 C 数组(关键参数)

    • 打开工具:LVGL 在线图像生成器

    • 上传图像(PNG/JPG/BMP),配置核心参数:

      参数名 配置值 / 说明 作用
      Color format CF_TRUE_COLOR(勾选 Alpha byte) 真彩色 + 透明通道(需透明时选)
      Chroma keyed 勾选(可选) 将默认透明色(黑色)设为透明
      Output format C array 生成 lv_img_dsc_t 类型数组
      Dither images 勾选(低色深场景) 减少锯齿,优化显示质量

      生成 xxx.c 和 xxx.h(数组存储 RGB 数据,含宽 / 高信息)。

  • Step2:工程集成(CMake 配置)
    添加如下内容

    # 添加图像头文件路径
    include_directories(${PROJECT_SOURCE_DIR}/resource/images)
    # 收集所有图像 .c 文件
    file(GLOB_RECURSE IMAGE_SOURCES ${PROJECT_SOURCE_DIR}/lvgl/images/*.c)
    # 加入编译列表(链接 LVGL 依赖库)
    add_executable(main main.c ${IMAGE_SOURCES})
    
  • Step3:代码显示(含接口注释)

    #include "lvgl/lvgl.h"
    LV_IMG_DECLARE(balloon); // 声明图像数组(等同于 extern const lv_img_dsc_t balloon;)
    
    /**
     * 显示固定图像(按屏幕比例缩放)
     * @param parent:父对象(如 lv_scr_act() 当前屏幕)
     * @param img_dsc:图像数组指针(&balloon)
     * @return 图像对象指针(NULL 表示失败)
     */
    lv_obj_t *img_show_fixed(lv_obj_t *parent, const lv_img_dsc_t **img_dsc) {
        // 创建图像对象
        lv_obj_t *img = lv_img_create(parent);
        if (img == NULL) { LV_LOG_ERROR("图像创建失败"); return NULL; }
        
        // 绑定图像数据(核心接口)
        lv_img_set_src(img, &img_dsc); // 支持数组/文件路径,此处用数组
        
        // 按屏幕50%宽度缩放,高度自适应
        lv_obj_set_size(img, LV_PCT(50), LV_SIZE_CONTENT);
        
        // 居中显示(向上偏移20px)
        lv_obj_align(img, LV_ALIGN_CENTER, 0, -20);
        
        return img;
    }
    
    // 调用示例
    void img_fixed_demo(void) {
        lv_obj_t *scr = lv_scr_act();
        img_show_fixed(scr, &balloon);
    }
    

宏定义与常用函数解析:

#if LV_USE_IMAGE              
#define lv_img_create         lv_image_create
#define lv_img_set_src        lv_image_set_src
#define lv_img_set_offset_x   lv_image_set_offset_x
#define lv_img_set_offset_y   lv_image_set_offset_y
#define lv_img_set_angle      lv_image_set_rotation
#define lv_img_set_pivot      lv_image_set_pivot
#define lv_img_set_zoom       lv_image_set_scale
#define lv_img_set_antialias  lv_image_set_antialias
#define lv_img_get_src        lv_image_get_src
#define lv_img_get_offset_x   lv_image_get_offset_x
#define lv_img_get_offset_y   lv_image_get_offset_y
#define lv_img_get_angle      lv_image_get_rotation
#define lv_img_get_pivot      lv_image_get_pivot
#define lv_img_get_zoom       lv_image_get_scale
#define lv_img_get_antialias  lv_image_get_antialias
#endif /* LV_USE_IMAGE */
/**
 * 创建图像控件(图像显示的入口函数,必用函数)
 * @param parent    父对象指针(lv_obj_t*,不可为NULL),图像控件的父容器(如屏幕、按钮、容器等)
 * @return          新创建的图像控件对象指针(lv_obj_t*),用于后续操作图像;内存不足时返回NULL,需检查返回值避免空指针操作
 * @note            图像控件创建后需通过lv_image_set_src设置图像源才能显示内容;
 *                  若父对象被删除,该图像控件会自动递归删除,无需手动释放
 */
lv_obj_t * lv_image_create(lv_obj_t * parent);

/**
 * 设置图像控件的图像源(图像显示的核心函数,必用函数)
 * @param img       图像控件对象指针(lv_obj_t*,不可为NULL),需设置图像源的图像控件
 * @param src       图像源(const void*),支持多种类型:
 *                  - 内置图像数组:通过LVGL图像转换器生成的数组(如&my_img_data);
 *                  - 文件路径:已注册文件系统的图像文件路径(如"SDCARD:/images/logo.png",需LV_USE_FILESYSTEM支持);
 *                  - 符号:LVGL内置符号(如LV_SYMBOL_OK,需LV_USE_SYMBOL支持);
 *                  - 注意:若src为NULL,图像控件将显示为空
 * @return          无返回值(void)
 * @note            图像源设置后会立即触发重绘,若图像较大可能导致短暂卡顿;
 *                  不同图像源类型需确保对应模块已启用(如文件系统、符号功能);
 *                  建议提前将图像转换为LVGL支持的格式(如ARGB8888、RGB565)以提升渲染效率
 */
void lv_image_set_src(lv_obj_t * img, const void * src);

/**
 * 设置图像的旋转角度(图像变换函数,常用)
 * @param img       图像控件对象指针(lv_obj_t*,不可为NULL),需旋转的图像控件
 * @param angle     旋转角度(int16_t),单位为度,支持0~359的整数值;0为不旋转,90为顺时针旋转90度,依此类推
 * @return          无返回值(void)
 * @note            旋转会改变图像的显示尺寸,需确保父容器有足够空间避免裁剪;
 *                  旋转操作涉及图像重绘,频繁旋转大图像可能影响性能;
 *                  若同时使用缩放(lv_image_set_scale),旋转中心由lv_image_set_pivot决定
 */
void lv_image_set_rotation(lv_obj_t * img, int16_t angle);

/**
 * 设置图像旋转的中心点(图像变换辅助函数,与旋转配合使用)
 * @param img       图像控件对象指针(lv_obj_t*,不可为NULL),需设置旋转中心的图像控件
 * @param x         旋转中心的X坐标(lv_coord_t),相对于图像控件左上角的偏移;默认值为图像宽度的一半(居中旋转)
 * @param y         旋转中心的Y坐标(lv_coord_t),相对于图像控件左上角的偏移;默认值为图像高度的一半(居中旋转)
 * @return          无返回值(void)
 * @note            旋转中心仅在图像旋转(lv_image_set_rotation)时生效;
 *                  若x或y超出图像控件范围,旋转中心会被限制在图像边界内;
 *                  合理设置旋转中心可实现绕边角、边缘等特殊点的旋转效果
 */
void lv_image_set_pivot(lv_obj_t * img, lv_coord_t x, lv_coord_t y);

/**
 * 设置图像的缩放比例(图像变换函数,常用)
 * @param img       图像控件对象指针(lv_obj_t*,不可为NULL),需缩放的图像控件
 * @param scale     缩放比例(uint16_t),取值范围为0~4096;1024为原始大小,2048为放大2倍,512为缩小一半
 * @return          无返回值(void)
 * @note            缩放会改变图像的显示尺寸,放大时若超过父容器尺寸会被裁剪;
 *                  缩放比例为0时图像不可见;
 *                  缩放操作涉及图像重采样,大比例放大可能导致图像模糊,可配合lv_image_set_antialias提升显示效果
 */
void lv_image_set_scale(lv_obj_t * img, uint16_t scale);

/**
 * 设置图像的抗锯齿效果(图像显示优化函数,常用)
 * @param img       图像控件对象指针(lv_obj_t*,不可为NULL),需设置抗锯齿的图像控件
 * @param en        使能标志(bool),true为启用抗锯齿,false为禁用
 * @return          无返回值(void)
 * @note            抗锯齿可提升图像旋转、缩放后的显示平滑度,但会增加CPU渲染开销;
 *                  仅在图像有变换(旋转、缩放)时生效,静态图像无需启用;
 *                  需确保LV_USE_IMAGE_ANTIALIAS宏已启用(默认启用),否则该函数无效果
 */
void lv_image_set_antialias(lv_obj_t * img, bool en);

场景 2:不限图像(动态加载,如用户照片)

适用于大量 / 动态图像,需启用 LVGL 的 TJPG 解码器 + 文件系统。
图片解码库相关宏按需启用(核心,处理不同格式图片)

用于启用各类图片格式的解码器,决定 LVGL 能识别并显示哪些格式的图片。

宏名 配置值 功能说明
LV_USE_LODEPNG 1 启用 LODEPNG 库,支持PNG 格式图片的解码(轻量级,适合嵌入式系统)。
LV_USE_LIBPNG 0 启用 libpng 库(另一个 PNG 解码器,支持更完整的 PNG 特性,当前配置未启用)。
LV_USE_BMP 1 启用 BMP 解码器,支持BMP 格式图片的解码(无压缩 / 简单压缩的 BMP 均支持)。
LV_USE_TJPGD 1 启用 TJPGD 库,支持JPG 格式图片及 LVGL 自定义 “拆分 JPG” 格式的解码(轻量级)。
LV_USE_LIBJPEG_TURBO 0 启用 libjpeg-turbo 库(高性能 JPG 解码器,支持完整 JPEG 规范,当前配置未启用)。
LV_USE_GIF 0 启用 GIF 解码器,支持GIF 格式图片(含动画 GIF),当前配置未启用。
LV_BIN_DECODER_RAM_LOAD 1 启用 “bin 格式图片解码到 RAM” 功能,支持将 bin 格式的图片数据解码后加载到内存显示。
LV_USE_RLE 1 启用 RLE 解压库,支持RLE 压缩格式的图片(如部分 BMP、自定义图片的压缩解压)。
LV_USE_FFMPEG 0 启用 FFmpeg 库(支持全格式图片解码,同时支持音视频,当前配置未启用)。
  • Step1:启用 TJPGD 支持(修改 lv_conf.h)

    #define LV_USE_TJPGD 1          // 启用 TJPGD 解码器(简化 JPG 格式)
    #define LV_USE_FS_POSIX 1      // 启用 POSIX 文件系统(Linux/RTOS 用)
    
    /* ==============================
     * 标准C库文件系统接口(STDIO)配置
     * 适用场景:通用平台(PC、嵌入式系统),依赖标准C库的fopen/fread等函数
     * ============================== */
    /* 启用STDIO文件系统接口
     * 1:启用,LVGL通过标准C库函数(fopen、fread、fclose等)访问文件
     * 0:禁用,不使用该接口 */
    #define LV_USE_FS_STDIO 1
    
    /* 当LV_USE_FS_STDIO为1时生效的子配置 */
    #if LV_USE_FS_STDIO
        /* 为STDIO文件系统分配虚拟盘符(如'A'、'B'等)
         * 用于区分多个文件系统(如同时连接SD卡和本地磁盘时)
         * 访问文件时需带盘符前缀,例:"A:/images/logo.jpg" */
        #define LV_FS_STDIO_LETTER 'A'
    
        /* 设置STDIO文件系统的基准路径(工作目录)
         * 所有通过该接口访问的文件路径会自动拼接在该路径后
         * 例:设为"/user/res/",则"A:pic.png"实际路径为"/user/res/pic.png"
         * 设为空字符串""时,直接使用路径参数中的绝对路径或相对路径(相对于程序运行目录) */
        #define LV_FS_STDIO_PATH "/"
    
        /* 文件读取缓存大小(单位:字节)
         * 0:禁用缓存,每次读取直接调用fread
         * >0:分配指定大小的缓存,减少底层IO调用,提升读取效率(建议1024~4096) */
        #define LV_FS_STDIO_CACHE_SIZE 0
    #endif
    
    /* ==============================
     * POSIX文件系统接口配置
     * 适用场景:类Unix系统(Linux、macOS等),依赖POSIX标准的open/read等函数
     * ============================== */
    /* 启用POSIX文件系统接口
     * 1:启用,LVGL通过POSIX标准函数(open、read、close等)访问文件
     * 0:禁用,不使用该接口 */
    #define LV_USE_FS_POSIX 1
    
    /* 当LV_USE_FS_POSIX为1时生效的子配置 */
    #if LV_USE_FS_POSIX
        /* 为POSIX文件系统分配虚拟盘符(作用同STDIO的盘符)
         * 例:盘符为'A'时,"A:/root/dog.jpg"对应实际路径"/root/dog.jpg" */
        #define LV_FS_POSIX_LETTER 'A'
    
        /* 设置POSIX文件系统的路径前缀(基准目录)
         * 所有通过该接口访问的文件路径会自动拼接在该前缀后
         * 设为空字符串""时,直接使用绝对路径(如"A:/home/user/file.txt"对应"/home/user/file.txt") */
        #define LV_FS_POSIX_PATH "/"
    #endif
    
  • Step2:代码动态加载 TJPGD

    /**
     * 图片点击事件回调(示例)
     */
    static void jpg_click_event(lv_event_t *e) {
        lv_obj_t *img = lv_event_get_target(e);
        LV_LOG_INFO("图片被点击!");  // 日志用于确认事件是否触发
        
        /* 修正缩放逻辑:点击在 800(≈78%) 和 1280(≈125%) 之间切换 */
        static uint16_t scale = 800;  // LVGL缩放基数:1024 = 100%
        scale = (scale == 800) ? 1280 : 800;  // 点击切换缩放比例
        lv_image_set_scale(img, scale);
    }
    /**
     * 动态加载并显示 JPG 图片(基于 TJPGD 解码器和文件系统)
     */
    void jpg_loader_demo(void) {
        /* 获取当前活跃屏幕作为父对象 */
        lv_obj_t *scr = lv_screen_active();
    
        /* 创建图像控件(用于显示 JPG 图片) */
        lv_obj_t *jpg_img = lv_image_create(scr);
        if(jpg_img == NULL) {
            LV_LOG_ERROR("创建图像控件失败!");
            return;
        }
    
        /* 设置图像控件的尺寸和初始位置(可根据图片实际大小调整) */
        lv_obj_set_size(jpg_img, 400, 300);  // 宽400px,高300px(超出部分会裁剪)
        lv_obj_align(jpg_img, LV_ALIGN_CENTER, 0, 0);  // 居中显示
    
        /* 设置 JPG 图片源(关键步骤:通过文件系统路径加载)
         * 路径格式:"盘符:/实际文件路径"
         * 注意:
         * - 盘符需与 lv_conf.h 中配置的 LV_FS_STDIO_LETTER 或 LV_FS_POSIX_LETTER 一致(此处为 'A')
         * - 确保文件存在且路径正确(如 Linux 下实际路径为 "/home/user/images/test.jpg",则此处写 "A:/home/user/images/test.jpg")
         */
        const char *jpg_path = "A:/home/wby/LVGL/Ubuntu/lv_port_linux-9.2/resource/img/bg.jpg";  // 替换为实际 JPG 文件路径
        lv_image_set_src(jpg_img, jpg_path);
        lv_obj_add_flag(jpg_img,LV_OBJ_FLAG_CLICKABLE);
    
        /* 检查图片是否加载成功(可选:添加错误处理) */
        const void *src = lv_image_get_src(jpg_img);
        if(src == NULL) {
            LV_LOG_ERROR("JPG 图片加载失败!路径:%s", jpg_path);
            
            /* 加载失败时显示提示标签 */
            lv_obj_t *err_label = lv_label_create(scr);
            lv_label_set_text(err_label, "图片加载失败,请检查路径!");
            lv_obj_align_to(err_label, jpg_img, LV_ALIGN_BOTTOM_MID, 0, 20);
        } else {
            LV_LOG_INFO("JPG 图片加载成功!路径:%s", jpg_path);
        }
    
        /* 可选:添加图片点击事件(示例) */
        lv_obj_add_event_cb(jpg_img, jpg_click_event, LV_EVENT_CLICKED, NULL);
    }
    
    

关键说明:

  • 路径格式:需严格遵循 "盘符:/ 实际路径" 格式,例如:
    • 若 JPG 文件在 Linux 系统的 /home/user/pic.jpg,路径为 "A:/home/user/pic.jpg"(因 LV_FS_POSIX_LETTER = 'A');
    • 若在 Windows 本地磁盘 D:/images/photo.jpg,路径为 "A:/D:/images/photo.jpg"(STDIO 接口下)。
  • 加载原理
    • lv_image_set_src 会自动调用 TJPGD 解码器(因 LV_USE_TJPGD = 1);
    • 文件读取通过配置的 POSIX/STDIO 接口实现(LV_USE_FS_POSIX = 1LV_USE_FS_STDIO = 1)。
  • 错误排查
    • 若图片不显示,先检查路径是否正确(可通过 LV_LOG 查看错误信息);
    • 确保 JPG 文件未损坏(TJPGD 支持大部分标准 JPG,但不支持过于复杂的格式如渐进式 JPG);
    • 若内存不足,可增大 lv_conf.h 中的 LV_MEM_SIZE(当前为 1MB,大图片可能需要更大内存)。
  • 扩展功能:可通过 lv_image_set_rotation(旋转)等函数对加载的 JPG 图片进行变换(如示例中的点击缩放)。
posted @ 2025-11-09 12:26  YouEmbedded  阅读(120)  评论(0)    收藏  举报