2、图像对象创建:lv_img_create、lv_img_set_src、图像对齐与缩放模式
好,咱们接着聊图像显示。上一节我们把图像数据怎么塞进内存讲清楚了,这一节就来看看怎么在屏幕上把它“亮”出来。
说白了,LVGL里显示一张图,核心就三步:创建对象、绑定数据源、设置显示方式。我刚开始用LVGL时,觉得这有啥难的?不就是new一个对象,传个指针嘛。结果真上手才发现,坑全在对齐和缩放上。你想想看,一张800x480的图,硬塞进一个200x200的框里,不设置缩放模式,那画面简直没法看。
2.1 创建图像对象:lv_img_create
创建图像对象,API极其简单:
lv_obj_t * img = lv_img_create(lv_scr_act()); // 在当前屏幕创建
嗯,就这么一行。但这里有个细节我提一下——父对象的选择。我个人习惯,如果图像是背景或者装饰,直接挂到屏幕下;如果是某个容器里的图标,那就挂到容器下。这样后续做移动、隐藏,层级关系清晰很多。
创建完之后,默认的图像对象是空的,啥也不显示。你得给它“喂”数据。
2.2 绑定图像数据源:lv_img_set_src
这是最核心的一步。数据源可以是三种东西:
- 内部图像(C数组):用转换工具生成的 .c 文件里的数组
- 外部文件(文件系统):比如SD卡里的 .bin 或 .png
- 符号/字符串:显示字体图标
代码示例:
// 方式一:内部图像(最常见)
extern const lv_img_dsc_t my_image;
lv_img_set_src(img, &my_image);
// 方式二:文件系统中的图片
lv_img_set_src(img, "S:/images/logo.bin");
// 方式三:符号(字体图标)
lv_img_set_src(img, LV_SYMBOL_HOME);
这里有个容易踩的坑:图像描述符必须保持有效。我曾经把图像数组定义在函数内部,结果函数退出后数组被释放,屏幕直接花屏。嗯,血的教训。图像数据要么用 const 修饰放在全局区,要么用动态内存分配并保证生命周期。
2.3 图像对齐模式
图像对象本身是一个矩形区域,图像在这个区域里怎么摆放?这就涉及到对齐了。
LVGL提供了几个对齐标志:
| 对齐方式 | 宏定义 | 说明 |
|---|---|---|
| 左上 | LV_IMG_ALIGN_TOP_LEFT | 默认,图像左上角对齐对象左上角 |
| 居中 | LV_IMG_ALIGN_CENTER | 图像中心对齐对象中心 |
| 右下 | LV_IMG_ALIGN_BOTTOM_RIGHT | 图像右下角对齐对象右下角 |
| 自定义偏移 | LV_IMG_ALIGN_STRETCH | 配合偏移量使用 |
设置对齐的API:
lv_img_set_align(img, LV_IMG_ALIGN_CENTER);
你可能会问:这有啥用?我举个例子。假设你有一个100x100的按钮,里面放一个20x20的图标。如果不设置对齐,图标默认贴在左上角,丑不丑?设成居中,图标就乖乖待在正中间了。
2.4 缩放模式
这才是重头戏。图像缩放,说白了就是图像和显示区域尺寸不匹配时,系统该怎么处理。
LVGL提供了三种缩放模式:
| 模式 | 宏定义 | 行为 |
|---|---|---|
| 不缩放 | LV_IMG_ZOOM_NONE | 保持原始尺寸,超出部分裁剪 |
| 缩放填充 | lv_img_set_zoom(img, 256 + offset) | 按比例缩放,256为原始大小 |
| 拉伸填充 | 配合对象尺寸 | 强制拉伸到对象大小,可能变形 |
代码示例:
// 放大到200%
lv_img_set_zoom(img, 512); // 256 = 100%, 512 = 200%
// 缩小到50%
lv_img_set_zoom(img, 128); // 128 = 50%
// 设置旋转角度(配合缩放)
lv_img_set_angle(img, 300); // 300/10 = 30度
还有一个容易被忽略的点:缩放后的图像质量。LVGL默认使用最近邻插值,速度快但锯齿明显。如果你追求画质,可以开启抗锯齿:
lv_img_set_antialias(img, true);
但代价是性能开销。嗯,这里就是个取舍问题了——你要速度还是要画质?
2.5 综合示例:一个带缩放和居中的图像
来,看一个完整的例子:
/* 创建图像对象 */
lv_obj_t * img = lv_img_create(lv_scr_act());
lv_obj_set_size(img, 200, 200); // 对象大小200x200
lv_obj_center(img); // 对象居中
/* 绑定图像数据 */
extern const lv_img_dsc_t my_photo;
lv_img_set_src(img, &my_photo);
/* 设置对齐和缩放 */
lv_img_set_align(img, LV_IMG_ALIGN_CENTER); // 图像居中
lv_img_set_zoom(img, 384); // 放大到150%
lv_img_set_antialias(img, true); // 开启抗锯齿
这段代码跑起来,你会看到一张居中的、放大了1.5倍的、边缘平滑的图像。嗯,效果还不错。
2.6 小结
这一节的内容其实就三个核心点:
- 创建:
lv_img_create指定父对象 - 绑定:
lv_img_set_src选对数据源类型 - 显示:对齐 + 缩放,决定图像怎么呈现
我个人觉得,对齐和缩放是UI美观度的关键。很多嵌入式设备的界面看起来“土”,就是因为图像要么贴边、要么变形。你花点心思调好这两个参数,界面质感能提升一个档次。
下一节,我们会深入聊聊图像缓存——怎么让图像显示更快、更省内存。到时候见。