草庐IT

LVGL库入门教程 - 颜色和图像

frozencandles 2023-03-28 原文

颜色

构造颜色

在 LVGL 中,颜色以结构 lv_color_t 表示。在最开始移植整个工程时,曾经在 lv_conf.h 中修改过颜色深度:

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

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

例如,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 的颜色格式有点难以调色,不过可以借用以下函数从十六位颜色中生成合适的颜色值:

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);       // 从十六进制简写创建

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

LVGL 还提供了 HSV 格式的颜色支持,

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 颜色

除此之外,lv_color_t 、RGB 颜色、HSV 颜色之间也能互相转换。


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

例如,以下直接调出了一个紫色:

lv_color_t purple = lv_palette_main(LV_PALETTE_PURPLE)

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

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

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

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

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

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

属性名 含义
bg_color 背景颜色
border_color 边框颜色
outline_color 轮廓颜色
shadow_color 阴影颜色
text_color 文本颜色

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

透明度

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

透明度使用类型 lv_opa_t 表示,LVGL 预定义了几个表示透明度的宏:LV_OPA_TRANSP 表示完全透明,LV_OPA_COVER 表示完全不透明,其余的 LV_OPA_10 ~ LV_OPA_90 整十表示的透明度依次递减。

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

属性名 含义
bg_opa 背景透明度
border_opa 边框透明度
outline_opa 轮廓透明度
shadow_opa 阴影透明度
text_opa 文本透明度
opa 整体透明度

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

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);

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

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

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

渐变色

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

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

属性名 含义
bg_color 主要颜色
bg_grad_color 渐变颜色
bg_grad_dir 渐变方向
bg_main_stop 渐变开始位置
bg_grad_stop 渐变结束位置
bg_dither_mode 渲染模式

当确定了渐变方向后,渐变从 bg_main_stop 位置开始,由 bg_color 过度到 bg_grad_color ,在 bg_grad_stop 位置结束。这里的位置是由比例衡量的,渐变区域在每个方向都被划分为 256 份,例如 128 代表中间位置,255 代表结束位置等。

例如,以下代码:

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);

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

再如,以下代码:

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);

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

还可以使用简写属性 bg_grad 设置完整的渐变属性。这种情况下,渐变使用结构 lv_grad_dsc_t 描述:

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;

LV_GRADIENT_MAX_STOPS 决定了最大拥有的渐变颜色数,可以在 lv_conf_internal.h 大约 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);

效果为:

颜色的其它内容

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

lv_obj_set_style_blend_mode(obj03, LV_BLEND_MODE_SUBTRACTIVE, 0);

效果为:

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

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

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

图片

创建图片

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

LVGL 已经提供了在线图片转换器,可以直接在 https://lvgl.io/tools/imageconverter 将一般的 PNG 或 JPG 图片转换为符合要求的 C 语言对象:

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

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

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

