LVGL official document - 7.11.0-16-Overview-Images

An image can be a file or a variable that stores the bitmap data itself and other metadata.

Store images

Images can be stored in two places:

  • Variables in internal memory (RAM or ROM)
  • file

Variables

The image stored in the variable is mainly composed of LV with the following fields_ img_ dsc_ T structure composition:

  • header
    • cf color format
    • w width in pixels
    • h height in pixels
    • Always three bits of 0
    • Reserved reserved fields
  • Data pointer to the array where image data is stored
  • data_ The length of the size data field in bytes

These are usually saved in the project in the form of C source code. They are linked to the final executable like other constant data.

Files

In order to use files, you need to add drivers to LVGL. In short, a driver is a set of functions registered in LVGL to perform open, read, close and other functions. You can add a standard interface to the standard File system (FAT32 on SD card), or you can implement your own simple File system to read data from SPI Flash. In either case, a file driver is an abstraction that reads and writes from memory. Go to the File system section to view the details.

The image stored in the file is not linked to the final executable file and needs to be read into memory before drawing. Therefore, compared with variables, this method has no advantage in resource occupation. However, this method can replace resources without recompiling the program.

Color fomats

LVGL supports the following built-in color formats:

  • LV_IMG_CF_TRUE_COLOR stores RGB colors (regardless of the color depth configured in LVGL).
  • LV_IMG_CF_TRUE_COLOR_ALPHA in LV_ IMG_ CF_ TRUE_ Based on color, an alpha channel (transparency) of one byte is added to each pixel.
  • LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED in LV_ IMG_ CF_ TRUE_ Based on color, if the pixel color is Lv_ LV in conf.h_ COLOR_ Transp defines the color, and the pixel becomes transparent.
  • LV_IMG_CF_INDEXED_1/2/4/8BIT uses 2, 4, 16 or 256 color palettes and uses 1, 2, 4 or 8 bits to store pixels.
  • LV_IMG_CF_ALPHA_1/2/4/8BIT stores only Alpha channels with 1, 2, 4 or 8 bits. The color of pixels is style image. Color, the opacity is the value of the Alpha channel. The original image data contains only Alpha channels. This is useful for bitmap s that are similar to fonts (the entire image is monochrome and the color is variable).

LV_ IMG_ CF_ TRUE_ The bytes of the image in color format are stored in the following order:

  • For 32-bit color depth:
    • Byte 0: Blue
    • Byte 1: Green
    • Byte 2: Red
    • Byte 3: Alpha
  • For 16 bit color depth:
    • Byte 0: Green 3 lower bit, Blue 5 bit
    • Byte 1: Red 5 bit, Green 3 higher bit
    • Byte 2: Alpha byte (only with LV_IMG_CF_TRUE_COLOR_ALPHA)
  • For 8-bit color depth:
    • Byte 0: Red 3 bit, Green 3 bit, Blue 2 bit
    • Byte 2: Alpha byte (only with LV_IMG_CF_TRUE_COLOR_ALPHA)

Images can be stored in Raw format. Its color format is not a built-in format and requires an external image decoder to decode the image.

  • LV_IMG_CF_RAW represents a basic raw image (such as PNG or JPG image)
  • LV_IMG_CF_RAW_ALPHA indicates that the image has an alpha channel, and each pixel adds an alpha channel of one byte
  • LV_IMG_CF_RAW_CHROME_KEYED is similar to the LV above_ IMG_ CF_ TRUE_ COLOR_ CHROMA_ KEYED

Add and use images

There are two ways to add images to LVGL:

  • Use online converter
  • Create images manually

Online converter

The address of the online image converter is: https://lvgl.io/tools/imageconverter .

Follow these steps to add an image to LVGL using an online converter.

  1. First, you need an image file in BMP, PNG or JPG format.
  2. Name the image.
  3. Select a color format.
  4. Select the image type. Selecting binary will generate a bin file. This file needs to be stored separately and read using the file system. Selecting variable generates a standard C file that can be linked to the project.
  5. Click the Convert button. Once the conversion is completed, the browser will automatically download the result file.

The converted C array (variable) contains bitmap s of various color depths, but only and Lv_ LV in conf.h_ COLOR_ Depth matching color depth will actually link to the final executable.

For bin file mode, you need to specify the required color format:

  • RGB332 8-bit color depth
  • RGB565 16 bit color depth
  • RGB565 Swap 16 is color depth (swap byte order)
  • RGB888 32-bit color depth

Manually create an image

If you create an image at run time, you can create an image with LVGL to display it. For example:

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,          /*Set the color format*/
    .data = my_img_data,
};

