docs(images): remove outdated information and reorganize image docs (#9221)

Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
This commit is contained in:
Victor Wheeler
2025-11-27 01:17:32 -07:00
committed by GitHub
parent c6585cab0f
commit 2a6ac68678
24 changed files with 1080 additions and 710 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

@@ -145,7 +145,7 @@ are needed to build packages or to run the build system itself. It may contain
compilers, build tools, and libraries that are required to support the build
process for the target.
.. _images:
.. _rpi4_images:
images
======
@@ -181,7 +181,7 @@ If it is mounted on /dev/sda, run the following command
sudo dd if=images/sdcard.img of=/dev/sda
As mentioned in :ref:`images`, the output image is in ``images`` and named
As mentioned in :ref:`rpi4_images`, the output image is in ``images`` and named
``sdcard.img``.
Connect an Ethernet cable to the RPi4 and ensure the laptop and the RPi4 are on
+9 -12
View File
@@ -1,3 +1,4 @@
.. include:: /include/external_links.txt
.. _bmp:
===========
@@ -6,18 +7,16 @@ BMP Decoder
This BMP Decoder utility allows you to use images from .BMP files in LVGL.
Library source: https://github.com/caj-johnson/bmp-decoder
Instead of loading the whole image at once, BMP pixels are read on demand,
so using BMP images requires very little RAM.
If enabled in ``lv_conf.h`` by setting :c:macro:`LV_USE_BMP` to ``1``, LVGL will
register a new image decoder automatically so BMP files can be directly used as image
sources. Example:
register the BMP image decoder automatically so BMP files can be directly used as
image sources. Example:
.. code-block:: c
lv_image_set_src(my_img, "S:path/to/picture.bmp");
lv_image_set_src(my_img, "S:path/to/picture.bmp");
Note that, a :ref:`file_system` driver needs to registered to open images from
files. Follow the instructions in :ref:`file_system`.
@@ -29,15 +28,13 @@ files. Follow the instructions in :ref:`file_system`.
Limitations
***********
- Only BMP files are supported. BMP images as C arrays
(:cpp:struct:`lv_image_dsc_t`) are not. This is because there is no practical
differences between how the BMP files and LVGL's image format stores
the image data.
- BMP files can be loaded only from .BMP files. If you want to store them in
flash it's better to convert them to a C array with `LVGL's image converter <https://lvgl.io/tools/imageconverter>`__.
- Only uncompressed BMP files are supported. BMP images as C arrays
(:cpp:type:`lv_image_dsc_t`) are not supported. This is because there is no
practical difference between how uncompressed BMP files and LVGL's image format
store the image data.
- The BMP file's color format needs to match the configured :c:macro:`LV_COLOR_DEPTH`
of the display on which it will be rendered. You can use GIMP to save the image
in the required format. Both RGB888 and ARGB888 works with
in the required format. Both RGB888 and ARGB888 work with
:c:macro:`LV_COLOR_DEPTH` ``32``
- Color palettes are not supported.
- Because the whole image is not loaded, it cannot be zoomed or rotated.
@@ -14,6 +14,7 @@ Image Support
libpng
lodepng
libwebp
lz4
rle
rlottie
svg
@@ -56,7 +56,7 @@ It should be noted that each image decoded needs to consume:
image width |times| image height |times| 3
bytes of RAM, and it needs to be combined with the :ref:`overview_image_caching`
bytes of RAM, and it needs to be combined with the :ref:`image caching`
feature to ensure that the memory usage is within a reasonable range.
@@ -48,7 +48,7 @@ It should be noted that each image of this decoder needs to consume
width |times| height |times| 4
bytes of RAM, and it needs to be combined with the :ref:`overview_image_caching` feature to
bytes of RAM, and it needs to be combined with the :ref:`image caching` feature to
ensure that the memory usage is within a reasonable range. The decoded image is
stored in RGBA pixel format.
@@ -53,7 +53,7 @@ Memory requirements for WebP images:
- Lossy WebP: width × height × 4 bytes (ARGB8888 format)
- Lossless WebP: width × height × 4 bytes (ARGB8888 format)
For optimal memory usage, combine with LVGL's :ref:`overview_image_caching` feature.
For optimal memory usage, combine with LVGL's :ref:`image caching` feature.
.. _libwebp_example:
@@ -28,7 +28,7 @@ bytes of RAM is required from the LVGL heap. The decoded image is stored in RGB
pixel format.
Since it might take significant time to decode PNG images LVGL's
:ref:`overview_image_caching` feature can be useful.
:ref:`image caching` feature can be useful.
@@ -0,0 +1,74 @@
.. include:: /include/substitutions.txt
.. include:: /include/external_links.txt
.. include:: /include/custom_roles.txt
.. _lz4:
=================
LZ4 Decompression
=================
LVGL provides the extremely fast LZ4 decompression method found in the `LZ4
repository <https://github.com/lz4/lz4>`__ on GitHub. It can be used to reduce
binary image size. The LZ4 compression is a lossless compression method.
The LVGL's built-in binary image decoder supports LZ4-compressed images.
The decoder supports both variable and file as image sources. The original
binary data is directly decoded to RAM.
Which Library
*************
If ``LV_USE_LZ4_INTERNAL`` is enabled in ``lv_conf.h``, LVGL's internal copy of the
LZ4 decompression algorithm is used (``./src/libs/lz4/lz4.c``).
If ``LV_USE_LZ4_EXTERNAL`` is enabled, the LVGL project is assumed to be compiled and
linked with an external LZ4 library that provides the :cpp:func:`LZ4_decompress_safe`
function.
One of them must be enabled to use LZ4 decompression.
Benefits
********
LZ4 is best at compressing data where compression and decompression speed is a
priority over compression ratio, making it ideal for applications like real-time data
processing.
.. image:: /_static/images/lz4-compress-statistics.png
:alt: LZ4 compress statistics from lz4.org
:align: center
.. _lz4_usage:
Usage
*****
To use the LZ4 Decoder, enable it in ``lv_conf.h`` configuration file by setting
either ``LV_USE_LZ4_INTERNAL`` or ``LV_USE_LZ4_EXTERNAL`` to ``1``. LZ4 images can
then be used in the same way as other images.
.. code-block:: c
lv_image_set_src(img, "path/to/cogwheel.bin");
Generating LZ4 Compressed Binary Images
***************************************
An LZ4 image binary can be directly generated from another image using script
``lvgl/scripts/LVGLImage.py``.
.. code-block:: bash
./scripts/LVGLImage.py --ofmt BIN --cf I8 --compress LZ4 cogwheel.png
This will decompress ``cogwheel.png``, and then re-compress it using LZ4 and write
the output to ``./output/cogwheel.bin``.
@@ -7,7 +7,7 @@ Image font
Draw image in **label** or **span** obj with :cpp:type:`lv_imgfont`. This is often used to
display Unicode emoji icons in text.
Supported image formats: determined by enabled LVGL :ref:`image decoders <overview_image_decoder>`.
Supported image formats: determined by enabled LVGL :ref:`image decoders <image_decoders>`.
@@ -150,7 +150,10 @@ Using these symbols is very simple:
lv_label_set_text(label, LV_SYMBOL_OK "Apply"); /*Concatenate with a string*/
To add a new symbol in a custom font:
.. _font_adding_a_custom_symbol:
Adding a Custom Symbol
----------------------
1. Search for a symbol on https://fontawesome.com. For example the
`USB symbol <https://fontawesome.com/icons/usb?style=brands>`__. Copy its
@@ -165,7 +168,9 @@ To add a new symbol in a custom font:
Make sure to compile the ``.c`` file of your font.
6. Declare the font using :cpp:expr:`LV_FONT_DECLARE(my_font_name)`.
**Using the symbol**
Using Your Custom Symbol
------------------------
1. Convert the Unicode value to UTF8, for example on
`this site <http://www.ltg.ed.ac.uk/~richard/utf-8.cgi?input=f287&mode=hex>`__.
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,122 @@
.. include:: /include/external_links.txt
.. _adding images to your project:
=============================
Adding Images to Your Project
=============================
You can add images to LVGL in three ways:
- using the :ref:`online converter <images_online_converter>`
- using the :ref:`offline converter <images_offline_converter>`
- :ref:`manually create images <images_manually_creating>`
.. _images_online_converter:
Online Converter
****************
Adding an image to LVGL via the `LVGL Online Image Converter`_ is easy:
1. Click [Select image file(s)] and select a BMP, PNG, JPG, WEBP or SVG image.
Also supported: GIF, SVGZ, TIF, TIFF, AI, DRW, PCT, PSP, XCF, PSD, RAW and HEIC.
2. Select the :ref:`Color format <images_color_formats>`. Currently supported:
- RGB565
- RGB565A8
- RGB888
- XRGB8888
- ARGB8888
If you need another color format, use the :ref:`offline converter
<images_offline_converter>`.
.. note:: BMP images are currently supported in file form only.
See :ref:`images_bmp_files` below.
3. Click the [Convert] button. This will convert the file and open a "Save As..."
dialog box. The default filename will be the filename of the selected image file
with a ``.c`` extension.
In the case of binary (.bin) files, you need to specify the color format you want:
- RGB332 for 8-bit color depth
- RGB565 for 16-bit color depth
- RGB565 Swap for 16-bit color depth (two bytes are swapped)
- RGB888 for 24-bit color depth (8-bit channels without an alpha channel)
.. _images_offline_converter:
Offline Converter
*****************
The offline converter is contained in ``./scripts/LVGLImage.py``. Run it with no
arguments to see its command-line options.
.. _images_bmp_files:
BMP and WEBP Files
******************
Currently, support for BMP and WEBP images is limited to using them as files on an
external file system. For a BMP file, follow the instructions in :ref:`bmp`. For
WEBP files, follow the instructions in :ref:`libwebp`.
.. _images_bin_files:
BIN Files
*********
Another way you can add an image to your project is by using the
:ref:`images_offline_converter` to create a ``.bin`` file. Typically, you would do
this with a target color format matching the Display the image is going to be sent
to. Optionally, you can use a command-line argument to cause the image contents to
be compressed using RLE or LZ4 compression as well. Of course, the decompression
logic must be part of your project by enabling appropriate ``LV_USE_RLE``,
``LV_USE_LZ4_INTERNAL``, and/or ``LV_USE_LZ4_EXTERNAL`` macros in your ``lv_conf.h``
file.
This enables the drawing logic to have a very low RAM footprint because the pixels
are extracted directly from the file similar to how they are extracted from BMP files.
See :ref:`rle` and :ref:`lz4`
.. _images_manually_creating:
Manually Creating an Image
**************************
If you are generating an image at run-time, you can craft an image
variable to display it using LVGL. For example:
.. code-block:: c
uint8_t my_img_data[] = {0x00, 0x01, 0x02, ...};
static lv_image_dsc_t my_img_dsc = {
.header.magic = LV_IMAGE_HEADER_MAGIC,
.header.cf = LV_COLOR_FORMAT_RGB565, /* Set color format */
.header.flags = 0,
.header.w = 80,
.header.h = 60,
.header.stride = 80 * LV_COLOR_DEPTH / 8,
.header.reserved_2 = 0,
.data_size = 80 * 60 * LV_COLOR_DEPTH / 8,
.data = my_img_data,
};
Another (possibly simpler) option to create and display an image at
run-time is to use the :ref:`Canvas <lv_canvas>` Widget.
@@ -0,0 +1,73 @@
.. _image caching:
=============
Image Caching
=============
Sometimes it takes a lot of time to open an image. Repeatedly decoding
a PNG/JPEG image or loading images from a slow external memory would be
inefficient and detrimental to the user experience.
Therefore, LVGL caches image data. Caching means some
images will be left open, hence LVGL can quickly access them from
``dsc->decoded`` instead of needing to decode them again.
Of course, caching images is resource intensive as it uses more RAM to
store the decoded image. LVGL tries to optimize the process as much as
possible (see below), but you will still need to evaluate if this would
be beneficial for your platform or not. Image caching may not be worth
it if you have a deeply embedded target which decodes small images from
a relatively fast storage medium.
Cache Size
**********
The size of cache (in bytes) can be defined with
:c:macro:`LV_CACHE_DEF_SIZE` in *lv_conf.h*. The default value is 0, so
no image is cached.
The size of cache can be changed at run-time with
:cpp:expr:`lv_cache_set_max_size(size_t size)`,
and retrieved with :cpp:expr:`lv_cache_get_max_size()`.
Value of Images
***************
When you use more images than available cache size, LVGL can't cache all the
images. Instead, the library will close one of the cached images to free space.
To decide which image to close, LVGL uses an LRU (least-recently-used) algorithm.
Most-recently-used images are prioritized to keep in the cache as long as possible,
while the oldest (images not used recently) are disposed of to make room for new
cache content.
Memory Usage
************
Note that a cached image might continuously consume memory. For example,
if three PNG images are cached, they will consume memory while they are
open.
Therefore, it's the user's responsibility to be sure there is enough RAM
to cache even the largest images at the same time.
Invalidating Cache Entries
**************************
Let's say you have loaded a PNG image into a :cpp:struct:`lv_image_dsc_t` ``my_png``
variable and use it in an ``lv_image`` Widget. If the image is already
cached and you then change the underlying PNG file, you need to notify
LVGL to cache the image again. Otherwise, there is no easy way of
detecting that the underlying file has changed and LVGL will still draw the
old image from cache. To do this, use :cpp:expr:`lv_image_cache_drop(&my_png)`.
To invalidate all cached images: :cpp:expr:`lv_image_cache_drop(NULL)`.
@@ -0,0 +1,202 @@
.. include:: /include/external_links.txt
.. _images_color_formats:
=============
Color Formats
=============
Built-in Input Color Formats
****************************
The following image pixel color formats have built-in decoding support:
.. note::
All of the below format names are used in code by prefixing them with
``LV_COLOR_FORMAT_`` (e.g. :cpp:enumerator:`LV_COLOR_FORMAT_RGB565`).
.. container:: tighter-table-3
+------------------------+-----+------------+-----------------------------------------------------------------+
| Format | BPP | Supported | Description |
| | | by offline | |
| | | converter | |
+========================+=====+============+=================================================================+
| I1 [1]_ | 1 | Yes | Indexed with 2-color palette |
+------------------------+-----+------------+-----------------------------------------------------------------+
| I2 [1]_ | 2 | Yes | Indexed with 4-color palette |
+------------------------+-----+------------+-----------------------------------------------------------------+
| I4 [1]_ | 4 | Yes | Indexed with 16-color palette |
+------------------------+-----+------------+-----------------------------------------------------------------+
| I8 [1]_ | 8 | Yes | Indexed with 256-color palette |
+------------------------+-----+------------+-----------------------------------------------------------------+
| A8 | 8 | Yes | Pixels express alpha only (used where color is supplied |
| | | | elsewhere as with fonts) |
+------------------------+-----+------------+-----------------------------------------------------------------+
| L8 | 8 | Yes | Luminance: pixels express gray-scale value in range [0-255] |
+------------------------+-----+------------+-----------------------------------------------------------------+
| AL88 | 16 | Not yet | L8 with an alpha byte |
+------------------------+-----+------------+-----------------------------------------------------------------+
| RGB565 | 16 | Yes | Standard RGB565 (little-endian format) |
+------------------------+-----+------------+-----------------------------------------------------------------+
| ARGB8565 | 24 | Yes | RGB565 preceded by alpha byte |
+------------------------+-----+------------+-----------------------------------------------------------------+
| RGB565A8 | 24 | Yes | RGB565 + trailing alpha byte |
+------------------------+-----+------------+-----------------------------------------------------------------+
| RGB565_SWAPPED | 16 | Yes | RGB565 big-endian format |
+------------------------+-----+------------+-----------------------------------------------------------------+
| RGB888 | 24 | Yes | Standard RGB with 8 bits per color channel |
+------------------------+-----+------------+-----------------------------------------------------------------+
| ARGB8888 | 32 | Yes | Standard ARGB with 8 bits per color channel |
+------------------------+-----+------------+-----------------------------------------------------------------+
| XRGB8888 | 32 | Yes | Like ARGB but alpha bytes are ignored |
+------------------------+-----+------------+-----------------------------------------------------------------+
| ARGB8888_PREMULTIPLIED | 32 | Yes | ARGB8888 with RGB pre-darkened according to alpha channel value |
+------------------------+-----+------------+-----------------------------------------------------------------+
| RAW [2]_ | ? | n/a | See :ref:`custom_image_formats` |
+------------------------+-----+------------+-----------------------------------------------------------------+
| RAW_ALPHA [2]_ | ? | n/a | See :ref:`custom_image_formats` |
+------------------------+-----+------------+-----------------------------------------------------------------+
.. [1] I1, I2, I4 and I8 indexed formats require ``LV_DRAW_SW_SUPPORT_ARGB8888`` to
be configured to ``1`` in your ``lv_conf.h`` file. Palette colors are
always ``ARGB8888``.
.. [2] Custom formats can be supported by specifying one of the RAW color formats and
using an external :ref:`image decoder <image_decoders>` to decode it.
See :ref:`image_decoders`.
Built-In Input and Output Formats
*********************************
+-------------------------+----------------+------------+-------------+
| Format | BPP | Supported | Description |
| | | by offline | |
| | | converter | |
+=========================+================+============+=============+
| NATIVE [3]_ | LV_COLOR_DEPTH | No | See below |
+-------------------------+----------------+------------+-------------+
| NATIVE_WITH_ALPHA [3]_ | LV_COLOR_DEPTH | No | See below |
+-------------------------+----------------+------------+-------------+
.. [3]
What they mean (from ``lv_color.h``):
.. code-block::
#if LV_COLOR_DEPTH == 1
LV_COLOR_FORMAT_NATIVE = LV_COLOR_FORMAT_I1,
LV_COLOR_FORMAT_NATIVE_WITH_ALPHA = LV_COLOR_FORMAT_I1,
#elif LV_COLOR_DEPTH == 8
LV_COLOR_FORMAT_NATIVE = LV_COLOR_FORMAT_L8,
LV_COLOR_FORMAT_NATIVE_WITH_ALPHA = LV_COLOR_FORMAT_AL88,
#elif LV_COLOR_DEPTH == 16
LV_COLOR_FORMAT_NATIVE = LV_COLOR_FORMAT_RGB565,
LV_COLOR_FORMAT_NATIVE_WITH_ALPHA = LV_COLOR_FORMAT_RGB565A8,
#elif LV_COLOR_DEPTH == 24
LV_COLOR_FORMAT_NATIVE = LV_COLOR_FORMAT_RGB888,
LV_COLOR_FORMAT_NATIVE_WITH_ALPHA = LV_COLOR_FORMAT_ARGB8888,
#elif LV_COLOR_DEPTH == 32
LV_COLOR_FORMAT_NATIVE = LV_COLOR_FORMAT_XRGB8888,
LV_COLOR_FORMAT_NATIVE_WITH_ALPHA = LV_COLOR_FORMAT_ARGB8888,
#else
#error "LV_COLOR_DEPTH should be 1, 8, 16, 24 or 32"
#endif
GPU Input Formats
*****************
The following color formats are supported by certain GPUs and are retained as
color-format enumeration values that can be used when a GPU is going to be doing the
drawing.
Alpha-Only and Special ARGB Formats
-----------------------------------
+----------+-----+------------+---------------------------------------+
| Format | BPP | Supported | Description |
| | | by offline | |
| | | converter | |
+==========+=====+============+=======================================+
| A1 | 1 | No | Like A8 but only 255 alpha or 0 alpha |
+----------+-----+------------+---------------------------------------+
| A2 | 2 | No | Like A8 but 4 alpha values |
+----------+-----+------------+---------------------------------------+
| A4 | 4 | No | Like A8 but 16 alpha values |
+----------+-----+------------+---------------------------------------+
| ARGB2222 | 8 | No | ARGB2222 |
+----------+-----+------------+---------------------------------------+
| ARGB1555 | 16 | No | ARGB1555 |
+----------+-----+------------+---------------------------------------+
| ARGB4444 | 16 | No | ARGB4444 |
+----------+-----+------------+---------------------------------------+
YUV Planar Formats
------------------
Reference: https://wiki.videolan.org/YUV/
.. container:: tighter-table-3
+--------+-----+------------+---------------------------------------------------+
| Format | BPP | Supported | Description |
| | | by offline | |
| | | converter | |
+========+=====+============+===================================================+
| I420 | | No | YUV420 planar (3 plane) |
+--------+-----+------------+---------------------------------------------------+
| I422 | | No | YUV422 planar (3 plane) |
+--------+-----+------------+---------------------------------------------------+
| I444 | | No | YUV444 planar (3 plane) |
+--------+-----+------------+---------------------------------------------------+
| I400 | | No | YUV400 no chroma channel |
+--------+-----+------------+---------------------------------------------------+
| NV21 | | No | YUV420 planar (2 plane), UV plane in 'V, U, V, U' |
+--------+-----+------------+---------------------------------------------------+
| NV12 | | No | YUV420 planar (2 plane), UV plane in 'U, V, U, V' |
+--------+-----+------------+---------------------------------------------------+
YUV Packed Formats
------------------
+--------+-----+------------+------------------------------+
| Format | BPP | Supported | Description |
| | | by offline | |
| | | converter | |
+========+=====+============+==============================+
| YUY2 | | No | YUV422 packed like 'Y U Y V' |
+--------+-----+------------+------------------------------+
| UYVY | | No | YUV422 packed like 'U Y V Y' |
+--------+-----+------------+------------------------------+
Proprietary Formats
-------------------
+-------------+-----+------------+-------------+
| Format | BPP | Supported | Description |
| | | by offline | |
| | | converter | |
+=============+=====+============+=============+
| NEMA_TSC4 | | No | NEMA TSC4 |
+-------------+-----+------------+-------------+
| NEMA_TSC6 | | No | NEMA TSC6 |
+-------------+-----+------------+-------------+
| NEMA_TSC6A | | No | NEMA TSC6A |
+-------------+-----+------------+-------------+
| NEMA_TSC6AP | | No | NEMA TSC6AP |
+-------------+-----+------------+-------------+
| NEMA_TSC12 | | No | NEMA TSC12 |
+-------------+-----+------------+-------------+
| NEMA_TSC12A | | No | NEMA TSC12A |
+-------------+-----+------------+-------------+
@@ -0,0 +1,298 @@
.. _image_decoders:
==============
Image Decoders
==============
What is an Image Decoder?
*************************
Images that are encoded (i.e. outside of the list of built-in supported
:ref:`images_color_formats`) are dealt with through an Image Decoder. An Image
Decoder is a body of logic that can convert a coded image into one of the
recognized formats.
.. _built-in image decoders:
Built-In Image Decoders
***********************
LVGL comes with a number of image decoders to support a number of popular image formats:
.. container:: tighter-table-5
+---------+----------------------+--------------------+-----------+-----------------------+---------------------+
| Format | ``lv_conf.h`` | Reference | External | Form | RAM Cost |
| | Symbol to Set | | Library | | |
| | | | Required? | | |
+=========+======================+====================+===========+=======================+=====================+
| BMP | LV_USE_BMP | :ref:`bmp` | No | File only | Low (1 draw buffer) |
+---------+----------------------+--------------------+-----------+-----------------------+---------------------+
| PNG | LV_USE_LODEPNG | :ref:`lodepng_rst` | No | File or variable | Full image |
+---------+----------------------+--------------------+-----------+-----------------------+---------------------+
| PNG | LV_USE_LIBPNG | :ref:`libpng` | Yes | File or variable | Full image |
+---------+----------------------+--------------------+-----------+-----------------------+---------------------+
| JPG | LV_USE_LIBJPEG_TURBO | :ref:`libjpeg` | Yes | File only | 8x8 Pixel Tiles |
+---------+----------------------+--------------------+-----------+-----------------------+---------------------+
| JPG | LV_USE_TJPGD | :ref:`tjpgd` | Yes | File or variable | 8x8 Pixel Tiles |
+---------+----------------------+--------------------+-----------+-----------------------+---------------------+
| WEBP | LV_USE_LIBWEBP | :ref:`libwebp` | Yes | File only | Full image |
+---------+----------------------+--------------------+-----------+-----------------------+---------------------+
| SVG | LV_USE_SVG | :ref:`svg` | No | File or variable | Full image |
+---------+----------------------+--------------------+-----------+-----------------------+---------------------+
| GIF | LV_USE_GIF | :ref:`gif` | No | Use GIF Widget (File) | Widget + 1 frame |
+---------+----------------------+--------------------+-----------+-----------------------+---------------------+
| Lottie | See reference | :ref:`lv_lottie` | No | Use Lottie Widget | Widget + 1 frame |
+---------+----------------------+--------------------+-----------+-----------------------+---------------------+
Once you have the appropriate symbol set to ``1`` in ``lv_conf.h``, to use a file,
simply make the file accessible on an external storage device. You will need to then
pass the :ref:`file-system <file_system>` path to the file containing your image as
the ``src`` argument to :cpp:expr:`lv_image_set_src(icon, "S:my_icon.png")`, and LVGL
takes care of the rest.
To use the encoded file as a variable, choose one of these approaches:
- Use the online- or offline converter to convert the file to an
:cpp:type:`lv_image_dsc_t` object + data into a ``.c`` file and compile and link it
into your project. The color format is stored in the ``header.cf`` field of the
:cpp:type:`lv_image_dsc_t` struct.
- There could be case where it was needed to load an image file into
dynamically-allocated RAM at run-time and free it later, thus avoiding storing the
images as part of the application. In this case, you could manually create a
:cpp:type:`lv_image_dsc_t` and point the ``data`` field to the byte array containing
the file content and set the ``header.cf`` field to :c:macro:`LV_COLOR_FORMAT_RAW`
or :c:macro:`LV_COLOR_FORMAT_RAW_ALPHA`, and set the image source to this
:cpp:type:`lv_image_dsc_t` object using :cpp:expr:`lv_image_set_src(icon, &my_img_dsc)`,
and when it is time to decode, the registered decoder that recognizes the image
format will be used to decode it.
The types having the word "variable" in the "Form" column in the table above would
support this approach if it was needed.
Using Custom Image Formats
**************************
If you have a file-based image type that is not in the above list, you can set up LVGL
to successfully handle it by implementing a custom image decoder. You can use an
external decoding library or write your own. To "connect" it to LVGL, use
LVGL's *Image Decoder* interface.
An image decoder consists of 4 callbacks:
:info: Get some basic info about the image (width, height and color format).
:open: Open an image:
- optionally store entire decoded image;
- set ``dsc->decoded`` to ``NULL`` to indicate the image can be decoded incrementally;
- return :cpp:enumerator:`LV_RESULT_OK` if decoder can decode the given
image, :cpp:enumerator:`LV_RESULT_INVALID` otherwise. (This is normally
done by reading the image header from the file and determining
compatibility by reading the header content.)
:get_area: If *open* didn't fully open an image this function should decode the
indicated area of the image into the draw buffer.
:close: Close an opened image, and free the allocated resources.
You can add any number of image decoders. When an image needs to be drawn, the
library will try all the registered image decoders until it finds one which can open
the image, i.e. one which knows that format.
The built-in decoder understands all the formats in :ref:`images_color_formats` minus
the ``RAW`` formats.
.. _custom_image_formats:
Custom Image Formats
--------------------
The easiest way to create a custom image is to use the online image converter and
select ``RAW`` or ``RAW_WITH_ALPHA`` format. It will just take every byte of the
binary file you uploaded and write it as an image "bitmap". You then need to attach
an image decoder that will parse that bitmap and generate the real, render-able
bitmap.
``header.cf`` will be :cpp:enumerator:`LV_COLOR_FORMAT_RAW`,
:cpp:enumerator:`LV_COLOR_FORMAT_RAW_ALPHA` accordingly. Use the format according
to your needs: a fully opaque image, or one using an alpha channel.
The decoded format of a RAW image depends on the decoder. Example: JPG images are
decoded to RGB888 and PNG images are decoded to ARGB8888. See
:ref:`images_color_formats` for more details.
Registering an Image Decoder
----------------------------
Here's an example of getting LVGL to work with a custom format using the PNG decoder
as an example. In ``lv_libpng.c``, see the following functions as examples to follow.
.. container:: tighter-table-1
+----------------------------------------------+-------------------------+
| Action | Function |
+==============================================+=========================+
| Create and register image decoder | lv_libpng_init() |
+----------------------------------------------+-------------------------+
| De-initialize image decoder | lv_libpng_deinit() |
+----------------------------------------------+-------------------------+
| Gather basic information about the image | decoder_info() |
| and store it in ``header``. | |
+----------------------------------------------+-------------------------+
| Open a image and generate decoded image [1]_ | decoder_open() |
+----------------------------------------------+-------------------------+
| Free any allocated resources | decoder_close() |
+----------------------------------------------+-------------------------+
| Partially decode based on specified area | decoder_get_area() [2]_ |
| (Optional: use if ``decoder_open()`` does | |
| not decode whole image.) | |
+----------------------------------------------+-------------------------+
.. [1]
In ``decoder_open()``, you should try to open the image source pointed by
``dsc->src``. Its type is already in ``dsc->src_type == LV_IMG_SRC_FILE/VARIABLE``.
If this format/type is not supported by the decoder, return :cpp:enumerator:`LV_RESULT_INVALID`.
However, if you can open the image, a pointer to the decoded image should be
set in ``dsc->decoded``. If the format is known, but you don't want to
decode the entire image (e.g. no memory for it), set ``dsc->decoded = NULL`` and
use ``decoder_get_area()`` to get the image area pixels.
.. [2]
``lv_bmp.c`` has an example of ``decoder_get_area()``.
Manually Using an Image Decoder
-------------------------------
LVGL will use registered image decoders automatically if you try and
draw a raw image (i.e. using the ``lv_image`` Widget) but you can use them
manually as well. Create an :cpp:type:`lv_image_decoder_dsc_t` variable to describe
the decoding session and call :cpp:func:`lv_image_decoder_open`.
.. code-block:: c
lv_result_t res;
lv_image_decoder_dsc_t dsc;
lv_image_decoder_args_t args = { 0 }; /* Custom decoder behavior via args */
res = lv_image_decoder_open(&dsc, &my_img_dsc, &args);
if(res == LV_RESULT_OK) {
/* Do something with `dsc->decoded`. You can copy out the decoded image by `lv_draw_buf_dup(dsc.decoded)`*/
lv_image_decoder_close(&dsc);
}
.. note::
You would need to set :c:macro:`LV_USE_PRIVATE_API` to ``1`` in ``lv_conf.h``
in order to do this since the definition of the :cpp:type:`lv_image_decoder_dsc_t`
and :cpp:type:`_lv_image_decoder_args_t` structs are both in a private header file.
Image Post-Processing
---------------------
Considering that some hardware has special requirements for image formats, such as
alpha premultiplication and stride alignment, most image decoders (such as PNG
decoders) may not directly output image data that meets hardware requirements.
For this reason, LVGL provides a method for implementing custom image post-processing
to address unpredicted future GPU requirements (over and above the premultiplication
and stride alignment provided by :cpp:func:`lv_image_decoder_post_process`):
- In your custom GPU :ref:`draw unit <draw units>`, call a custom post-processing
function after ``lv_image_decoder_open`` to adjust the data in the image cache, and
- then mark the processing status in ``cache_entry->process_state`` (to avoid repeated
post-processing).
The below code example assumes the image was opened using the decoder interface
(e.g. using :ref:`libpng` and thus has already called
:cpp:func:`lv_image_decoder_post_process` to perform stride alignment and/or
premultiplication via the decoder descriptor's ``args`` field).
Example (requires :c:macro:`LV_USE_PRIVATE_API` to ``1`` in ``lv_conf.h``):
.. code-block:: c
/* Define post-processing state */
typedef enum {
MY_IMAGE_PROCESS_STATE_NONE = 0,
MY_IMAGE_PROCESS_STATE_BIT_SHIFTED = 1 << 4,
} image_process_state_t;
lv_result_t my_image_post_process(lv_image_decoder_dsc_t * dsc)
{
lv_color_format_t color_format = dsc->header.cf;
lv_result_t res = LV_RESULT_OK;
if (color_format == LV_COLOR_FORMAT_ARGB8888) {
lv_cache_t * cache_p = dsc->cache;
lv_cache_entry_t * entry = dsc->cache_entry;
lv_mutex_lock(&cache_p->lock);
if (!(entry->flags & MY_IMAGE_PROCESS_STATE_BIT_SHIFTED)) {
lv_draw_buf_t * shifted_buf = NULL; /* Insert allocation call here. */
if (shifted_buf == NULL) {
LV_LOG_ERROR("No memory for bit-shifting adjustment.");
res = LV_RESULT_INVALID;
goto alloc_failed;
}
/* Handle additional GPU requirement here. */
lv_free(dsc->decoded);
dsc->decoded = shifted_buf;
entry->flags |= MY_IMAGE_PROCESS_STATE_BIT_SHIFTED;
LV_LOG_USER("Bit shifting completed.");
}
alloc_failed:
lv_mutex_unlock(&cache_p->lock);
}
return res;
}
/* GPU draw unit */
void gpu_draw_image(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * draw_dsc, const lv_area_t * coords)
{
/* ... */
lv_image_decoder_dsc_t decoder_dsc;
lv_image_decoder_args_t args;
lv_memzero(&args, sizeof(args));
args.premultiply = true;
args.stride_align = true;
lv_result_t res = lv_image_decoder_open(&decoder_dsc, draw_dsc->src, &args);
if (res != LV_RESULT_OK) {
LV_LOG_ERROR("Failed to open image");
return;
}
/* Pre-multiplication and stride alignment are now done from the call to
* lv_image_decoder_open() above. But our additional GPU requirement (which we
* are calling bit-shifting above) isn't handled yet, so we do it below. */
res = my_image_post_process(&decoder_dsc);
if (res != LV_RESULT_OK) {
LV_LOG_ERROR("Failed to post-process image");
return;
}
/* ... */
}
API
***
.. API equals: lv_image_decoder_open
@@ -0,0 +1,17 @@
.. _images:
======
Images
======
.. toctree::
:maxdepth: 2
overview
sources
color_formats
adding_images
using_images
decoders
caching
@@ -0,0 +1,61 @@
.. _images overview:
========
Overview
========
In LVGL, the term "image" can refer to two things:
- an :ref:`lv_image` Widget (capitalized), or
- data that is used to draw an image to a Display.
This section of LVGL documentation is about the latter: it describes how to use the
LVGL images module to draw images (in various forms) to a Display.
What is an Image?
*****************
An image can be thought of as set of pixels used to create an image on a Display.
Images can be:
- an :cpp:type:`lv_image_dsc_t` object plus its pixel data in RAM or ROM in any of the
:ref:`supported pixel formats <images_color_formats>`, or
- a stored image in a file on an external file system, or loaded into RAM or ROM.
Such files can contain color formats other than the supported formats (e.g. JPEG,
BMP, PNG, SVG, WEBP, GIF or other formats).
When the color format of the image is not in the same format as the :ref:`Display <display>` it
will be sent to, the drawing logic converts those pixels to the target Display's
format (into a buffer) when it is drawn.
Using Images
************
You make use of images by using any of these Widgets:
+-----------------------+---------------------------------+
| Widget | Via |
+=======================+=================================+
| :ref:`lv_image` | setting image source |
+-----------------------+---------------------------------+
| :ref:`lv_imagebutton` | setting image source |
+-----------------------+---------------------------------+
| :ref:`lv_animimg` | setting image source |
+-----------------------+---------------------------------+
| :ref:`lv_canvas` | direct access to drawing buffer |
+-----------------------+---------------------------------+
| any | background image style |
+-----------------------+---------------------------------+
There are also a number of Widgets that use Image Widgets internally for optional icons:
- :ref:`lv_list`
- :ref:`lv_menu`
- :ref:`lv_msgbox`
- :ref:`lv_win`
@@ -0,0 +1,156 @@
.. include:: /include/external_links.txt
.. _image_sources:
=============
Image Sources
=============
The images module supports images in any of 3 forms:
.. container:: tighter-table-3
+------------+------------------------------------------------------------------+
| Form | Source |
+============+==================================================================+
| Variables_ | :cpp:type:`lv_image_dsc_t` object + data in ROM or RAM |
+------------+------------------------------------------------------------------+
| Files_ | :ref:`file_system` path to file (e.g. JPG, PNG, BMP etc.) |
+------------+------------------------------------------------------------------+
| Symbols_ | C strings starting with Unicode characters (e.g. icons) in UTF-8 |
+------------+------------------------------------------------------------------+
Image sources are set by calling one of the ``..._set_src()`` functions. See code
examples below.
.. _image_sources_variables:
Variables
*********
In this context, a "variable" is a C symbol that is used in C code to refer to an
object in either RAM or ROM.
Images stored as variables are comprised of an :cpp:struct:`lv_image_dsc_t` struct
plus its data. The struct contains the following fields:
:header:
:magic: Magic number (must be LV_IMAGE_HEADER_MAGIC)
:cf: Color format. See :ref:`images_color_formats`.
:flags: Image flags (any of the ``LV_IMAGE_FLAGS_...`` enumeration values).
:w: Width in pixels (<= 2048)
:h: Height in pixels (<= 2048)
:stride: Number of bytes between the beginning of one row of pixels and the beginning of the next row
:reserved_2: reserved for future use
:data_size: length of ``data`` in bytes
:data: pointer to a byte array where the data of the image is stored (pixels
and sometimes indexed color palettes [for indexed color formats]).
When ``header.cf`` is one of the ``RAW`` formats, this can also contain
the contents of a file loaded into RAM at run-time, or embedded in ROM
(program space).
These are usually stored within a project as a C file generated by one of these two
LVGL image converters:
- `LVGL Online Image Converter`_
- Offline converter in ``./scripts/LVGLImage.py``.
At this writing, the online converter supports these formats:
- RGB565
- RGB565A8
- RGB888
- XRGB8888
- ARGB8888
The offline converter can convert an image into the above formats plus all the other
supported color formats.
The generated C files are compiled and linked into the resulting executable like any
other ``const`` data.
See :ref:`adding images to your project` for more details.
Example:
.. code-block:: c
LV_IMAGE_DECLARE(img_cogwheel_argb);
lv_obj_t * img = lv_image_create(lv_screen_active());
lv_image_set_src(img, &img_cogwheel_argb);
.. _image_sources_files:
Files
*****
Files can be used as image sources by passing in the path string to the image file
to the ``lv_<widget>_set_src()`` function as the ``src`` argument. The string must
begin with a printable ASCII character (range [0x20-0x7F]). Example:
.. code-block:: c
lv_image_set_src(icon, "S:my_icon.png");
Images stored as files are normally not linked into the resulting executable, and must
be read into RAM before being drawn. As a result, they are not as resource-friendly
as images linked at compile time. However, they are easier to replace without
needing to rebuild the main program.
Exceptions where there is no meaningful extra memory usage:
- JPEG: Only a few pixels are read and drawn at once.
- BMP: Pixels are transferred directly from the file to the draw buffer.
- BIN: Pixels are transferred line-by-line to the draw buffer.
For the images module to deal with files you need to add a *Driver* for the target
storage system to LVGL. See :ref:`file_system` for details.
.. _image_sources_symbols:
Symbols
*******
Symbols that can be used as an image source are ``char *`` strings beginning with a
Unicode character encoded in UTF-8, which will have a first-byte value >= 0x80. After
that, these strings can contain any other characters, including additional Unicode
characters. Such strings are passed as the image source like this:
.. code-block:: c
lv_image_set_src(icon, LV_SYMBOL_BATTERY_FULL);
/* or */
lv_image_set_src(icon, LV_SYMBOL_OK " Accept");
The file ``./src/font/lv_symbol_def.h`` contains a wide variety of Unicode symbols you
can use directly, or you can make your own. See :ref:`font_adding_a_custom_symbol`
for details.
.. note::
Symbols are only implemented for :ref:`lv_image` Widgets.
Examples
********
See :ref:`Using Images Examples <using_images_examples>` for a number of examples of
using image sources in these 3 forms.
API
***
.. API equals: lv_image_set_src
@@ -0,0 +1,40 @@
.. _using images:
============
Using Images
============
The simplest way to use an image in LVGL is to display it with an
:ref:`lv_image` Widget:
.. code-block:: c
lv_obj_t * icon = lv_image_create(lv_screen_active());
/* From variable */
lv_image_set_src(icon, &my_img_dsc);
/* From file */
lv_image_set_src(icon, "S:my_icon.bin");
/* From Unicode string */
lv_image_set_src(icon, LV_SYMBOL_BATTERY_FULL);
If the image was converted to a variable with the :ref:`online <images_online_converter>`
or :ref:`offline converter <images_offline_converter>`, you should use
:cpp:expr:`LV_IMAGE_DECLARE(my_img_dsc)` to declare the image in the file where
you want to use it.
.. _using_images_examples:
Examples
********
.. include:: /examples/widgets/image/index.rst
.. include:: /examples/libs/bmp/index.rst
.. include:: /examples/libs/libpng/index.rst
+1 -1
View File
@@ -10,7 +10,7 @@ Main Modules
display/index
indev/index
fonts/index
image
images/index
color
timer
animation
+1 -1
View File
@@ -42,7 +42,7 @@ Or you can use
Canvas supports all the color formats like
:cpp:enumerator:`LV_COLOR_FORMAT_ARGB8888` or :cpp:enumerator:`LV_COLOR_FORMAT_I2`. See the full
list in the :ref:`Color formats <overview_image_color_formats>` section.
list in the :ref:`Color formats <images_color_formats>` section.
Indexed colors
--------------
+6 -5
View File
@@ -1,4 +1,5 @@
.. include:: /include/substitutions.txt
.. include:: /include/external_links.txt
.. _lv_image:
================
@@ -11,7 +12,7 @@ Overview
Images are Widgets that display images from flash (as arrays) or
from files. Images can also display symbols (``LV_SYMBOL_...``).
Using the :ref:`Image decoder interface <overview_image_decoder>`, custom image formats
Using the :ref:`Image decoder interface <image_decoders>`, custom image formats
can be supported as well.
.. _lv_image_parts_and_styles:
@@ -39,7 +40,7 @@ To provide maximum flexibility, the source of the image can be:
To set the source of an image, use :cpp:expr:`lv_image_set_src(img, src)`.
To generate a pixel array from a PNG, JPG or BMP image, use the `Online image converter tool <https://lvgl.io/tools/imageconverter>`__
To generate a pixel array from a PNG, JPG or BMP image, use the `LVGL Online Image Converter`_
and set the converted image as the image source with its pointer with
:cpp:expr:`lv_image_set_src(img1, &converted_img_var)`.
To make the converted image variable accessible from the C file, declare it with
@@ -88,8 +89,8 @@ Besides RGB888 and ARGB8888 color formats, the following formats are supported:
- **Indexed**: Image has a color palette, and each pixel is an index into that palette.
- **Alpha indexed**: The values stored at pixel positions are alpha (opacity) values.
These options can be selected in the image converter. Learn more
about color formats in the :ref:`overview_image_color_formats` section.
These options can be selected in the `LVGL Online Image Converter`_. Learn more
about color formats in the :ref:`images_color_formats` section.
Recolor
-------
@@ -141,7 +142,7 @@ causes the transformations to be of higher quality, but slower.
Transformations require the whole image to be available. Therefore
indexed images (``LV_COLOR_FORMAT_I1/2/4/8_...``) and alpha only images cannot be transformed.
In other words transformations work only on normal (A)RGB or A8 images stored as a
C array, or on images provided by a custom :ref:`overview_image_decoder`
C array, or on images provided by a custom :ref:`image_decoders`
that returns the whole image.
Note that the real coordinates of image Widgets do not change with a
+5 -3
View File
@@ -1,3 +1,5 @@
.. _VSCode Simulator: https://github.com/lvgl/lv_port_pc_vscode
.. _Figma: https://www.figma.com/
.. _see all plans: https://pro.lvgl.io/pricing
.. _VSCode Simulator: https://github.com/lvgl/lv_port_pc_vscode
.. _Figma: https://www.figma.com/
.. _see all plans: https://pro.lvgl.io/pricing
.. _LVGL Online Image Converter: https://lvgl.io/tools/imageconverter
.. _LVGL Online Font Converter: https://lvgl.io/tools/fontconverter