/*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

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

LV_IMG_DECLARE(lvgl_logo);
lv_obj_t* img01 = lv_img_create(lv_scr_act());
lv_img_set_src(img01, &lvgl_logo);

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

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

图片的属性

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

属性 简介
img_opa 图片透明度
img_recolor 可以给图片加上一层颜色滤镜
img_recolor_opa 这层滤镜的透明度

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

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

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

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

图片按钮

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

例如,以下准备图片如下:

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

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);

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

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

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

首发于:http://frozencandles.fun/archives/383

参考资料/延伸阅读

https://docs.lvgl.io/master/overview/color.html

颜色参考文档

https://docs.lvgl.io/master/overview/image.html
https://docs.lvgl.io/master/widgets/core/img.html

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

有关LVGL库入门教程 - 颜色和图像的更多相关文章

  1. ruby - 在没有 sass 引擎的情况下使用 sass 颜色函数 - 2

    我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re

  2. ruby 诅咒颜色 - 2

    如何使用Ruby的默认Curses库获取颜色?所以像这样:puts"\e[0m\e[30;47mtest\e[0m"效果很好。在浅灰色背景上呈现漂亮的黑色。但是这个:#!/usr/bin/envrubyrequire'curses'Curses.noecho#donotshowtypedkeysCurses.init_screenCurses.stdscr.keypad(true)#enablearrowkeys(forpageup/down)Curses.stdscr.nodelay=1Curses.clearCurses.setpos(0,0)Curses.addstr"Hello

  3. ruby-on-rails - 添加回形针新样式不影响旧上传的图像 - 2

    我有带有Logo图像的公司模型has_attached_file:logo我用他们的Logo创建了许多公司。现在,我需要添加新样式has_attached_file:logo,:styles=>{:small=>"30x15>",:medium=>"155x85>"}我是否应该重新上传所有旧数据以重新生成新样式?我不这么认为……或者有什么rake任务可以重新生成样式吗? 最佳答案 参见Thumbnail-Generation.如果rake任务不适合你,你应该能够在控制台中使用一个片段来调用重新处理!关于相关公司

  4. ruby - Rails 3 的 RGB 颜色选择器 - 2

    状态:我正在构建一个应用程序,其中需要一个可供用户选择颜色的字段,该字段将包含RGB颜色代码字符串。我已经测试了一个看起来很漂亮但效果不佳的。它是“挑剔的颜色”,并托管在此存储库中:https://github.com/Astorsoft/picky-color.在这里我打开一个关于它的一些问题的问题。问题:请建议我在Rails3应用程序中使用一些颜色选择器。 最佳答案 也许页面上的列表jQueryUIDevelopment:ColorPicker为您提供开箱即用的产品。原因是jQuery现在包含在Rails3应用程序中,因此使用基

  5. postman接口测试工具-基础使用教程 - 2

    1.postman介绍Postman一款非常流行的API调试工具。其实,开发人员用的更多。因为测试人员做接口测试会有更多选择,例如Jmeter、soapUI等。不过,对于开发过程中去调试接口,Postman确实足够的简单方便,而且功能强大。2.下载安装官网地址:https://www.postman.com/下载完成后双击安装吧,安装过程极其简单,无需任何操作3.使用教程这里以百度为例,工具使用简单,填写URL地址即可发送请求,在下方查看响应结果和响应状态码常用方法都有支持请求方法:getpostputdeleteGet、Post、Put与Delete的作用get:请求方法一般是用于数据查询,

  6. LC滤波器设计学习笔记(一)滤波电路入门 - 2

    目录前言滤波电路科普主要分类实际情况单位的概念常用评价参数函数型滤波器简单分析滤波电路构成低通滤波器RC低通滤波器RL低通滤波器高通滤波器RC高通滤波器RL高通滤波器部分摘自《LC滤波器设计与制作》,侵权删。前言最近需要学习放大电路和滤波电路,但是由于只在之前做音乐频谱分析仪的时候简单了解过一点点运放,所以也是相当从零开始学习了。滤波电路科普主要分类滤波器:主要是从不同频率的成分中提取出特定频率的信号。有源滤波器:由RC元件与运算放大器组成的滤波器。可滤除某一次或多次谐波,最普通易于采用的无源滤波器结构是将电感与电容串联,可对主要次谐波(3、5、7)构成低阻抗旁路。无源滤波器:无源滤波器,又称

  7. 在VMware16虚拟机安装Ubuntu详细教程 - 2

    在VMware16.2.4安装Ubuntu一、安装VMware1.打开VMwareWorkstationPro官网,点击即可进入。2.进入后向下滑动找到Workstation16ProforWindows,点击立即下载。3.下载完成,文件大小615MB,如下图:4.鼠标右击,以管理员身份运行。5.点击下一步6.勾选条款,点击下一步7.先勾选,再点击下一步8.去掉勾选,点击下一步9.点击下一步10.点击安装11.点击许可证12.在百度上搜索VM16许可证,复制填入,然后点击输入即可,亲测有效。13.点击完成14.重启系统,点击是15.双击VMwareWorkstationPro图标,进入虚拟机主

  8. 微信小程序开发入门与实战(Behaviors使用) - 2

    @作者:SYFStrive @博客首页:HomePage📜:微信小程序📌:个人社区(欢迎大佬们加入)👉:社区链接🔗📌:觉得文章不错可以点点关注👉:专栏连接🔗💃:感谢支持,学累了可以先看小段由小胖给大家带来的街舞👉微信小程序(🔥)目录自定义组件-behaviors    1、什么是behaviors    2、behaviors的工作方式    3、创建behavior    4、导入并使用behavior    5、behavior中所有可用的节点    6、同名字段的覆盖和组合规则总结最后自定义组件-behaviors    1、什么是behaviorsbehaviors是小程序中,用于实现

  9. ruby-on-rails - 在 Ruby (on Rails) 中使用 imgur API 获取图像 - 2

    我正在尝试使用Ruby2.0.0和Rails4.0.0提供的API从imgur中提取图像。我已尝试按照Ruby2.0.0文档中列出的各种方式构建http请求,但均无济于事。代码如下:require'net/http'require'net/https'defimgurheaders={"Authorization"=>"Client-ID"+my_client_id}path="/3/gallery/image/#{img_id}.json"uri=URI("https://api.imgur.com"+path)request,data=Net::HTTP::Get.new(path

  10. python ffmpeg 使用 pyav 转换 一组图像 到 视频 - 2

    2022/8/4更新支持加入水印水印必须包含透明图像,并且水印图像大小要等于原图像的大小pythonconvert_image_to_video.py-f30-mwatermark.pngim_dirout.mkv2022/6/21更新让命令行参数更加易用新的命令行使用方法pythonconvert_image_to_video.py-f30im_dirout.mkvFFMPEG命令行转换一组JPG图像到视频时,是将这组图像视为MJPG流。我需要转换一组PNG图像到视频,FFMPEG就不认了。pyav内置了ffmpeg库,不需要系统带有ffmpeg工具因此我使用ffmpeg的python包装p

随机推荐