☰
LVGL Image 控件(lv_img)四例实战:从图像显示到旋转缩放与重着色
2026/10/5 2:00:36 网站建设 项目流程
  • 智能硬件
  • 嵌入式
  • 硬件开发

【免费下载链接】X-TRACK

A GPS bicycle speedometer that supports offline maps and track recording

项目地址:https://gitcode.com/gh_mirrors/xt/X-TRACK
点击查看免费下载

本文以 X-TRACK 仓库所携带的 LVGL 模拟器工程(Software/X-Track/Simulator/LVGL.Simulator)中widgets/img示例为蓝本,系统讲解 LVGLlv_img图像控件的四大核心能力:从变量/符号创建图像、运行时图像重着色、围绕枢轴点的旋转与缩放、以及图像偏移与样式定制。读完本文,你既能掌握lv_img的完整 API 用法与动画组合技巧,也能看到这些能力在 X-TRACK 码表(如实时地图、状态栏图标)中的真实落点。

示例总览:img 控件的四张「能力清单」

LVGL 官方示例在 lv_examples_index.rst 中把图像控件归纳为四个递进主题,每个主题对应一个可独立运行的 C 示例,并附带 MicroPython 版本:

序号主题C 示例Python 示例
1Image from variable and symbol(从变量与符号创建图像)lv_example_img_1.clv_example_img_1.py
2Image recoloring(图像重着色)lv_example_img_2.clv_example_img_2.py
3Rotate and zoom(旋转与缩放)lv_example_img_3.clv_example_img_3.py
4Image offset and styling(图像偏移与样式)lv_example_img_4.clv_example_img_4.py

四个示例共享同一批示例资源(img_cogwheel_argb齿轮图、img_skew_strip斜条纹图),均以LV_IMG_DECLARE声明外部图像描述符。下面逐一展开。

示例一:从变量与符号创建图像

C 实现核心逻辑

lv_example_img_1.c 演示了lv_img的两种数据来源:C 变量形式的图像描述符与内置字体符号(Symbol):

void lv_example_img_1(void) { LV_IMG_DECLARE(img_cogwheel_argb); lv_obj_t * img1 = lv_img_create(lv_scr_act()); lv_img_set_src(img1, &img_cogwheel_argb); /* 来源一:图像变量 */ lv_obj_align(img1, LV_ALIGN_CENTER, 0, -20); lv_obj_set_size(img1, 200, 200); /* 缩放显示区域,不影响原图 */ lv_obj_t * img2 = lv_img_create(lv_scr_act()); lv_img_set_src(img2, LV_SYMBOL_OK "Accept"); /* 来源二:符号+文本 */ lv_obj_align_to(img2, img1, LV_ALIGN_OUT_BOTTOM_MID, 0, 20); }

要点拆解:

  • LV_IMG_DECLARE(img_cogwheel_argb):声明一个外部图像描述符(lv_img_dsc_t),实际定义通常在lv_examples/assets相关的图像源文件中;声明后可直接把&img_cogwheel_argb传给lv_img_set_src()。
  • lv_img_set_src()是控件的「入口 API」,它同时接受三种输入:图像描述符指针、文件路径字符串、以及内置符号宏。示例中的LV_SYMBOL_OK "Accept"即用内置字体中的LV_SYMBOL_OK(勾选图标)拼接文本Accept,构成一个「图标+文字」的轻量标签,无需额外图片资源。
  • lv_obj_set_size(img1, 200, 200):lv_img默认按原图尺寸绘制,设置对象尺寸可缩放绘制区域;同时lv_obj_align/lv_obj_align_to完成屏幕居中与相对对齐(LV_ALIGN_OUT_BOTTOM_MID表示贴齐 img1 底边中部、向下偏移 20 像素)。

MicroPython 版本对照

lv_example_img_1.py 展示了嵌入式 MicroPython 环境下同一逻辑的写法,其中两个细节值得注意:

  1. PNG 解码器注册:在读取 PNG 文件前,必须通过lv.img.decoder_create()创建解码器并挂接get_png_info/open_png回调(来自imagetools),否则 PNG 资源无法解码;
  2. 图像描述符构造:用lv.img_dsc_t({'data_size': len(png_data), 'data': png_data})把读入的 PNG 字节直接包装成图像描述符,再交给img1.set_src(...)。
decoder = lv.img.decoder_create() decoder.info_cb = get_png_info decoder.open_cb = open_png with open('../../assets/img_cogwheel_argb.png','rb') as f: png_data = f.read() img_cogwheel_argb = lv.img_dsc_t({'data_size': len(png_data), 'data': png_data}) img1 = lv.img(lv.scr_act()) img1.set_src(img_cogwheel_argb) img1.align(lv.ALIGN.CENTER, 0, -20) img1.set_size(200, 200)

示例二:运行时图像重着色(Recoloring)

图像重着色让 UI 可以「一套素材、任意换肤」——例如用同一个图标根据状态染成红色、绿色或灰色。

C 实现:四个滑条驱动颜色