If color is LV format_ IMG_ CF_ TRUE_ COLOR_ Alpha, data can be set_ Size 80 * 60 * LV_IMG_PX_SIZE_ALPHA_BYTE.

Use images

The easiest way to use images in LVGL is for lv_img Object.

lv_obj_t * icon = lv_img_create(lv_scr_act(), NULL);

/*From variable*/
lv_img_set_src(icon, &my_icon_dsc);

/*From file*/
lv_img_set_src(icon, "S:my_icon.bin");

If the image is converted with online tools, LV is used where the image needs to be used_ IMG_ Declare (my_icon_dsc) declaration.

Image decoder

As described in the Color fomats section, LVGL supports several built-in image formats. In most cases, these are sufficient. However, LVGL does not directly support general image formats such as PNG or JPG.

To handle non built-in image formats, you need to use an external library and attach it to LVGL through the Image Decoder interface.

The Image Decoder contains four callbacks:

  • info get some basic information about the image (width, height, color format).
  • open opens the image. Either store the decoded image or set it to NULL to indicate that the image can be read line by line.
  • read if open does not fully open the image, this function will give the decoded data (up to one line) from the specified position.
  • close closes the open image and releases the allocated resources.

Any number of image decoders can be added. When the image needs to be drawn, LVGL will try all registered decoders until it finds a decoder that can open the image (recognition format).

LV_IMG_CF_TRUE_COLOR_…, LV_IMG_INDEXED_… And LV_IMG_ALPHA_… This format is directly supported by the built-in decoder (especially all non raw formats).

Custom image formats

The easiest way to create a custom image is to use the online image conversion tool and set it to Raw, Raw with alpha, or Raw with chrome keyed format. It uses every byte of the uploaded binary file and writes the bitmap of the image. Then, an image decoder is used to convert the bitmap into a real, renderable bitmap.

Corresponding head The value of CF will be LV_IMG_CF_RAW,LV_IMG_CF_RAW_ALPHA or LV_IMG_CF_RAW_CHROME_KEYED. You need to select the correct format according to your needs: completely opaque, alpha channel or Chroma key.

After decoding, LVGL treats Raw format as true color. In other words, the image decoder must decode the Raw image into the true color format described in the Color formats chapter.

If you want to create a custom image, you need to use LV_IMG_CF_USER_ENCODED_0... 7 Color Format. However, LVGL can only draw images in true Color Format (or Raw format, but this will eventually be converted to true color), so LVGL does not recognize LV_IMG_CF_USER_ENCODED_0... 7 in these formats. Therefore, they need to convert to those known formats (as described in the Color Format chapter). You can first decode these images into non-true color Format (such as LV_IMG_INDEXED_4BITS), and then call the built-in decoding function to True Color.

If a custom encoding format is used, the color format (DSC - > header. CF) in the open function needs to be changed according to the new format.

Register an image decoder

The following is an example of processing PNG pictures in LVGL.

First, you need to create an image decoder and set up some functions to open / close PNG files. As follows:

/*Create a new decoder and register functions */
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);


/**
 * Get info about a PNG image
 * @param decoder pointer to the decoder where this function belongs
 * @param src can be file name or pointer to a C array
 * @param header store the info here
 * @return LV_RES_OK: no error; LV_RES_INV: can't get the info
 */
static lv_res_t decoder_info(lv_img_decoder_t * decoder, const void * src, lv_img_header_t * header)
{
  /*Check whether the type `src` is known by the decoder*/
  if(is_png(src) == false) return LV_RES_INV;

  /* Read the PNG header and find `width` and `height` */
  ...

  header->cf = LV_IMG_CF_RAW_ALPHA;
  header->w = width;
  header->h = height;
}

/**
 * Open a PNG image and return the decided image
 * @param decoder pointer to the decoder where this function belongs
 * @param dsc pointer to a descriptor which describes this decoding session
 * @return LV_RES_OK: no error; LV_RES_INV: can't get the info
 */
static lv_res_t decoder_open(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc)
{

  /*Check whether the type `src` is known by the decoder*/
  if(is_png(src) == false) return LV_RES_INV;

  /*Decode and store the image. If `dsc->img_data` is `NULL`, the `read_line` function will be called to get the image data line-by-line*/
  dsc->img_data = my_png_decoder(src);

  /*Change the color format if required. For PNG usually 'Raw' is fine*/
  dsc->header.cf = LV_IMG_CF_...

  /*Call a built in decoder function if required. It's not required if`my_png_decoder` opened the image in true color format.*/
  lv_res_t res = lv_img_decoder_built_in_open(decoder, dsc);

  return res;
}

