LVGL库入门 04 - 颜色与图像

news/2024/9/28 5:22:20 标签: linux, c++, lvgl, c
cle class="baidu_pl">
cle_content" class="article_content clearfix">
content_views" class="htmledit_views">

ckground-color:transparent;">1、颜色

ckground-color:transparent;">1.1、构造颜色

在 LVGL 中࿰c;颜色以结构 <code>lv_color_tcode> 表示。在最开始移植整个工程时࿰c;曾经在 <code>lv_conf.hcode> 中修改过颜色深度:

/*Color depth: 1 (1 byte per pixel), 8 (RGB332), 16 (RGB565), 32 (ARGB8888)*/
#define LV_COLOR_DEPTH 32

LVGL 会自动根据所选的颜色深度创建合适的颜色结构。在接下来几处位置还有几个与颜色有关的配置选项࿰c;可以参照注释修改。

例如࿰c;16 位 big-endian 的颜色定义为:

typedef union {
    struct {
        uint16_t blue  : 5;
        uint16_t green : 6;
        uint16_t red   : 5;
    } ch;
    uint16_t full;
} lv_color16_t;
typedef lv_color16_t lv_color_t;

那么就可以根据该结构创建合适的颜色值了:

lv_color_t orange = {
    .ch = {
        .red   = 0b11111,
        .green = 0b101001,
        .blue  = 0
    }
};

直接创建 RGB565 的颜色格式有点难以调色࿰c;不过可以借用以下函数从十六位颜色中生成合适的颜色值:

lv_color_t orange = lv_color_make(0xFF, 0xA5, 0);  // 从颜色通道创建
lv_color_t aqua = lv_color_hex(0x00FFFF);          // 从十六进制创建
lv_color_t lightgrey = lv_color_hex3(0xddd);       // 从十六进制简写创建

这些颜色在创建时࿰c;每种颜色通道的值都使用 0~255 表示即可࿰c;创建过程中会自动转换为合适的颜色值。

LVGL 还提供了 HSV 格式的颜色支持࿰c;

lv_color_t red = lv_color_hsv_to_rgb(0, 100, 100);   // 从 HSV 颜色空间创建颜色
lv_color_hsv_t blue = lv_color_rgb_to_hsv(r, g, b);  // 将 RGB 颜色转换为 HSV 颜色

除此之外࿰c;<code>lv_color_tcode> 、RGB 颜色、HSV 颜色之间也能互相转换。


如果觉得 16 进制的颜色还是不够直观࿰c;还可以使用调色板功能。LVGL 提供了常用颜色的色值表示࿰c;可以直接使用、微调、混合这些颜色。

例如࿰c;以下直接调出了一个紫色:

lv_color_t purple = lv_palette_main(LV_PALETTE_PURPLE)

如果觉得默认的紫色太深或太浅的话࿰c;还可以在调色板中更改亮度:

lv_color_t dark_purple = lv_palette_darken(LV_PALETTE_PURPLE, 2)  // 调深两级࿰c;最多可以调深或浅 4 级
lv_color_t light_purple = lv_color_lighten(purple, 60);  // 调浅一些࿰c;调到 255 就变成纯白

甚至还可以将两种颜色混合:

lv_color_t orange = lv_color_mix(red, yellow, 156);

比例的取值为 0~255 ࿰c;例如设定为 0 就是全红࿰c;128 就是红黄各占一半等。

可以将一个颜色类型直接应用到以下样式属性中:

属性名含义
<code>bg_colorcode>背景颜色
<code>border_colorcode>边框颜色
<code>outline_colorcode>轮廓颜色
<code>shadow_colorcode>阴影颜色
<code>text_colorcode>文本颜色

以及上一节提到的直线和弧线颜色。

ckground-color:transparent;">1.2、透明度

有时候两个控件间可能发生重叠࿰c;这个时候就可以给它们设置一个透明度。

透明度使用类型 <code>lv_opa_tcode> 表示࿰c;LVGL 预定义了几个表示透明度的宏:<code>LV_OPA_TRANSPcode> 表示完全透明࿰c;<code>LV_OPA_COVER code>表示完全不透明࿰c;其余的 <code>LV_OPA_10 code>~ <code>LV_OPA_90 code>整十表示的透明度依次递减。

