mirror of
https://github.com/lvgl/lvgl.git
synced 2026-05-11 05:37:37 +08:00
feat(image): add custom RLE decoder (#4332)
Signed-off-by: Xu Xingliang <xuxingliang@xiaomi.com>
This commit is contained in:
@@ -1115,6 +1115,9 @@ menu "LVGL configuration"
|
||||
config LV_USE_GIF
|
||||
bool "GIF decoder library"
|
||||
|
||||
config LV_USE_RLE
|
||||
bool "RLE compressed bin image decoder library"
|
||||
|
||||
config LV_USE_QRCODE
|
||||
bool "QR code library"
|
||||
|
||||
|
||||
@@ -19,3 +19,4 @@
|
||||
barcode
|
||||
rlottie
|
||||
ffmpeg
|
||||
rle
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
@@ -0,0 +1,84 @@
|
||||
RLE Decoder
|
||||
===========
|
||||
|
||||
The RLE Decoder is a part of LVGL that is responsible for decoding RLE
|
||||
compressed original LVGL binary files. The file name suffix is always set
|
||||
to '.rle' and the file header is added with another 64-bit value that
|
||||
includes a 32-bit magic number and 32-bit RLE information.
|
||||
|
||||
The decoder supports both variable and file as image sources. The original
|
||||
binary data is directly decompressed to RAM, and further decoded by LVGL's
|
||||
built-in decoder.
|
||||
|
||||
Benefits
|
||||
--------
|
||||
|
||||
Based on test result from a watch project. Most of the images can be compressed
|
||||
to save more than 70% space as show in below statistic. It shows the file count
|
||||
of every compress level. For rare conditions, RLE compress may increase the file
|
||||
size if there's no large repetition in data.
|
||||
|
||||
.. image:: /libs/rle-compress-statistics.png
|
||||
:alt: RLE compress statistics from a watch project
|
||||
:align: center
|
||||
|
||||
|
||||
Theory
|
||||
------
|
||||
|
||||
The RLE algorithm is a simple compression algorithm that is based on the fact that
|
||||
the for many pixels, the color is the same. The algorithm simply counts how many
|
||||
repeated data are there and store the count value and the color value.
|
||||
If the coming pixels are not repeated, it stores the non-repeat count value and
|
||||
original color value. For more details, the script used to compress the image
|
||||
can be found from `lvgl/script/LVGLImage.py`.
|
||||
|
||||
.. code:: python
|
||||
|
||||
def rle_compress(self, data: bytearray, blksize: int, threshold=16):
|
||||
index = 0
|
||||
data_len = len(data)
|
||||
compressed_data = []
|
||||
while index < data_len:
|
||||
memview = memoryview(data)
|
||||
repeat_cnt = self.get_repeat_count(
|
||||
memview[index:], blksize)
|
||||
if repeat_cnt == 0:
|
||||
# done
|
||||
break
|
||||
elif repeat_cnt < threshold:
|
||||
nonrepeat_cnt = self.get_nonrepeat_count(
|
||||
memview[index:], blksize, threshold)
|
||||
ctrl_byte = uint8_t(nonrepeat_cnt | 0x80)
|
||||
compressed_data.append(ctrl_byte)
|
||||
compressed_data.append(
|
||||
memview[index: index + nonrepeat_cnt*blksize])
|
||||
index += nonrepeat_cnt * blksize
|
||||
else:
|
||||
ctrl_byte = uint8_t(repeat_cnt)
|
||||
compressed_data.append(ctrl_byte)
|
||||
compressed_data.append(memview[index: index + blksize])
|
||||
index += repeat_cnt * blksize
|
||||
|
||||
return b"".join(compressed_data)
|
||||
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
To use the RLE Decoder, ensure that `LV_USE_RLE` is defined and set to `1`.
|
||||
The RLE image can be used same as other images.
|
||||
|
||||
.. code:: c
|
||||
|
||||
lv_image_set_src(img, "path/to/image.rle");
|
||||
|
||||
Generate RLE images
|
||||
-------------------
|
||||
|
||||
The image can be directly generated using script `lvgl/script/LVGLImage.py`
|
||||
|
||||
|
||||
.. code:: bash
|
||||
|
||||
./script/LVGLImage.py --ofmt RLE --cf I8 cogwheel.png
|
||||
@@ -81,7 +81,7 @@
|
||||
</release>
|
||||
<release date="2022-08-30" version="1.0.8" url="https://github.com/lvgl/lvgl/raw/eb2e296d23b009aca7daf0e9be062d05b4b0048a/env_support/cmsis-pack/LVGL.lvgl.1.0.8.pack">
|
||||
- LVGL 9.0.0-dev
|
||||
- Add the binding for pikascript (an ultra-light-weight python VM)
|
||||
- Add the binding for pikascript (an ultra-light-weight python VM)
|
||||
- Montyly update for August
|
||||
</release>
|
||||
<release date="2022-07-29" version="1.0.7" url="https://github.com/lvgl/lvgl/raw/b454a66e0be85976385c81cf9c9025f272a66f5d/env_support/cmsis-pack/LVGL.lvgl.1.0.7.pack">
|
||||
@@ -212,7 +212,7 @@
|
||||
<description>Require Arm-2D Support</description>
|
||||
<require Cclass="Acceleration" Cgroup="Arm-2D"/>
|
||||
</condition>
|
||||
|
||||
|
||||
<condition id="LVGL-GPU-Arm-2D">
|
||||
<description>Enable LVGL Arm-2D GPU Support</description>
|
||||
<require Cclass="LVGL" Cgroup="lvgl" Csub="Essential"/>
|
||||
@@ -223,7 +223,7 @@
|
||||
<deny Cclass="LVGL" Cgroup="lvgl" Csub="GPU NXP-VGLite"/>
|
||||
<deny Cclass="LVGL" Cgroup="lvgl" Csub="GPU GD32-IPA"/>
|
||||
</condition>
|
||||
|
||||
|
||||
<condition id="LVGL-GPU-STM32-DMA2D">
|
||||
<description>Enable LVGL Arm-2D GPU Support</description>
|
||||
<require Cclass="LVGL" Cgroup="lvgl" Csub="Essential"/>
|
||||
@@ -234,7 +234,7 @@
|
||||
<deny Cclass="LVGL" Cgroup="lvgl" Csub="GPU NXP-VGLite"/>
|
||||
<deny Cclass="LVGL" Cgroup="lvgl" Csub="GPU GD32-IPA"/>
|
||||
</condition>
|
||||
|
||||
|
||||
<condition id="LVGL-GPU-SWM341-DMA2D">
|
||||
<description>Enable LVGL Arm-2D GPU Support</description>
|
||||
<require Cclass="LVGL" Cgroup="lvgl" Csub="Essential"/>
|
||||
@@ -245,7 +245,7 @@
|
||||
<deny Cclass="LVGL" Cgroup="lvgl" Csub="GPU NXP-VGLite"/>
|
||||
<deny Cclass="LVGL" Cgroup="lvgl" Csub="GPU GD32-IPA"/>
|
||||
</condition>
|
||||
|
||||
|
||||
<condition id="LVGL-GPU-NXP-PXP">
|
||||
<description>Enable LVGL Arm-2D GPU Support</description>
|
||||
<require Cclass="LVGL" Cgroup="lvgl" Csub="Essential"/>
|
||||
@@ -256,7 +256,7 @@
|
||||
<deny Cclass="LVGL" Cgroup="lvgl" Csub="GPU NXP-VGLite"/>
|
||||
<deny Cclass="LVGL" Cgroup="lvgl" Csub="GPU GD32-IPA"/>
|
||||
</condition>
|
||||
|
||||
|
||||
<condition id="LVGL-GPU-NXP-VGLite">
|
||||
<description>Enable LVGL Arm-2D GPU Support</description>
|
||||
<require Cclass="LVGL" Cgroup="lvgl" Csub="Essential"/>
|
||||
@@ -267,7 +267,7 @@
|
||||
<!--<deny Cclass="LVGL" Cgroup="lvgl" Csub="GPU NXP-VGLite"/>-->
|
||||
<deny Cclass="LVGL" Cgroup="lvgl" Csub="GPU GD32-IPA"/>
|
||||
</condition>
|
||||
|
||||
|
||||
<condition id="LVGL-GPU-GD32-IPA">
|
||||
<description>Enable LVGL Arm-2D GPU Support</description>
|
||||
<require Cclass="LVGL" Cgroup="lvgl" Csub="Essential"/>
|
||||
@@ -500,7 +500,7 @@
|
||||
<file category="sourceC" name="lv_cmsis_pack.c" attr="config" version="1.0.0" />
|
||||
<file category="header" name="lvgl.h" />
|
||||
<file category="doc" name="README.md"/>
|
||||
|
||||
|
||||
<!-- code template -->
|
||||
<file category="header" name="examples/porting/lv_port_disp_template.h" attr="template" select="Display port template" version="2.0.0"/>
|
||||
<file category="sourceC" name="examples/porting/lv_port_disp_template.c" attr="template" select="Display port template" version="2.0.0"/>
|
||||
@@ -782,6 +782,21 @@
|
||||
#define LV_USE_GIF 1
|
||||
</RTE_Components_h>
|
||||
|
||||
/*! \brief enable RLE compressed bin image decoder support */
|
||||
#define LV_USE_RLE 1
|
||||
</RTE_Components_h>
|
||||
|
||||
</component>
|
||||
|
||||
<component Cgroup="lvgl" Csub="Libs RLE" condition="LVGL-Essential">
|
||||
<description>Add RLE compressed bin image decoder support</description>
|
||||
<files>
|
||||
<!-- src/libs/rle -->
|
||||
<file category="sourceC" name="src/libs/rle/lv_rle_decoder.c" />
|
||||
</files>
|
||||
|
||||
<RTE_Components_h>
|
||||
|
||||
</component>
|
||||
|
||||
<component Cgroup="lvgl" Csub="Libs sJPG" condition="LVGL-Essential">
|
||||
@@ -799,7 +814,7 @@
|
||||
</RTE_Components_h>
|
||||
|
||||
</component>
|
||||
|
||||
|
||||
<component Cgroup="lvgl" Csub="Libs QRCode" condition="LVGL-Essential">
|
||||
<description>Add QRCode support</description>
|
||||
<files>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
1. Copy the **lv_conf_template.h** to '**cmsis-pack**' directory
|
||||
|
||||
2. Set the macro protector to '1'
|
||||
2. Set the macro protector to '1'
|
||||
|
||||
```c
|
||||
...
|
||||
@@ -47,7 +47,7 @@ remove the misleading guide above this code segment.
|
||||
#define LV_STRING_INCLUDE <string.h>
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
5. Remove macro definitions for
|
||||
|
||||
@@ -135,7 +135,7 @@ Make sure `LV_MEM_SIZE` is no less than `(64*1024U)`.
|
||||
#if LV_USE_DEMO_WIDGETS
|
||||
#define LV_DEMO_WIDGETS_SLIDESHOW 0
|
||||
#endif
|
||||
|
||||
|
||||
/*Benchmark your system*/
|
||||
#if LV_USE_DEMO_BENCHMARK
|
||||
/*Use RGB565A8 images with 16 bit color depth instead of ARGB8565*/
|
||||
@@ -143,7 +143,7 @@ Make sure `LV_MEM_SIZE` is no less than `(64*1024U)`.
|
||||
#endif
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
10. Remove following macro definitions in the `3rd party libraries` section:
|
||||
|
||||
@@ -153,6 +153,7 @@ Make sure `LV_MEM_SIZE` is no less than `(64*1024U)`.
|
||||
- \#define LV_USE_FS_FATFS 0
|
||||
- \#define LV_USE_LODEPNG 0
|
||||
- \#define LV_USE_BMP 0
|
||||
- \#define LV_USE_RLE 0
|
||||
- \#define LV_USE_SJPG 0
|
||||
- \#define LV_USE_GIF 0
|
||||
- \#define LV_USE_BARCODE 0
|
||||
|
||||
@@ -619,6 +619,9 @@
|
||||
/*Decode bin images to RAM*/
|
||||
#define LV_BIN_DECODER_RAM_LOAD 0
|
||||
|
||||
/*RLE decoder library*/
|
||||
#define LV_USE_RLE 0
|
||||
|
||||
/*QR code library*/
|
||||
#define LV_USE_QRCODE 0
|
||||
|
||||
|
||||
@@ -91,6 +91,7 @@ extern "C" {
|
||||
|
||||
#include "src/libs/barcode/lv_barcode.h"
|
||||
#include "src/libs/bmp/lv_bmp.h"
|
||||
#include "src/libs/rle/lv_rle_decoder.h"
|
||||
#include "src/libs/fsdrv/lv_fsdrv.h"
|
||||
#include "src/libs/lodepng/lv_lodepng.h"
|
||||
#include "src/libs/libpng/lv_libpng.h"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* @file lv_rle_decoder.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_RLE_DECODER_H
|
||||
#define LV_RLE_DECODER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "../../../lvgl.h"
|
||||
|
||||
#if LV_USE_RLE
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Register the RLE decoder functions in LVGL
|
||||
*/
|
||||
void lv_rle_decoder_init(void);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /*LV_USE_RLE*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /*LV_RLE_DECODER_H*/
|
||||
@@ -2055,6 +2055,15 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*RLE decoder library*/
|
||||
#ifndef LV_USE_RLE
|
||||
#ifdef CONFIG_LV_USE_RLE
|
||||
#define LV_USE_RLE CONFIG_LV_USE_RLE
|
||||
#else
|
||||
#define LV_USE_RLE 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*QR code library*/
|
||||
#ifndef LV_USE_QRCODE
|
||||
#ifdef CONFIG_LV_USE_QRCODE
|
||||
|
||||
@@ -258,6 +258,10 @@ void lv_init(void)
|
||||
lv_bmp_init();
|
||||
#endif
|
||||
|
||||
#if LV_USE_RLE
|
||||
lv_rle_decoder_init();
|
||||
#endif
|
||||
|
||||
/*Make FFMPEG last because the last converter will be checked first and
|
||||
*it's superior to any other */
|
||||
#if LV_USE_FFMPEG
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 76 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 103 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 95 KiB |
@@ -60,6 +60,7 @@
|
||||
#define LV_USE_FS_MEMFS 1
|
||||
#define LV_FS_MEMFS_LETTER 'M'
|
||||
|
||||
#define LV_USE_RLE 1
|
||||
#define LV_USE_LODEPNG 1
|
||||
#define LV_USE_LIBPNG 1
|
||||
#define LV_USE_BMP 1
|
||||
|
||||
@@ -17,5 +17,6 @@
|
||||
|
||||
#define LV_USE_LODEPNG 1
|
||||
#define LV_USE_BMP 1
|
||||
#define LV_USE_RLE 1
|
||||
#define LV_USE_GIF 1
|
||||
#define LV_USE_QRCODE 1
|
||||
|
||||
@@ -157,4 +157,52 @@ void test_image_built_in_decode_rotate_and_recolor(void)
|
||||
TEST_ASSERT_EQUAL_SCREENSHOT("draw/image_format_rotate_and_recolor.png");
|
||||
}
|
||||
|
||||
void test_image_rle_decode(void)
|
||||
{
|
||||
img_create("rleA8", "A:src/test_files/binimages/cogwheel.A8.rle", false, false);
|
||||
img_create("rleI1", "A:src/test_files/binimages/cogwheel.I1.rle", false, false);
|
||||
img_create("rleI2", "A:src/test_files/binimages/cogwheel.I2.rle", false, false);
|
||||
img_create("rleI4", "A:src/test_files/binimages/cogwheel.I4.rle", false, false);
|
||||
img_create("rleI8", "A:src/test_files/binimages/cogwheel.I8.rle", false, false);
|
||||
img_create("rleRGB565A8", "A:src/test_files/binimages/cogwheel.RGB565A8.rle", false, false);
|
||||
img_create("rleRGB565", "A:src/test_files/binimages/cogwheel.RGB565.rle", false, false);
|
||||
img_create("rleRGB888", "A:src/test_files/binimages/cogwheel.RGB888.rle", false, false);
|
||||
img_create("rleXRGB8888", "A:src/test_files/binimages/cogwheel.XRGB8888.rle", false, false);
|
||||
img_create("rleARGB8888", "A:src/test_files/binimages/cogwheel.ARGB8888.rle", false, false);
|
||||
|
||||
TEST_ASSERT_EQUAL_SCREENSHOT("draw/image_format_rle.png");
|
||||
}
|
||||
|
||||
void test_image_rle_decode_rotate(void)
|
||||
{
|
||||
img_create("rleA8", "A:src/test_files/binimages/cogwheel.A8.rle", true, false);
|
||||
img_create("rleI1", "A:src/test_files/binimages/cogwheel.I1.rle", true, false);
|
||||
img_create("rleI2", "A:src/test_files/binimages/cogwheel.I2.rle", true, false);
|
||||
img_create("rleI4", "A:src/test_files/binimages/cogwheel.I4.rle", true, false);
|
||||
img_create("rleI8", "A:src/test_files/binimages/cogwheel.I8.rle", true, false);
|
||||
img_create("rleRGB565A8", "A:src/test_files/binimages/cogwheel.RGB565A8.rle", true, false);
|
||||
img_create("rleRGB565", "A:src/test_files/binimages/cogwheel.RGB565.rle", true, false);
|
||||
img_create("rleRGB888", "A:src/test_files/binimages/cogwheel.RGB888.rle", true, false);
|
||||
img_create("rleXRGB8888", "A:src/test_files/binimages/cogwheel.XRGB8888.rle", true, false);
|
||||
img_create("rleARGB8888", "A:src/test_files/binimages/cogwheel.ARGB8888.rle", true, false);
|
||||
|
||||
TEST_ASSERT_EQUAL_SCREENSHOT("draw/image_format_rle_rotate.png");
|
||||
}
|
||||
|
||||
void test_image_rle_decode_rotate_recolor(void)
|
||||
{
|
||||
img_create("rleA8", "A:src/test_files/binimages/cogwheel.A8.rle", true, true);
|
||||
img_create("rleI1", "A:src/test_files/binimages/cogwheel.I1.rle", true, true);
|
||||
img_create("rleI2", "A:src/test_files/binimages/cogwheel.I2.rle", true, true);
|
||||
img_create("rleI4", "A:src/test_files/binimages/cogwheel.I4.rle", true, true);
|
||||
img_create("rleI8", "A:src/test_files/binimages/cogwheel.I8.rle", true, true);
|
||||
img_create("rleRGB565A8", "A:src/test_files/binimages/cogwheel.RGB565A8.rle", true, true);
|
||||
img_create("rleRGB565", "A:src/test_files/binimages/cogwheel.RGB565.rle", true, true);
|
||||
img_create("rleRGB888", "A:src/test_files/binimages/cogwheel.RGB888.rle", true, true);
|
||||
img_create("rleXRGB8888", "A:src/test_files/binimages/cogwheel.XRGB8888.rle", true, true);
|
||||
img_create("rleARGB8888", "A:src/test_files/binimages/cogwheel.ARGB8888.rle", true, true);
|
||||
|
||||
TEST_ASSERT_EQUAL_SCREENSHOT("draw/image_format_rle_rotate_recolor.png");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user