/**
 * Decode `len` pixels starting from the given `x`, `y` coordinates and store them in `buf`.
 * Required only if the "open" function can't open the whole decoded pixel array. (dsc->img_data == NULL)
 * @param decoder pointer to the decoder the function associated with
 * @param dsc pointer to decoder descriptor
 * @param x start x coordinate
 * @param y start y coordinate
 * @param len number of pixels to decode
 * @param buf a buffer to store the decoded pixels
 * @return LV_RES_OK: ok; LV_RES_INV: failed
 */
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)
{
   /*With PNG it's usually not required*/

   /*Copy `len` pixels from `x` and `y` coordinates in True color format to `buf` */

}

/**
 * Free the allocated resources
 * @param decoder pointer to the decoder where this function belongs
 * @param dsc pointer to a descriptor which describes this decoding session
 */
static void decoder_close(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc)
{
  /*Free all allocated data*/

  /*Call the built-in close function if the built-in open/read_line was used*/
  lv_img_decoder_built_in_close(decoder, dsc);

}

in summary:

  1. In decoder_ In the info function, you need to collect some basic information of the image and store it in the header.
  2. In decoder_ In the open function, you need to open the image resource pointed to by DSC - > Src. Its type is stored in DSC - > Src_ type == LV_ IMG_ SRC_ File / variable. If this format / type is not supported by the decoder, LV is returned_ RES_ INV. If this image can be opened, the pointer to the decoded True Color image should be assigned to DSC - > img_ data. If you can recognize it but don't want to decode it for the time being (for example, you don't have enough memory), set DSC - > img_ Data = null, so read is called_ Line to get pixels.
  3. In decoder_ In the close function, release all allocated resources.
  4. decoder_ The read function is optional. Decoding the whole image at one time requires a lot of memory and calculation, but if only one line of the image is decoded instead of the whole file, memory and calculation time can be saved. In this case, you need to set the line read function and DSC - > img in the open function_ data = NULL.

Manually use an image decoder

When drawing Raw images, LVGL will automatically use the registered decoder, but this process can also be specified manually. Create a lv_img_decoder_dsc_t type variable to describe the decoded session and call lv_img_decoder_open() function.

lv_res_t res;
lv_img_decoder_dsc_t dsc;
res = lv_img_decoder_open(&dsc, &my_img_dsc, LV_COLOR_WHITE);

if(res == LV_RES_OK) {
  /*Do something with `dsc->img_data`*/
  lv_img_decoder_close(&dsc);
}

Image caching

Sometimes it takes time to open an image. Repeatedly decoding PNG images or loading images from slow external memory will be inefficient and have a poor user experience.

Therefore, LVGL caches the specified number of images. Caching means that some images will remain open, so LVGL can be downloaded from DSC - > img_ Read them quickly in data instead of decoding them again.

Of course, the cache will use more RAM (store decoded images), and LVGL will try to optimize this process (see later chapters), but you still need to evaluate whether this operation is beneficial to your platform. If you decode a small image from a very fast storage medium, the image cache may not be worth it.

Cache size

The number of cached entities can be Lv_ LV in conf.h_ IMG_ CACHE_ DEF_ Size definition. The default value is 1, so only recently used images remain open.

The size of the cache can be called at run time_ img_ cache_ set_ Size (entry_num).

Value of images

When the number of images used exceeds the cache limit, LVGL cannot cache all these images. At this time, LVGL will close the previously cached image to free up space.

To decide which image to close, LVGL measures the time it takes to open it. Cache entities that open slowly will be more valuable. Cache them as long as possible.

If you want to rewrite the LVGL measurement method, you can manually set the opening time in the decoder's open function: DSC - > time_ to_ open = time_ ms. If not, it is set by LVGL.

Each cached entity has a life value. Whenever an image is opened from the cache, the life value of the opened image will increase by time_to_open, which means it is more active, and the life value of other images will decrease, which means it is older.

If the cache is full, the entity with the lowest life value will be closed.

Memory usage

Note that cached images continue to use memory. For example, if three PNG images are cached, memory will be occupied while they remain open.

Therefore, the user needs to ensure that there is enough memory for caching even when the largest image is cached at the same time,

Clean the cache

If a PNG image has been loaded into lv_img_ dsc_ t my_ The variable PN is used in LV G_ On the IMG object. If the image has been cached and you change the PNG file behind it, you need to notify LVGL to cache the image again. Otherwise, LVGL will not know that the file behind it has changed, and it will still draw the old image.

To refresh, call Lv_ img_ cache_ invalidate_ src(&my_png). If the parameter is NULL, the entire cache will be emptied.

Keywords: C Linux Embedded system GUI LVGL

Added by dcro2 on Sun, 02 Jan 2022 19:45:32 +0200