可以将透明度应用到以下样式属性中:

属性名含义
<code>bg_opacode>背景透明度
<code>border_opacode>边框透明度
<code>outline_opacode>轮廓透明度
<code>shadow_opacode>阴影透明度
<code>text_opacode>文本透明度
<code>opacode>整体透明度

以及直线和弧线透明度。例如࿰c;以下创建了两个部分重叠的控件࿰c;并在一个的背景上加透明度:

static lv_style_t style_grass;
lv_style_init(&style_grass);
lv_style_set_opa(&style_grass, LV_OPA_30);
lv_obj_t* obj = lv_obj_create(lv_scr_act());
lv_obj_t* cover = lv_obj_create(lv_scr_act());
lv_obj_add_style(cover, &style_grass, 0);

这样就可以看见被遮挡的控件了:

class="img-center">imagec="https://img-blog.csdnimg.cn/img_convert/91a4fe5a5fd3a87d89285260fd002ad9.jpeg" width="202" />

注意需要给上层࿰c;即后创建的的控件加透明度才会有这样的效果。透明度其实就是为控件重新调色࿰c;因此不是 32 位颜色的屏幕也可以使用透明度。

<code>lv_opa_tcode> 类型的本质就是 8 位无符号整数࿰c;因此可以自行创建一个透明度数值࿰c;设为 255 就代表完全透明;还可以将透明度应用到 <code>lv_color_mix()code> 的第三个参数上。

ckground-color:transparent;">1.3、渐变色

可以使用渐变色给控件加上更美观的效果。

只有背景颜色能设置渐变色。一个渐变色的效果由以下几个属性支配:

属性名含义
<code>bg_colorcode>主要颜色
<code>bg_grad_colorcode>渐变颜色
<code>bg_grad_dircode>渐变方向
<code>bg_main_stopcode>渐变开始位置
<code>bg_grad_stopcode>渐变结束位置
<code>bg_dither_modecode>渲染模式

当确定了渐变方向后࿰c;渐变从 <code>bg_main_stopcode> 位置开始࿰c;由 <code>bg_colorcode> 过度到 <code>bg_grad_colorcode> ࿰c;在 <code>bg_grad_stopcode> 位置结束。这里的位置是由比例衡量的࿰c;渐变区域在每个方向都被划分为 256 份࿰c;例如 128 代表中间位置࿰c;255 代表结束位置等。

例如࿰c;以下代码:

lv_obj_t* obj01 = lv_obj_create(lv_scr_act());
lv_obj_set_style_bg_color(obj01, lv_palette_main(LV_PALETTE_BLUE), 0);
lv_obj_set_style_bg_grad_color(obj01, lv_palette_main(LV_PALETTE_RED), 0);
lv_obj_set_style_bg_grad_dir(obj01, LV_GRAD_DIR_HOR, 0);

渐变效果为水平方向从蓝色一直渐变到红色:

class="img-center">imagec="https://img-blog.csdnimg.cn/img_convert/4d563e43707050f254a37722ee5c84c4.jpeg" width="150" />

再如࿰c;以下代码:

lv_obj_t* obj02 = lv_obj_create(lv_scr_act());
lv_obj_set_style_bg_color(obj02, lv_palette_main(LV_PALETTE_GREEN), 0);
lv_obj_set_style_bg_grad_color(obj02, lv_palette_main(LV_PALETTE_PURPLE), 0);
lv_obj_set_style_bg_grad_stop(obj02, 128, 0);
lv_obj_set_style_bg_grad_dir(obj02, LV_GRAD_DIR_VER, 0);

渐变效果为竖直方向从绿色一直渐变到紫色࿰c;但实际渐变区域只有上半部分:

class="img-center">imagec="https://img-blog.csdnimg.cn/img_convert/9802b5b324ec48064ae4c9d56cccc1ea.jpeg" width="136" />

还可以使用简写属性 <code>bg_gradcode> 设置完整的渐变属性。这种情况下࿰c;渐变使用结构 <code>lv_grad_dsc_tcode> 描述:

typedef struct {
    lv_gradient_stop_t stops[LV_GRADIENT_MAX_STOPS];
    uint8_t            stops_count;
    lv_grad_dir_t      dir    : 3;
    lv_dither_mode_t   dither : 3;
} lv_grad_dsc_t;

宏 <code>LV_GRADIENT_MAX_STOPScode> 决定了最大拥有的渐变颜色数࿰c;可以在 <code>lv_conf_internal.hcode> 大约 377 行修改该宏的数量:

#ifndef LV_GRADIENT_MAX_STOPS
    #ifdef CONFIG_LV_GRADIENT_MAX_STOPS
        #define LV_GRADIENT_MAX_STOPS CONFIG_LV_GRADIENT_MAX_STOPS
    #else
        #define LV_GRADIENT_MAX_STOPS 3
    #endif
#endif

然后就可以自定义多种颜色的渐变了:

static lv_grad_dsc_t grad_sunset;
grad_sunset.stops[0] = (lv_gradient_stop_t){ .color = lv_palette_main(LV_PALETTE_RED), .frac = 96 };
grad_sunset.stops[1] = (lv_gradient_stop_t){ .color = lv_palette_main(LV_PALETTE_ORANGE), .frac = 128 };
grad_sunset.stops[2] = (lv_gradient_stop_t){ .color = lv_palette_main(LV_PALETTE_BLUE), .frac = 216 };
grad_sunset.stops_count = 3;
grad_sunset.dir = LV_GRAD_DIR_VER;
lv_obj_t* obj03 = lv_obj_create(lv_scr_act());
lv_obj_set_style_bg_grad(obj03, &grad_sunset, 0);

效果为:

class="img-center">imagec="https://img-blog.csdnimg.cn/img_convert/1d55a9489a3de71e8f3361ea1701e715.jpeg" width="135" />

ckground-color:transparent;">1.4、颜色的其它内容

LVGL 还提供了许多处理颜色的滤镜。可以使用样式属性 <code>blend_modecode> 设置颜色和背景色的融合。例如࿰c;以下将控件的颜色设置为背景色的反色:

lv_obj_set_style_blend_mode(obj03, LV_BLEND_MODE_SUBTRACTIVE, 0);

效果为:

class="img-center">imagec="https://img-blog.csdnimg.cn/img_convert/3c5a27653e5a66b07b61997b8b0374ec.jpeg" width="136" />

注意边框的颜色也变成反色了。

最后࿰c;LVGL 中还要一个控件 color wheel ࿰c;可以快速创建一个颜色选择器。它的默认表现形式为:

class="img-center">imagec="https://img-blog.csdnimg.cn/img_convert/41b477ba09bcdf2b29224c46e61edf35.gif" width="240" />

它类似于圆弧࿰c;并可以通过长按切换模式。可以使用函数 <code>lv_colorwheel_get_rgb()code> 获取当前选择的颜色。

ckground-color:transparent;">2、图片

ckground-color:transparent;">2.1、创建图片

图片可以以两种方式存储:一是作为一个数组之类的变量࿰c;二是通过二进制文件的形式存储。由于还没有介绍文件相关的内容࿰c;这里仅介绍使用数组的方式来存储并使用图片。

LVGL 已经提供了在线图片转换器࿰c;可以直接在 Online image converter - BMP, JPG or PNG to C array or binary | LVGL 将一般的 PNG 或 JPG 图片转换为符合要求的 C 语言对象:

class="img-center">imagec="https://img-blog.csdnimg.cn/img_convert/11bdcc8f1434146137159e90fb9b5254.jpeg" width="1045" />

注意转换完成后得到的是一个完整的源文件࿰c;文件名同时也是图片的变量名。以上唯一值的注意的一点是图片所用的颜色格式࿰c;一般来说颜色格式可以分为以下几类:

  1. True color :自动适配当前项目使用的颜色深度
  2. Indexed :从调色板创建较少的颜色数目
  3. Alpha only :单色图像࿰c;只使用透明度
  4. Raw :使用图像原本的颜色格式

