图像¶
图像可以是一个文件,也可以是一个存储位图本身及一些元数据的变量。
存储图像¶
您可以将图像存储在两个地方:
作为变量存储在内部内存中(RAM 或 ROM)
作为文件存储
颜色格式¶
支持多种内置颜色格式:
LV_IMG_CF_TRUE_COLOR 简单地存储 RGB 颜色(以 LVGL 配置的颜色深度)。
LV_IMG_CF_TRUE_COLOR_ALPHA 类似于
LV_IMG_CF_TRUE_COLOR,但每个像素还添加了一个 alpha(透明度)字节。LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED 类似于
LV_IMG_CF_TRUE_COLOR,但如果像素具有LV_COLOR_TRANSP颜色(在 lv_conf.h 中设置),它将是透明的。LV_IMG_CF_INDEXED_1/2/4/8BIT 使用一个包含 2、4、16 或 256 种颜色的调色板,并以 1、2、4 或 8 位存储每个像素。
LV_IMG_CF_ALPHA_1/2/4/8BIT 仅存储 Alpha 值,使用 1、2、4 或 8 位。 像素采用
style.img_recolor的颜色和设置的不透明度。源图像必须是 alpha 通道。这对于类似字体的位图非常理想,其中整个图像是可以更改的一种颜色。
LV_IMG_CF_TRUE_COLOR 图像的字节按以下顺序存储。
对于 32 位颜色深度:
字节 0: 蓝色
字节 1: 绿色
字节 2: 红色
字节 3: Alpha
对于 16 位颜色深度:
字节 0: 绿色低 3 位,蓝色 5 位
字节 1: 红色 5 位,绿色高 3 位
字节 2: Alpha 字节(仅适用于 LV_IMG_CF_TRUE_COLOR_ALPHA)
对于 8 位颜色深度:
字节 0: 红色 3 位,绿色 3 位,蓝色 2 位
字节 2: Alpha 字节(仅适用于 LV_IMG_CF_TRUE_COLOR_ALPHA)
您可以以 Raw 格式存储图像,以指示它未使用内置颜色格式之一进行编码,需要使用外部图像解码器来解码图像。
LV_IMG_CF_RAW 表示基本的原始图像(例如 PNG 或 JPG 图像)。
LV_IMG_CF_RAW_ALPHA 表示图像具有 alpha,并为每个像素添加一个 alpha 字节。
LV_IMG_CF_RAW_CHROMA_KEYED 表示图像是色度键控的,如上文
LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED中所述。
添加和使用图像¶
您可以通过两种方式将图像添加到 LVGL:
使用在线转换器
手动创建图像
在线转换器¶
在线图像转换器可在此处找到:https://lvgl.io/tools/imageconverter
通过在线转换器将图像添加到 LVGL 非常简单。
首先需要选择一个 BMP、PNG 或 JPG 图像。
为图像命名,该名称将在 LVGL 中使用。
选择颜色格式。
选择所需的图像类型。选择二进制将生成一个
.bin文件,必须单独存储并使用文件支持读取。选择变量将生成一个标准的 C 文件,可以链接到您的项目中。点击 Convert 按钮。转换完成后,浏览器会自动下载生成的文件。
在生成的 C 数组(变量)中,所有颜色深度(1、8、16 或 32)的位图都包含在 C 文件中,但只有与 lv_conf.h 中的 LV_COLOR_DEPTH 匹配的颜色深度会实际链接到生成的可执行文件中。
对于二进制文件,您需要指定所需的颜色格式:
RGB332 用于 8 位颜色深度
RGB565 用于 16 位颜色深度
RGB565 Swap 用于 16 位颜色深度(交换两个字节)
RGB888 用于 32 位颜色深度
手动创建图像¶
如果您在运行时生成图像,可以制作一个图像变量以使用 LVGL 显示它。例如:
uint8_t my_img_data[] = {0x00, 0x01, 0x02, ...};
static lv_img_dsc_t my_img_dsc = {
.header.always_zero = 0,
.header.w = 80,
.header.h = 60,
.data_size = 80 * 60 * LV_COLOR_DEPTH / 8,
.header.cf = LV_IMG_CF_TRUE_COLOR, /*设置颜色格式*/
.data = my_img_data,
};
如果颜色格式是 LV_IMG_CF_TRUE_COLOR_ALPHA,您可以将 data_size 设置为 80 * 60 * LV_IMG_PX_SIZE_ALPHA_BYTE。
另一种(可能更简单的)在运行时创建和显示图像的选项是使用画布对象。
图像解码器¶
如颜色格式部分所述,LVGL 支持几种内置图像格式。在许多情况下,这些格式已经足够。然而,LVGL 不直接支持通用图像格式,如 PNG 或 JPG。
要处理非内置图像格式,您需要使用外部库并通过图像解码器接口将它们附加到 LVGL。
图像解码器由 4 个回调组成:
info 获取有关图像的一些基本信息(宽度、高度和颜色格式)。
open 打开图像:存储解码后的图像或将其设置为
NULL以指示图像可以逐行读取。read 如果 open 未完全打开图像,此函数应从给定位置提供一些解码数据(最多 1 行)。
close 关闭已打开的图像,释放分配的资源。
您可以添加任意数量的图像解码器。当需要绘制图像时,库将尝试所有注册的图像解码器,直到找到一个可以打开图像的解码器,即一个知道该格式的解码器。
LV_IMG_CF_TRUE_COLOR_...、LV_IMG_INDEXED_... 和 LV_IMG_ALPHA_... 格式(本质上,所有非 RAW 格式)由内置解码器理解。
自定义图像格式¶
创建自定义图像的最简单方法是使用在线图像转换器并选择 Raw、Raw with alpha 或 Raw with chroma-keyed 格式。它将获取您上传的二进制文件的每个字节,并将其写为图像“位图”。然后,您需要附加一个图像解码器来解析该位图并生成真实的、可渲染的位图。
header.cf 将分别为 LV_IMG_CF_RAW、LV_IMG_CF_RAW_ALPHA 或 LV_IMG_CF_RAW_CHROMA_KEYED。您应根据需要选择正确的格式:完全不透明的图像、使用 alpha 通道或使用色度键。
解码后,raw 格式被库视为真彩色。换句话说,图像解码器必须根据颜色格式部分中描述的格式将raw图像解码为真彩色。
如果要创建自定义图像,应使用 LV_IMG_CF_USER_ENCODED_0..7 颜色格式。然而,库只能以真彩色格式(或raw,但最终将是真彩色格式)绘制图像。
LV_IMG_CF_USER_ENCODED_... 格式不为库所知,因此应将其解码为颜色格式部分中已知的格式之一。
可以先将图像解码为非真彩色格式(例如:LV_IMG_INDEXED_4BITS),然后调用内置解码器函数将其转换为真彩色。
对于用户编码格式,打开函数中的颜色格式(dsc->header.cf)应根据新格式进行更改。
注册图像解码器¶
以下是使 LVGL 支持 PNG 图像的示例。
首先,您需要创建一个新的图像解码器并设置一些函数以打开/关闭 PNG 文件。它应如下所示:
/*创建一个新的解码器并注册函数*/
lv_img_decoder_t * dec = lv_img_decoder_create();
lv_img_decoder_set_info_cb(dec, decoder_info);
lv_img_decoder_set_open_cb(dec, decoder_open);
lv_img_decoder_set_close_cb(dec, decoder_close);
/**
* 获取有关 PNG 图像的信息
* @param decoder 此函数所属的解码器指针
* @param src 可以是文件名或指向 C 数组的指针
* @param header 在此处存储信息
* @return LV_RES_OK: 无错误; LV_RES_INV: 无法获取信息
*/
static lv_res_t decoder_info(lv_img_decoder_t * decoder, const void * src, lv_img_header_t * header)
{
/*检查解码器是否知道 `src` 的类型*/
if(is_png(src) == false) return LV_RES_INV;
/*读取 PNG 头并找到 `width` 和 `height` */
...
header->cf = LV_IMG_CF_RAW_ALPHA;
header->w = width;
header->h = height;
}
/**
* 打开 PNG 图像并返回解码后的图像
* @param decoder 此函数所属的解码器指针
* @param dsc 描述此解码会话的描述符指针
* @return LV_RES_OK: 无错误; LV_RES_INV: 无法获取信息
*/
static lv_res_t decoder_open(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc)
{
/*检查解码器是否知道 `src` 的类型*/
if(is_png(src) == false) return LV_RES_INV;
/*解码并存储图像。如果 `dsc->img_data` 为 `NULL`,将调用 `read_line` 函数逐行获取图像数据*/
dsc->img_data = my_png_decoder(src);
/*如果需要,改变颜色格式。对于 PNG,通常 'Raw' 就可以了*/
dsc->header.cf = LV_IMG_CF_...
/*如果需要,调用内置解码器函数。如果 `my_png_decoder` 以真彩色格式打开图像,则不需要。*/
lv_res_t res = lv_img_decoder_built_in_open(decoder, dsc);
return res;
}
/**
* 从给定的 `x`、`y` 坐标开始解码 `len` 像素,并将它们存储在 `buf` 中。
* 仅当“open”函数无法打开整个解码的像素数组时需要。(dsc->img_data == NULL)
* @param decoder 与函数关联的解码器指针
* @param dsc 解码器描述符指针
* @param x 起始 x 坐标
* @param y 起始 y 坐标
* @param len 要解码的像素数
* @param buf 存储解码像素的缓冲区
* @return LV_RES_OK: 成功; LV_RES_INV: 失败
*/
lv_res_t decoder_built_in_read_line(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc, lv_coord_t x,
lv_coord_t y, lv_coord_t len, uint8_t * buf)
{
/*对于 PNG 通常不需要*/
/*将 `len` 像素从 `x` 和 `y` 坐标以真彩色格式复制到 `buf` */
}
/**
* 释放分配的资源
* @param decoder 此函数所属的解码器指针
* @param dsc 描述此解码会话的描述符指针
*/
static void decoder_close(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc)
{
/*释放所有分配的数据*/
/*如果使用了内置的 open/read_line,调用内置的 close 函数*/
lv_img_decoder_built_in_close(decoder, dsc);
}
总结如下:
在
decoder_info中,您应收集有关图像的一些基本信息并将其存储在header中。在
decoder_open中,您应尝试打开由dsc->src指向的图像源。其类型已在dsc->src_type == LV_IMG_SRC_FILE/VARIABLE中。 如果解码器不支持此格式/类型,则返回LV_RES_INV。 但是,如果您可以打开图像,则应在dsc->img_data中设置指向解码后的真彩色图像的指针。 如果已知格式,但您不想解码整个图像(例如:没有足够的内存),请在打开函数中设置dsc->img_data = NULL并使用read_line获取像素数据。在
decoder_close中,您应释放所有分配的资源。decoder_read是可选的。解码整个图像需要额外的内存和一些计算开销。 但是,它可以在不解码整个图像的情况下解码图像的一行,您可以节省内存和时间。 要指示应使用行读取函数,请在打开函数中设置dsc->img_data = NULL。
手动使用图像解码器¶
如果您尝试绘制原始图像(即使用 lv_img 对象),LVGL 将自动使用注册的图像解码器,但您也可以手动使用它们。创建一个 lv_img_decoder_dsc_t 变量来描述解码会话并调用 lv_img_decoder_open()。
color 参数仅用于 LV_IMG_CF_ALPHA_1/2/4/8BIT 图像,以指示图像的颜色。
frame_id 可用于打开的图像是动画时。
lv_res_t res;
lv_img_decoder_dsc_t dsc;
res = lv_img_decoder_open(&dsc, &my_img_dsc, color, frame_id);
if(res == LV_RES_OK) {
/*对 `dsc->img_data` 执行操作*/
lv_img_decoder_close(&dsc);
}
图像缓存¶
有时打开图像需要花费大量时间。 连续解码 PNG 图像或从较慢的外部存储器加载图像会效率低下并损害用户体验。
因此,LVGL 缓存了一定数量的图像。缓存意味着某些图像将保持打开状态,因此 LVGL 可以快速从 dsc->img_data 访问它们,而无需再次解码。
当然,缓存图像会占用更多的 RAM 来存储解码后的图像。LVGL 尽可能优化此过程(见下文),但您仍需要评估这对您的平台是否有益。如果您有一个从相对较快的存储介质解码小图像的深度嵌入式目标,图像缓存可能不值得。
缓存大小¶
缓存条目的数量可以通过 lv_conf.h 中的 LV_IMG_CACHE_DEF_SIZE 定义。默认值为 1,因此只有最近使用的图像将保持打开状态。
可以使用 lv_img_cache_set_size(entry_num) 在运行时更改缓存的大小。
图像的价值¶
当您使用的图像多于缓存条目时,LVGL 无法缓存所有图像。相反,库将关闭一个缓存的图像以释放空间。
为了决定关闭哪个图像,LVGL 使用之前对打开图像所需时间的测量。保存较慢打开图像的缓存条目被认为更有价值,并尽可能长时间保留在缓存中。
如果您想或需要覆盖 LVGL 的测量值,可以在解码器打开函数中手动设置打开时间值 dsc->time_to_open = time_ms,以给出更高或更低的值。(保持不变以让 LVGL 控制它。)
每个缓存条目都有一个*“生命”值。每次通过缓存打开图像时,所有条目的生命值都会减少,使它们变得更旧。 当使用缓存的图像时,其生命值会增加打开时间*值,使其更有活力。
如果缓存中没有更多空间,将关闭生命值最低的条目。
清理缓存¶
假设您已将 PNG 图像加载到 lv_img_dsc_t my_png 变量中,并在 lv_img 对象中使用它。如果图像已缓存,然后您更改了底层 PNG 文件,则需要通知 LVGL 再次缓存图像。否则,没有简单的方法可以检测到底层文件已更改,LVGL 仍将从缓存中绘制旧图像。
为此,请使用 lv_img_cache_invalidate_src(&my_png)。如果将 NULL 作为参数传递,则整个缓存将被清理。
API¶
图像缓冲区¶
Typedefs
-
typedef uint8_t
lv_img_cf_t¶
Enums
-
Values:
-
enumerator
LV_IMG_CF_UNKNOWN¶
-
enumerator
LV_IMG_CF_RAW¶ Contains the file as it is. Needs custom decoder function
-
enumerator
LV_IMG_CF_RAW_ALPHA¶ Contains the file as it is. The image has alpha. Needs custom decoder function
-
enumerator
LV_IMG_CF_RAW_CHROMA_KEYED¶ Contains the file as it is. The image is chroma keyed. Needs custom decoder function
-
enumerator
LV_IMG_CF_TRUE_COLOR¶ Color format and depth should match with LV_COLOR settings
-
enumerator
LV_IMG_CF_TRUE_COLOR_ALPHA¶ Same as
LV_IMG_CF_TRUE_COLORbut every pixel has an alpha byte
-
enumerator
LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED¶ Same as
LV_IMG_CF_TRUE_COLORbut LV_COLOR_TRANSP pixels will be transparent
-
enumerator
LV_IMG_CF_INDEXED_1BIT¶ Can have 2 different colors in a palette (can't be chroma keyed)
-
enumerator
LV_IMG_CF_INDEXED_2BIT¶ Can have 4 different colors in a palette (can't be chroma keyed)
-
enumerator
LV_IMG_CF_INDEXED_4BIT¶ Can have 16 different colors in a palette (can't be chroma keyed)
-
enumerator
LV_IMG_CF_INDEXED_8BIT¶ Can have 256 different colors in a palette (can't be chroma keyed)
-
enumerator
LV_IMG_CF_ALPHA_1BIT¶ Can have one color and it can be drawn or not
-
enumerator
LV_IMG_CF_ALPHA_2BIT¶ Can have one color but 4 different alpha value
-
enumerator
LV_IMG_CF_ALPHA_4BIT¶ Can have one color but 16 different alpha value
-
enumerator
LV_IMG_CF_ALPHA_8BIT¶ Can have one color but 256 different alpha value
-
enumerator
LV_IMG_CF_RGB888¶
-
enumerator
LV_IMG_CF_RGBA8888¶
-
enumerator
LV_IMG_CF_RGBX8888¶
-
enumerator
LV_IMG_CF_RGB565¶
-
enumerator
LV_IMG_CF_RGBA5658¶
-
enumerator
LV_IMG_CF_RGB565A8¶
-
enumerator
LV_IMG_CF_RESERVED_15¶ Reserved for further use.
-
enumerator
LV_IMG_CF_RESERVED_16¶ Reserved for further use.
-
enumerator
LV_IMG_CF_RESERVED_17¶ Reserved for further use.
-
enumerator
LV_IMG_CF_RESERVED_18¶ Reserved for further use.
-
enumerator
LV_IMG_CF_RESERVED_19¶ Reserved for further use.
-
enumerator
LV_IMG_CF_RESERVED_20¶ Reserved for further use.
-
enumerator
LV_IMG_CF_RESERVED_21¶ Reserved for further use.
-
enumerator
LV_IMG_CF_RESERVED_22¶ Reserved for further use.
-
enumerator
LV_IMG_CF_RESERVED_23¶ Reserved for further use.
-
enumerator
LV_IMG_CF_USER_ENCODED_0¶ User holder encoding format.
-
enumerator
LV_IMG_CF_USER_ENCODED_1¶ User holder encoding format.
-
enumerator
LV_IMG_CF_USER_ENCODED_2¶ User holder encoding format.
-
enumerator
LV_IMG_CF_USER_ENCODED_3¶ User holder encoding format.
-
enumerator
LV_IMG_CF_USER_ENCODED_4¶ User holder encoding format.
-
enumerator
LV_IMG_CF_USER_ENCODED_5¶ User holder encoding format.
-
enumerator
LV_IMG_CF_USER_ENCODED_6¶ User holder encoding format.
-
enumerator
LV_IMG_CF_USER_ENCODED_7¶ User holder encoding format.
-
enumerator
Functions
-
lv_img_dsc_t *
lv_img_buf_alloc(lv_coord_t w, lv_coord_t h, lv_img_cf_t cf)¶ Allocate an image buffer in RAM
- Parameters
w -- width of image
h -- height of image
cf -- a color format (
LV_IMG_CF_...)
- Returns
an allocated image, or NULL on failure
-
lv_color_t
lv_img_buf_get_px_color(lv_img_dsc_t *dsc, lv_coord_t x, lv_coord_t y, lv_color_t color)¶ Get the color of an image's pixel
- Parameters
dsc -- an image descriptor
x -- x coordinate of the point to get
y -- x coordinate of the point to get
color -- the color of the image. In case of
LV_IMG_CF_ALPHA_1/2/4/8this color is used. Not used in other cases.safe -- true: check out of bounds
- Returns
color of the point
-
lv_opa_t
lv_img_buf_get_px_alpha(lv_img_dsc_t *dsc, lv_coord_t x, lv_coord_t y)¶ Get the alpha value of an image's pixel
- Parameters
dsc -- pointer to an image descriptor
x -- x coordinate of the point to set
y -- x coordinate of the point to set
safe -- true: check out of bounds
- Returns
alpha value of the point
-
void
lv_img_buf_set_px_color(lv_img_dsc_t *dsc, lv_coord_t x, lv_coord_t y, lv_color_t c)¶ Set the color of a pixel of an image. The alpha channel won't be affected.
- Parameters
dsc -- pointer to an image descriptor
x -- x coordinate of the point to set
y -- x coordinate of the point to set
c -- color of the point
safe -- true: check out of bounds
-
void
lv_img_buf_set_px_alpha(lv_img_dsc_t *dsc, lv_coord_t x, lv_coord_t y, lv_opa_t opa)¶ Set the alpha value of a pixel of an image. The color won't be affected
- Parameters
dsc -- pointer to an image descriptor
x -- x coordinate of the point to set
y -- x coordinate of the point to set
opa -- the desired opacity
safe -- true: check out of bounds
-
void
lv_img_buf_set_palette(lv_img_dsc_t *dsc, uint8_t id, lv_color_t c)¶ Set the palette color of an indexed image. Valid only for
LV_IMG_CF_INDEXED1/2/4/8- Parameters
dsc -- pointer to an image descriptor
id -- the palette color to set:
for
LV_IMG_CF_INDEXED1: 0..1for
LV_IMG_CF_INDEXED2: 0..3for
LV_IMG_CF_INDEXED4: 0..15for
LV_IMG_CF_INDEXED8: 0..255
c -- the color to set
-
void
lv_img_buf_free(lv_img_dsc_t *dsc)¶ Free an allocated image buffer
- Parameters
dsc -- image buffer to free
-
uint32_t
lv_img_buf_get_img_size(lv_coord_t w, lv_coord_t h, lv_img_cf_t cf)¶ Get the memory consumption of a raw bitmap, given color format and dimensions.
- Parameters
w -- width
h -- height
cf -- color format
- Returns
size in bytes
-
void
_lv_img_buf_get_transformed_area(lv_area_t *res, lv_coord_t w, lv_coord_t h, int16_t angle, uint16_t zoom, const lv_point_t *pivot)¶ Get the area of a rectangle if its rotated and scaled
- Parameters
res -- store the coordinates here
w -- width of the rectangle to transform
h -- height of the rectangle to transform
angle -- angle of rotation
zoom -- zoom, (256 no zoom)
pivot -- x,y pivot coordinates of rotation
-
struct
lv_img_header_t¶ - #include <lv_img_buf.h>
The first 8 bit is very important to distinguish the different source types. For more info see
lv_img_get_src_type()in lv_img.c On big endian systems the order is reversed so cf and always_zero must be at the end of the struct.
-
struct
lv_img_dsc_t¶ - #include <lv_img_buf.h>
Image header it is compatible with the result from image converter utility
Public Members
-
lv_img_header_t
header¶ A header describing the basics of the image
-
uint32_t
data_size¶ Size of the image in bytes
-
const uint8_t *
data¶ Pointer to the data of the image
-
lv_img_header_t