lv_example_img_2.c 创建红、绿、蓝三个颜色分量滑条加一个「着色强度」滑条:

static void slider_event_cb(lv_event_t * e) { LV_UNUSED(e); lv_color_t color = lv_color_make(lv_slider_get_value(red_slider), lv_slider_get_value(green_slider), lv_slider_get_value(blue_slider)); lv_opa_t intense = lv_slider_get_value(intense_slider); lv_obj_set_style_img_recolor_opa(img1, intense, 0); lv_obj_set_style_img_recolor(img1, color, 0); }

实现机制分三步:

  1. 滑条范围设为0~255(lv_slider_set_range(slider, 0, 255)),滑条自身通过LV_PART_KNOB/LV_PART_INDICATOR局部样式着色,形成视觉分组;
  2. 每个滑条注册LV_EVENT_VALUE_CHANGED事件回调;回调内用lv_color_make()合成 RGB 颜色,读取强度滑条得到lv_opa_t透明度值;
  3. 通过两条样式属性生效:lv_obj_set_style_img_recolor()(着色色值)与lv_obj_set_style_img_recolor_opa()(着色强度)。LV_OPA_*宏(如LV_OPA_20、LV_OPA_50)即预定义的透明度常量。

代码末尾的lv_event_send(intense_slider, LV_EVENT_VALUE_CHANGED, NULL)是「手动触发一次事件」,保证界面一出现就立即用初始滑条值完成首次着色,无需用户先操作。

MicroPython 版本对照

lv_example_img_2.py 逻辑与 C 版一一对应,仅将 API 改为面向对象风格:

color = lv.color_make(red_slider.get_value(), green_slider.get_value(), blue_slider.get_value()) intense = intense_slider.get_value() img1.set_style_img_recolor_opa(intense, 0) img1.set_style_img_recolor(color, 0)

示例三:围绕枢轴点旋转与缩放

旋转与缩放是仪表类 UI 的常用能力——指针、罗盘、地图朝向都可以借此实现。

C 实现:动画驱动的变换

lv_example_img_3.c 用两个独立动画分别驱动角度与缩放:

lv_img_set_pivot(img, 0, 0); /* 以左上角为枢轴点 */ lv_anim_t a; lv_anim_init(&a); lv_anim_set_var(&a, img); lv_anim_set_exec_cb(&a, set_angle); /* 回调内部调用 lv_img_set_angle */ lv_anim_set_values(&a, 0, 3600); /* 0 ~ 3600,即 10 圈 */ lv_anim_set_time(&a, 5000); /* 5 秒 */ lv_anim_set_repeat_count(&a, LV_ANIM_REPEAT_INFINITE); lv_anim_start(&a); lv_anim_set_exec_cb(&a, set_zoom); /* 回调内部调用 lv_img_set_zoom */ lv_anim_set_values(&a, 128, 256); /* 128=原始大小,256=2 倍 */ lv_anim_set_playback_time(&a, 3000); /* 回放阶段 3 秒 */ lv_anim_start(&a);

关键参数语义(可从 lv_img.h 的接口注释印证):

  • 枢轴点lv_img_set_pivot(obj, x, y):变换围绕的固定点,坐标相对图像左上角;示例设为(0, 0)即绕左上角旋转,若想绕中心旋转应设为(w/2, h/2);
  • 角度lv_img_set_angle(obj, angle):单位为 0.1°,3600表示 360°;
  • 缩放lv_img_set_zoom(obj, zoom):256为 100%(1 倍),128为 50%,512为 200%,示例从 128 缩放到 256 实现 0.5 倍 → 1 倍的连续放大;
  • 动画通过lv_anim_set_exec_cb把set_angle/set_zoom两个静态函数作为执行回调,LV_ANIM_REPEAT_INFINITE表示无限循环;复用同一个lv_anim_t a变量分两次lv_anim_start(),实现角度与缩放两个动画并行。

MicroPython 版本对照

lv_example_img_3.py 用两个动画对象a1(角度)与a2(缩放)分别配置,通过set_custom_exec_cb(lambda a,val: set_angle(img,val))绑定执行回调:

img.set_pivot(0, 0) # Rotate around the top left corner a1.set_values(0, 3600); a1.set_time(5000) a1.set_repeat_count(lv.ANIM_REPEAT.INFINITE) a2.set_values(128, 256); a2.set_time(5000); a2.set_playback_time(3000) a2.set_repeat_count(lv.ANIM_REPEAT.INFINITE)

示例四:图像偏移与样式定制

图像偏移(offset)在「大图放小窗、滚动查看」的场景中非常实用,典型应用如滚动公告条、循环滚动的进度背景。

C 实现:样式 + 纵向偏移动画

lv_example_img_4.c 先定义并添加一个自定义样式,再让图像沿 Y 轴循环偏移:

static lv_style_t style; lv_style_init(&style); lv_style_set_bg_color(&style, lv_palette_main(LV_PALETTE_YELLOW)); lv_style_set_bg_opa(&style, LV_OPA_COVER); lv_style_set_img_recolor_opa(&style, LV_OPA_COVER); /* 完全着色 */ lv_style_set_img_recolor(&style, lv_color_black()); /* 染成黑色 */ lv_obj_t * img = lv_img_create(lv_scr_act()); lv_obj_add_style(img, &style, 0); lv_img_set_src(img, &img_skew_strip); lv_obj_set_size(img, 150, 100); lv_obj_center(img); /* 动画:0 -> 100 像素的 Y 偏移,无限循环,回放 500ms */ lv_anim_set_exec_cb(&a, ofs_y_anim); /* 回调内部调用 lv_img_set_offset_y */ lv_anim_set_values(&a, 0, 100); lv_anim_set_time(&a, 3000); lv_anim_set_playback_time(&a, 500); lv_anim_set_repeat_count(&a, LV_ANIM_REPEAT_INFINITE);

要点拆解:

  • 样式叠加两种效果:lv_style_set_bg_*给控件绘制黄色背景(LV_PALETTE_YELLOW+LV_OPA_COVER),lv_style_set_img_recolor*把斜条纹图整体染成黑色——一张白色/浅色素材可通过此方式瞬间变成深色主题素材;
  • 偏移 API:lv_img_set_offset_x/y(obj, coord)沿指定轴平移图像内容,配合lv_obj_set_size限定可视窗口,即可做出「窗口内滚动」效果;
  • 动画使用LV_ANIM_REPEAT_INFINITE无限循环,lv_anim_set_playback_time(500)让回程(100→0)只需 500ms,形成快速复位、慢速滚动的节奏。

在 X-TRACK 项目中的实际应用

X-TRACK 的 LVGL 模拟器与真机固件共用同一套 UI 代码,lv_img正是其界面图像渲染的基础控件。从源码结构看,X-TRACK 主要页面均直接使用lv_img系列 API:

  • LiveMapView.cpp:实时地图页面使用lv_img显示地图瓦片与定位图标——地图缩放、朝向旋转正是依赖本文示例三讲解的lv_img_set_zoom/lv_img_set_angle/lv_img_set_pivot能力;
  • StatusBar.cpp:状态栏中的电池、卫星、闹钟等图标均由lv_img承载,运行时切换图标/着色对应示例一、二的能力;
  • SystemInfosView.cpp:系统信息页的图标排版使用lv_img与对齐 API;
  • ResourcePool.cpp:统一通过图像描述符(lv_img_dsc_t)对外提供页面图片资源,页面层只需lv_img_set_src(img, pool->xxx)即可注入资源——这与示例一LV_IMG_DECLARE+lv_img_set_src的模式同构。

因此,掌握本文四个示例,就等于拿到了 X-TRACK 界面图像体系(图标、地图瓦片、动效)的底层基本功:先以变量/符号建图,再用样式重着色适配主题,用枢轴点 + 角度 + 缩放实现指针与地图变换,最后用偏移配合窗口实现滚动效果。

常用 API 速查

结合示例与 lv_img.h 声明,核心接口汇总如下:

函数作用关键取值/说明
lv_img_create(parent)创建图像对象返回lv_obj_t*
lv_img_set_src(obj, src)设置图像来源图像变量指针 / 文件路径 /LV_SYMBOL_*符号
lv_img_set_angle(obj, angle)设置旋转角单位 0.1°,3600=360°
lv_img_set_pivot(obj, x, y)设置变换枢轴点相对图像左上角
lv_img_set_zoom(obj, zoom)设置缩放256=100%,128=50%
lv_img_set_offset_x(obj, x)/lv_img_set_offset_y(obj, y)图像内容偏移配合对象尺寸形成滚动窗口
lv_obj_set_style_img_recolor(obj, color, sel)重着色色值与示例二配合使用
lv_obj_set_style_img_recolor_opa(obj, opa, sel)重着色强度LV_OPA_*透明度常量

运行前提说明:以上示例编译开关依赖LV_USE_IMG与LV_BUILD_EXAMPLES(示例文件开头#if LV_USE_IMG && LV_BUILD_EXAMPLES已体现),示例二额外依赖LV_USE_SLIDER;这些配置位于模拟器工程的 lv_conf.h 中,读者可在本地查看与调整。若在资源受限的 MCU 上使用,建议参考示例按需裁剪动画与变换功能,并优先使用经过 LVGL 图像转换工具(仓库 Tools 目录下提供TilesConverterForLVGL.exe等)预处理的 C 数组图像格式,以降低运行时解码开销。

  • 智能硬件
  • 嵌入式
  • 硬件开发

【免费下载链接】X-TRACK

A GPS bicycle speedometer that supports offline maps and track recording

项目地址:https://gitcode.com/gh_mirrors/xt/X-TRACK
点击查看免费下载
上一篇:getnf高级用法:批量安装、卸载与更新字体的10个实用命令
下一篇:MMRotate旋转目标检测完整指南:从入门到实战

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询