最后一个 RBG565-A8 就不必多说了。值的注意的是࿰c;以上有一种叫“Chroma key” 的颜色格式࿰c;它对应 <code>lv_conf.hcode> 的第 42 行的配置࿰c;注释是这样说的:

/*Images pixels with this color will not be drawn if they are chroma keyed)*/
#define LV_COLOR_CHROMA_KEY lv_color_hex(0x00ff00)         /*pure green*/

更多有关于此的介绍可以阅读维基百科 https://en.wikipedia.org/wiki/Chroma_key

转换完成后࿰c;将得到的源文件添加到当前工程内࿰c;然后通过以下几行代码就可以显示该图像:

LV_IMG_DECLARE(class="tags" href="/tags/LVGL.html" title=lvgl>lvgl_logo);
lv_obj_t* img01 = lv_img_create(lv_scr_act());
lv_img_set_src(img01, &class="tags" href="/tags/LVGL.html" title=lvgl>lvgl_logo);

这里第一个宏的作用本质就是一个 <code>externcode> 语句。显示的效果为:

class="img-center">imagec="https://img-blog.csdnimg.cn/img_convert/8ff1e1a317d1b59bb0c5200a0725e187.jpeg" width="384" />

注意这里在模拟器上创建的图片是具有透明度的。

ckground-color:transparent;">2.2、图片的属性

像直线和圆弧一样࿰c;图片对象也是有特殊的属性的࿰c;不过比较少:

属性简介
<code>img_opacode>图片透明度
<code>img_recolorcode>可以给图片加上一层颜色滤镜
<code>img_recolor_opacode>这层滤镜的透明度

默认情况下࿰c;图片控件会自动调整宽度以适应图片大小。如果控件过小࿰c;那么图片的额外部分会被去除;如果控件过大࿰c;那么图片会像地砖一样重复铺开来填补剩下的区域。

可以通过 <code>lv_img_set_offset_x(img, x_ofs)code> 与 y 轴对应的函数给图片设置一个偏移量来修改显示范围。例如࿰c;可以通过偏移量结合控件宽度来裁剪图片:

lv_img_set_offset_x(img01, -2);
lv_img_set_offset_y(img01, -7);
lv_obj_set_size(img01, 74, 74);

这里通过负值来将图片向左上角偏移࿰c;从而框选出合适的区域:

class="img-center">imagec="https://img-blog.csdnimg.cn/img_convert/18d2fb3bc4e5a993960df86ab195bc1a.jpeg" width="119" />

ckground-color:transparent;">2.3、图片按钮

最后再介绍一个内容࿰c;可以通过图片来创建一个按钮。这种情况下࿰c;需要准备三张图片࿰c;分别描述按钮的左边、中间和右边。

例如࿰c;以下准备图片如下:

class="img-center">imagec="https://img-blog.csdnimg.cn/img_convert/ab855fc69d6ff07d71d2ac3039e8937d.png" width="21" />

 

class="img-center">imagec="https://img-blog.csdnimg.cn/img_convert/3d40bcacc151e727e01f29e295689815.png" width="10" />

 

class="img-center">imagec="https://img-blog.csdnimg.cn/img_convert/6b4f0f5e2d27babe6cc8ac753f45a27f.png" width="24" />

由于标签的宽度是不确定的࿰c;因此中间的图片必须是水平可平铺的。将其转换为对应的图片格式后࿰c;可以通过以下代码创建一个图片按钮:

lv_obj_t* imgbtn = lv_imgbtn_create(lv_scr_act());
lv_imgbtn_set_src(imgbtn, LV_IMGBTN_STATE_RELEASED, &imgbtn_left, &imgbtn_mid, &imgbtn_right);
lv_obj_t* label = lv_label_create(imgbtn);
lv_label_set_text(label, "Image Button");
lv_obj_set_style_img_recolor_opa(imgbtn, LV_OPA_30, LV_STATE_PRESSED);
lv_obj_set_style_img_recolor(imgbtn, lv_color_black(), LV_STATE_PRESSED);

注意在创建的过程中࿰c;将以上图片应用到按钮的普通状态(即什么事件都没有的状态)的外观中。这里通过给点击事件加上一层深色的滤镜使点击时外观可以发生改变:

class="img-center">imagec="https://img-blog.csdnimg.cn/img_convert/8cd203424839ff80b3314010ff198f1d.gif" width="240" />

这样按钮就可以变得很花哨了。

以上对于图片的介绍比较简单࿰c;不过也基本足以应付一般的使用场景了。更多细节可以参考官方文档。

ckground-color:transparent;">3、参考资料/延伸阅读

Colors — LVGL documentation

颜色参考文档

https://docs.class="tags" href="/tags/LVGL.html" title=lvgl>lvgl.io/master/overview/image.html
https://docs.class="tags" href="/tags/LVGL.html" title=lvgl>lvgl.io/master/widgets/core/img.html

有关图片及图片控件的完整使用描述


http://www.niftyadmin.cn/n/5144248.html

相关文章

【Java】AI+智慧工地云平台源码(SaaS模式)

伴随着科学技术的不断发展&#xff0c;信息化手段、移动技术、智能穿戴及工具在工程施工阶段的应用不断提升&#xff0c;智慧工地概念应运而生&#xff0c;庞大的建设规模催生着智慧工地的探索和研发。 一、带你认识智慧工地 伴随着技术的不断发展&#xff0c;信息化手段、移动…

【数据结构复习之路】数组和广义表(严蔚敏版)万字详解主打基础

专栏&#xff1a;数据结构复习之路 复习完上面三章【线性表】【栈和队列】【串】&#xff0c;我们接着复习数组和广义表&#xff0c;这篇文章我写的非常详细且通俗易懂&#xff0c;看完保证会带给你不一样的收获。如果对你有帮助&#xff0c;看在我这么辛苦整理的份上&#xf…

nginx转发接口一会正常一会返回404.html

在使用nginx(版本是1.24.0)转发时&#xff0c;出现了api接口一会正常返回&#xff0c;一会返回 404.html的情况。 以下是我的nginx配置&#xff1a; nginx.conf #user nobody; worker_processes 1;#error_log logs/error.log; #error_log logs/error.log notice; #error_…

vim三种模式,文本操作(操作字符/光标,列出行号可视化块模式/多文件查看)

目录 vim--文本编辑器 功能 基本概念 命令/默认模式 插入模式 底行模式 文本操作 引入 移动光标位置 删除字符 -- x/dd 复制/粘贴字符 -- yw/yyp 替换文本 -- r / %s 底行模式 全局替换 -- /g 撤销操作 -- u / ctrlr 修改字符 -- cw 示例 跳行 -- ctrlg 底行…

【JVM经典面试题(五十二道)】

文章目录 JVM经典面试题&#xff08;五十二道&#xff09;引言1.什么是JVM 内存管理2.能说一下JVM的内存区域吗&#xff1f;3.说一下JDK1.6、1.7、1.8内存区域的变化&#xff1f;4.为什么使用元空间替代永久代作为方法区的实现&#xff1f;5.对象创建的过程了解吗&#xff1f;6…

高防CDN:分布式节点的网络安全之道

在当今数字化时代&#xff0c;网络攻击已经成为了威胁网站和在线服务的常见现象。为了应对这一挑战&#xff0c;高防CDN&#xff08;内容分发网络&#xff09;崭露头角&#xff0c;采用分布式节点的方式提供了强大的网络安全防护。本文将详细说明高防CDN采用分布式节点的意义&a…

金融帝国实验室(Capitalism Lab)即将隆重推出『出口公司』功能

『金融帝国实验室』&#xff08;Capitalism Lab&#xff09;即将迎来v10.0.00重大版本更新&#xff01; 并将为〔实验性DLC〕引入全新【出口公司】功能。 ————————————— 【出口公司】允许您&#xff1a; >通过出口客户搜索查找全球买家&#xff1b; >建立…

Java,面向对象,抽象类和抽象方法(abstract的使用)

关于抽象类和抽象方法的使用&#xff0c;以Person和student和Teacher为例&#xff0c;若Student类和Teacher继承于Person类&#xff0c;老师和学生都有Person的特征。在一个班级里&#xff0c;只需要创建老师和学生的实例&#xff0c;并不需要创建Person的实例。关于Person的方…