feat(rle): add RLE compressed binary image support (#4870)

Signed-off-by: Xu Xingliang <xuxingliang@xiaomi.com>
This commit is contained in:
Neo Xu 2023-11-30 16:47:15 +08:00 committed by GitHub
parent 5d38a26a8a
commit 16254ef90d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 488 additions and 32 deletions

View File

@ -91,6 +91,11 @@ class PngQuant:
return compressed
class CompressMethod(Enum):
NONE = 0x00
RLE = 0x01
class ColorFormat(Enum):
UNKNOWN = 0x00
TRUECOLOR = 0x04
@ -280,8 +285,10 @@ class LVGLImageHeader:
w: int = 0,
h: int = 0,
stride: int = 0,
align: int = 1):
align: int = 1,
flags: int = 0):
self.cf = cf
self.flags = flags
self.w = w & 0xffff
self.h = h & 0xffff
if w > 0xffff or h > 0xffff:
@ -314,8 +321,7 @@ class LVGLImageHeader:
binary = bytearray()
binary += uint8_t(self.cf.value)
binary += uint8_t(0) # 8bits format
binary += uint8_t(0) # 8bits user flags
binary += uint8_t(0) # 8bits reserved
binary += uint16_t(self.flags) # 16bits flags
binary += uint16_t(self.w) # 16bits width
binary += uint16_t(self.h) # 16bits height
@ -338,6 +344,40 @@ class LVGLImageHeader:
return self
class LVGLCompressData:
def __init__(self,
cf: ColorFormat,
method: CompressMethod,
raw_data: bytes = b''):
self.blk_size = (cf.bpp + 7) // 8
self.compress = method
self.raw_data = raw_data
self.raw_data_len = len(raw_data)
self.compressed = self._compress(raw_data)
def _compress(self, raw_data: bytes) -> bytearray:
if self.compress == CompressMethod.NONE:
return raw_data
if self.compress == CompressMethod.RLE:
# RLE compression performs on pixel unit, pad data to pixel unit
pad = b'\x00' * (self.blk_size - self.raw_data_len % self.blk_size)
self.raw_data_len += len(pad)
compressed = RLEImage().rle_compress(raw_data + pad, self.blk_size)
else:
raise ParameterError(f"Invalid compress method: {self.compress}")
self.compressed_len = len(compressed)
bin = bytearray()
bin += uint32_t(self.compress.value)
bin += uint32_t(self.compressed_len)
bin += uint32_t(self.raw_data_len)
bin += compressed
return bin
class LVGLImage:
def __init__(self,
@ -346,12 +386,17 @@ class LVGLImage:
h: int = 0,
data: bytes = b'') -> None:
self.stride = 0 # default no valid stride value
self.compress = CompressMethod.NONE
self.set_data(cf, w, h, data)
def __repr__(self) -> str:
return (f"'LVGL image {self.w}x{self.h}, {self.cf.name},"
f" (12+{self.data_len})Byte'")
def set_compress(self, method: CompressMethod):
# only do compression when return binary data
self.compress = method
def adjust_stride(self, stride: int = 0, align: int = 1):
'''
Stride can be set directly, or by stride alignment in bytes
@ -439,9 +484,17 @@ class LVGLImage:
raw data
'''
bin = bytearray()
header = LVGLImageHeader(self.cf, self.w, self.h, self.stride)
flags = 0
flags |= 0x08 if self.compress != CompressMethod.NONE else 0
header = LVGLImageHeader(self.cf,
self.w,
self.h,
self.stride,
flags=flags)
bin += header.binary
bin += self.data
compress = LVGLCompressData(self.cf, self.compress, self.data)
bin += compress.compressed
return bin
@property
@ -614,7 +667,7 @@ const lv_img_dsc_t {varname} = {{
data += [0, 0, 0, a]
encoder = png.Writer(self.w, self.h, greyscale=False, alpha=True)
elif self.cf == ColorFormat.L8:
# to greyscale
# to grayscale
encoder = png.Writer(self.w,
self.h,
bitdepth=self.cf.bpp,
@ -634,7 +687,7 @@ const lv_img_dsc_t {varname} = {{
with open(filename, "wb") as f:
encoder.write_array(f, data)
self.adjust_stride(stride=self.stride)
self.adjust_stride(stride=old_stride)
def from_png(self,
filename: str,
@ -852,8 +905,8 @@ class RLEImage(LVGLImage):
index = 0
data_len = len(data)
compressed_data = []
memview = memoryview(data)
while index < data_len:
memview = memoryview(data)
repeat_cnt = self.get_repeat_count(memview[index:], blksize)
if repeat_cnt == 0:
# done
@ -946,6 +999,7 @@ class PNGConverter:
odir: str,
background: int = 0x00,
align: int = 1,
compress: CompressMethod = CompressMethod.NONE,
keep_folder=True) -> None:
self.files = files
self.cf = cf
@ -954,6 +1008,7 @@ class PNGConverter:
self.pngquant = None
self.keep_folder = keep_folder
self.align = align
self.compress = compress
self.background = background
def _replace_ext(self, input, ext):
@ -974,6 +1029,7 @@ class PNGConverter:
self.cf,
background=self.background)
rle.adjust_stride(align=self.align)
rle.set_compress(self.compress)
output.append((f, rle))
rle.to_rle(self._replace_ext(f, ".rle"))
else:
@ -981,6 +1037,7 @@ class PNGConverter:
self.cf,
background=self.background)
img.adjust_stride(align=self.align)
img.set_compress(self.compress)
output.append((f, img))
if self.ofmt == OutputFormat.BIN_FILE:
img.to_bin(self._replace_ext(f, ".bin"))
@ -1008,6 +1065,12 @@ def main():
"XRGB8888", "RGB565", "RGB565A8", "RGB888", "TRUECOLOR",
"TRUECOLOR_ALPHA", "AUTO"
])
parser.add_argument('--compress',
help=("Binary data compress method, default to NONE"),
default="NONE",
choices=["NONE", "RLE"])
parser.add_argument('--align',
help="stride alignment in bytes for bin image",
default=1,
@ -1048,6 +1111,7 @@ def main():
cf = ColorFormat[args.cf]
ofmt = OutputFormat(args.ofmt)
compress = CompressMethod[args.compress]
converter = PNGConverter(files,
cf,
@ -1055,6 +1119,7 @@ def main():
args.output,
background=args.background,
align=args.align,
compress=compress,
keep_folder=False)
output = converter.convert()
for f, img in output:
@ -1066,10 +1131,11 @@ def main():
def test():
logging.basicConfig(level=logging.INFO)
f = "pngs/cogwheel.RGB565A8.png"
img = LVGLImage().from_png(f, cf=ColorFormat.RGB565, background=0xFF_FF_00)
img = LVGLImage().from_png(f, cf=ColorFormat.RGB888, background=0xFF_FF_00)
img.adjust_stride(align=16)
img.to_bin(f + ".bin")
img.to_png(f + ".png") # convert back to png
img.set_compress(CompressMethod.RLE)
img.to_bin("output/cogwheel.RGB888.bin")
img.to_png("output/cogwheel.RGB888.png.png") # convert back to png
if __name__ == "__main__":

View File

@ -62,6 +62,13 @@ typedef enum _lv_image_flags_t {
*/
LV_IMAGE_FLAGS_VECTORS = 0x04,
/**
* The image data is compressed, so decoder needs to decode image firstly.
* If this flag is set, the whole image will be decompressed upon decode, and
* `get_area_cb` won't be necessary.
*/
LV_IMAGE_FLAGS_COMPRESSED = 0x08,
/**
* Flags reserved for user, lvgl won't use these bits.
*/
@ -75,6 +82,12 @@ typedef enum _lv_image_flags_t {
LV_IMAGE_FLAGS_USER8 = 0x0800,
} lv_image_flags_t;
typedef enum {
LV_IMAGE_COMPRESS_NONE = 0,
LV_IMAGE_COMPRESS_RLE, /*LVGL custom RLE compression*/
LV_IMAGE_COMPRESS_LZ4,
} lv_image_compress_t;
/**
* The first 8 bit is very important to distinguish the different source types.
* For more info see `lv_image_get_src_type()` in lv_img.c

View File

@ -10,6 +10,8 @@
#include "../../draw/lv_draw_image.h"
#include "../../draw/lv_draw_buf.h"
#include "../../stdlib/lv_string.h"
#include "../../stdlib/lv_sprintf.h"
#include "../../libs/rle/lv_rle.h"
/*********************
* DEFINES
@ -19,11 +21,25 @@
* TYPEDEFS
**********************/
/**
* Data format for compressed image data.
*/
typedef struct _lv_image_compressed_t {
uint32_t method: 4; /*Compression method, see `lv_image_compress_t`*/
uint32_t reserved : 28; /*Reserved to be used later*/
uint32_t compressed_size; /*Compressed data size in byte*/
uint32_t decompressed_size; /*Decompressed data size in byte*/
const uint8_t * data; /*Compressed data*/
} lv_image_compressed_t;
typedef struct {
lv_fs_file_t * f;
lv_color32_t * palette;
uint8_t * img_data;
lv_opa_t * opa;
uint8_t * decompressed;
lv_image_compressed_t compressed;
} decoder_data_t;
/**********************
@ -38,8 +54,11 @@ static lv_result_t decode_indexed(lv_image_decoder_t * decoder, lv_image_decoder
static lv_result_t decode_alpha_only(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc);
static lv_result_t decode_indexed_line(lv_color_format_t color_format, const lv_color32_t * palette, int32_t x,
int32_t w_px, const uint8_t * in, lv_color32_t * out);
static lv_result_t decode_compressed(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc);
static lv_fs_res_t fs_read_file_at(lv_fs_file_t * f, uint32_t pos, uint8_t * buff, uint32_t btr, uint32_t * br);
static lv_fs_res_t fs_read_file_at(lv_fs_file_t * f, uint32_t pos, void * buff, uint32_t btr, uint32_t * br);
static lv_result_t decompress_image(lv_image_decoder_dsc_t * dsc, const lv_image_compressed_t * compressed);
/**********************
* STATIC VARIABLES
@ -86,10 +105,8 @@ lv_result_t lv_bin_decoder_info(lv_image_decoder_t * decoder, const void * src,
lv_image_src_t src_type = lv_image_src_get_type(src);
if(src_type == LV_IMAGE_SRC_VARIABLE) {
header->w = ((lv_image_dsc_t *)src)->header.w;
header->h = ((lv_image_dsc_t *)src)->header.h;
header->cf = ((lv_image_dsc_t *)src)->header.cf;
header->stride = ((lv_image_dsc_t *)src)->header.stride;
lv_image_dsc_t * image = (lv_image_dsc_t *)src;
lv_memcpy(header, &image->header, sizeof(lv_image_header_t));
}
else if(src_type == LV_IMAGE_SRC_FILE) {
/*Support only "*.bin" files*/
@ -170,23 +187,26 @@ lv_result_t lv_bin_decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_d
return LV_RESULT_INVALID;
}
decoder_data->f = f;
decoder_data->f = f; /*Now free_decoder_data will take care of the file*/
lv_color_format_t cf = dsc->header.cf;
/*Palette for indexed image and whole image of A8 image are always loaded to RAM for simplicity*/
if(LV_COLOR_FORMAT_IS_INDEXED(cf)) {
if(dsc->header.flags & LV_IMAGE_FLAGS_COMPRESSED) {
res = decode_compressed(decoder, dsc);
}
else if(LV_COLOR_FORMAT_IS_INDEXED(cf)) {
/*Palette for indexed image and whole image of A8 image are always loaded to RAM for simplicity*/
res = decode_indexed(decoder, dsc);
}
else if(LV_COLOR_FORMAT_IS_ALPHA_ONLY(cf)) {
res = decode_alpha_only(decoder, dsc);
}
#if LV_BIN_DECODER_RAM_LOAD
else if(cf == LV_COLOR_FORMAT_ARGB8888 || cf == LV_COLOR_FORMAT_XRGB8888
|| cf == LV_COLOR_FORMAT_RGB888 || cf == LV_COLOR_FORMAT_RGB565) {
res = decode_rgb(decoder, dsc);
}
else if(cf == LV_COLOR_FORMAT_RGB565A8) {
else if(cf == LV_COLOR_FORMAT_ARGB8888 \
|| cf == LV_COLOR_FORMAT_XRGB8888 \
|| cf == LV_COLOR_FORMAT_RGB888 \
|| cf == LV_COLOR_FORMAT_RGB565 \
|| cf == LV_COLOR_FORMAT_RGB565A8) {
res = decode_rgb(decoder, dsc);
}
#else
@ -199,12 +219,16 @@ lv_result_t lv_bin_decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_d
else if(dsc->src_type == LV_IMAGE_SRC_VARIABLE) {
/*The variables should have valid data*/
lv_image_dsc_t * img_dsc = (lv_image_dsc_t *)dsc->src;
if(img_dsc->data == NULL) {
lv_image_dsc_t * image = (lv_image_dsc_t *)dsc->src;
if(image->data == NULL) {
return LV_RESULT_INVALID;
}
lv_color_format_t cf = img_dsc->header.cf;
lv_color_format_t cf = image->header.cf;
if(dsc->header.flags & LV_IMAGE_FLAGS_COMPRESSED) {
/*@todo*/
res = LV_RESULT_INVALID;
}
if(LV_COLOR_FORMAT_IS_INDEXED(cf)) {
/*Need decoder data to store converted image*/
decoder_data_t * decoder_data = get_decoder_data(dsc);
@ -404,6 +428,7 @@ static void free_decoder_data(lv_image_decoder_dsc_t * dsc)
}
lv_draw_buf_free(decoder_data->img_data);
lv_draw_buf_free(decoder_data->decompressed);
lv_free(decoder_data->palette);
lv_free(decoder_data);
dsc->user_data = NULL;
@ -423,7 +448,13 @@ static lv_result_t decode_indexed(lv_image_decoder_t * decoder, lv_image_decoder
const uint8_t * indexed_data = NULL;
uint32_t stride = dsc->header.stride;
if(dsc->src_type == LV_IMAGE_SRC_FILE) {
bool is_compressed = dsc->header.flags & LV_IMAGE_FLAGS_COMPRESSED;
if(is_compressed) {
uint8_t * data = decoder_data->decompressed;
palette = (lv_color32_t *)data;
indexed_data = data + palette_len;
}
else if(dsc->src_type == LV_IMAGE_SRC_FILE) {
/*read palette for indexed image*/
palette = lv_malloc(palette_len);
LV_ASSERT_MALLOC(palette);
@ -496,14 +527,14 @@ static lv_result_t decode_indexed(lv_image_decoder_t * decoder, lv_image_decoder
dsc->header.cf = LV_COLOR_FORMAT_ARGB8888;
dsc->img_data = img_data;
decoder_data->img_data = img_data; /*Free when decoder closes*/
if(dsc->src_type == LV_IMAGE_SRC_FILE) {
if(dsc->src_type == LV_IMAGE_SRC_FILE && !is_compressed) {
decoder_data->palette = (void *)palette; /*Free decoder data on close*/
lv_draw_buf_free((void *)indexed_data);
}
return LV_RESULT_OK;
exit_with_buf:
if(dsc->src_type == LV_IMAGE_SRC_FILE) {
if(dsc->src_type == LV_IMAGE_SRC_FILE && !is_compressed) {
lv_free((void *)palette);
lv_draw_buf_free((void *)indexed_data);
}
@ -570,7 +601,11 @@ static lv_result_t decode_alpha_only(lv_image_decoder_t * decoder, lv_image_deco
return LV_RESULT_INVALID;
}
if(dsc->src_type == LV_IMAGE_SRC_FILE) {
if(dsc->header.flags & LV_IMAGE_FLAGS_COMPRESSED) {
/*Copy from image data*/
lv_memcpy(img_data, decoder_data->decompressed, file_len);
}
else if(dsc->src_type == LV_IMAGE_SRC_FILE) {
res = fs_read_file_at(decoder_data->f, sizeof(lv_image_header_t), img_data, file_len, &rn);
if(res != LV_FS_RES_OK || rn != file_len) {
LV_LOG_WARN("Read header failed: %d", res);
@ -622,6 +657,87 @@ static lv_result_t decode_alpha_only(lv_image_decoder_t * decoder, lv_image_deco
return LV_RESULT_OK;
}
static lv_result_t decode_compressed(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc)
{
uint32_t rn;
uint32_t len;
uint32_t compressed_len;
uint8_t * file_buf;
decoder_data_t * decoder_data = get_decoder_data(dsc);
lv_fs_file_t * f = decoder_data->f;
lv_result_t res;
lv_image_compressed_t * compressed = &decoder_data->compressed;
lv_memzero(compressed, sizeof(lv_image_compressed_t));
if(lv_fs_seek(f, 0, LV_FS_SEEK_END) != LV_FS_RES_OK ||
lv_fs_tell(f, &compressed_len) != LV_FS_RES_OK) {
LV_LOG_WARN("Failed to get compressed file len");
return LV_RESULT_INVALID;
}
compressed_len -= sizeof(lv_image_header_t);
compressed_len -= 12;
/*Read compress header*/
len = 12;
res = fs_read_file_at(f, sizeof(lv_image_header_t), compressed, len, &rn);
if(res != LV_FS_RES_OK || rn != len) {
LV_LOG_WARN("Read compressed header failed: %d", res);
return LV_RESULT_INVALID;
}
if(compressed->compressed_size != compressed_len) {
LV_LOG_WARN("Compressed size mismatch: %" LV_PRIu32" != %" LV_PRIu32, compressed->compressed_size, compressed_len);
return LV_RESULT_INVALID;
}
file_buf = lv_malloc(compressed_len);
if(file_buf == NULL) {
LV_LOG_WARN("No memory for compressed file");
return LV_RESULT_INVALID;
}
/*Continue to read the compressed data following compression header*/
res = lv_fs_read(f, file_buf, compressed_len, &rn);
if(res != LV_FS_RES_OK || rn != compressed_len) {
LV_LOG_WARN("Read compressed file failed: %d", res);
lv_free(file_buf);
return LV_RESULT_INVALID;
}
/*Decompress the image*/
compressed->data = file_buf;
res = decompress_image(dsc, compressed);
compressed->data = NULL; /*No need to store the data any more*/
lv_free(file_buf);
if(res != LV_RESULT_OK) {
LV_LOG_WARN("Decompress failed");
return LV_RESULT_INVALID;
}
/*Depends on the cf, need to further decode image like an C-array image*/
lv_image_dsc_t * image = (lv_image_dsc_t *)dsc->src;
if(image->data == NULL) {
return LV_RESULT_INVALID;
}
lv_color_format_t cf = dsc->header.cf;
if(LV_COLOR_FORMAT_IS_INDEXED(cf)) {
res = decode_indexed(decoder, dsc);
}
else if(LV_COLOR_FORMAT_IS_ALPHA_ONLY(cf)) {
res = decode_alpha_only(decoder, dsc);
}
else {
/*The decompressed data is the original image data.*/
dsc->img_data = decoder_data->decompressed;
res = LV_RESULT_OK;
}
return res;
}
static lv_result_t decode_indexed_line(lv_color_format_t color_format, const lv_color32_t * palette, int32_t x,
int32_t w_px, const uint8_t * in, lv_color32_t * out)
{
@ -670,7 +786,7 @@ static lv_result_t decode_indexed_line(lv_color_format_t color_format, const lv_
return LV_RESULT_OK;
}
static lv_fs_res_t fs_read_file_at(lv_fs_file_t * f, uint32_t pos, uint8_t * buff, uint32_t btr, uint32_t * br)
static lv_fs_res_t fs_read_file_at(lv_fs_file_t * f, uint32_t pos, void * buff, uint32_t btr, uint32_t * br)
{
lv_fs_res_t res;
if(br) *br = 0;
@ -687,3 +803,50 @@ static lv_fs_res_t fs_read_file_at(lv_fs_file_t * f, uint32_t pos, uint8_t * buf
return LV_FS_RES_OK;
}
static lv_result_t decompress_image(lv_image_decoder_dsc_t * dsc, const lv_image_compressed_t * compressed)
{
/*Need to store decompressed data to decoder to free on close*/
decoder_data_t * decoder_data = get_decoder_data(dsc);
if(decoder_data == NULL) {
return LV_RESULT_INVALID;
}
uint8_t * decompressed;
uint32_t input_len = compressed->compressed_size;
uint32_t out_len = compressed->decompressed_size;
/*Note, stride must match.*/
decompressed = lv_draw_buf_malloc(out_len, dsc->header.cf);
if(decompressed == NULL) {
LV_LOG_WARN("No memory for decompressed image, input: %" LV_PRIu32 ", output: %" LV_PRIu32, input_len, out_len);
return LV_RESULT_INVALID;
}
if(compressed->method == LV_IMAGE_COMPRESS_RLE) {
#if LV_USE_RLE
/*Compress always happen on byte*/
uint32_t pixel_byte;
if(dsc->header.cf == LV_COLOR_FORMAT_RGB565A8)
pixel_byte = 2;
else
pixel_byte = (lv_color_format_get_bpp(dsc->header.cf) + 7) >> 3;
const uint8_t * input = compressed->data;
uint8_t * output = decompressed;
uint32_t len;
len = lv_rle_decompress(input, input_len, output, out_len, pixel_byte);
if(len != compressed->decompressed_size) {
LV_LOG_WARN("Decompress failed: %" LV_PRIu32 ", got: %" LV_PRIu32, out_len, len);
lv_draw_buf_free(decompressed);
return LV_RESULT_INVALID;
}
#else
LV_LOG_WARN("RLE decompress is not enabled");
lv_draw_buf_free(decompressed);
return LV_RESULT_INVALID;
#endif
}
decoder_data->decompressed = decompressed; /*Free on decoder close*/
return LV_RESULT_OK;
}

99
src/libs/rle/lv_rle.c Normal file
View File

@ -0,0 +1,99 @@
/**
* @file lv_rle.c
*/
/*********************
* INCLUDES
*********************/
#include "../../stdlib/lv_string.h"
#include "lv_rle.h"
#if LV_USE_RLE
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
uint32_t lv_rle_decompress(const uint8_t * input,
uint32_t input_buff_len, uint8_t * output,
uint32_t output_buff_len, uint8_t blk_size)
{
uint32_t ctrl_byte;
uint32_t rd_len = 0;
uint32_t wr_len = 0;
while(rd_len < input_buff_len) {
ctrl_byte = input[0];
rd_len++;
input++;
if(rd_len > input_buff_len)
return 0;
if(ctrl_byte & 0x80) {
/* copy directly from input to output */
uint32_t bytes = blk_size * (ctrl_byte & 0x7f);
rd_len += bytes;
if(rd_len > input_buff_len)
return 0;
wr_len += bytes;
if(wr_len > output_buff_len)
return 0;
lv_memcpy(output, input, bytes);
output += bytes;
input += bytes;
}
else {
rd_len += blk_size;
if(rd_len > input_buff_len)
return 0;
wr_len += blk_size * ctrl_byte;
if(wr_len > output_buff_len)
return 0;
if(blk_size == 1) {
/* optimize the most common case. */
lv_memset(output, input[0], ctrl_byte);
output += ctrl_byte;
}
else {
for(uint32_t i = 0; i < ctrl_byte; i++) {
lv_memcpy(output, input, blk_size);
output += blk_size;
}
}
input += blk_size;
}
}
return wr_len;
}
/**********************
* STATIC FUNCTIONS
**********************/
#endif /*LV_USE_RLE*/

46
src/libs/rle/lv_rle.h Normal file
View File

@ -0,0 +1,46 @@
/**
* @file lv_rle.h
*
*/
#ifndef LV_RLE_H
#define LV_RLE_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../../../lvgl.h"
#if LV_USE_RLE
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
uint32_t lv_rle_decompress(const uint8_t * input,
uint32_t input_buff_len, uint8_t * output,
uint32_t output_buff_len, uint8_t blk_size);
/**********************
* MACROS
**********************/
#endif /*LV_USE_RLE*/
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /*LV_RLE_H*/

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

View File

@ -159,6 +159,7 @@ void test_image_built_in_decode_rotate_and_recolor(void)
void test_image_rle_decode(void)
{
#if LV_USE_RLE
img_create("rleA1", "A:src/test_files/binimages/cogwheel.A1.rle", false, false);
img_create("rleA2", "A:src/test_files/binimages/cogwheel.A2.rle", false, false);
img_create("rleA4", "A:src/test_files/binimages/cogwheel.A4.rle", false, false);
@ -174,10 +175,12 @@ void test_image_rle_decode(void)
img_create("rleARGB8888", "A:src/test_files/binimages/cogwheel.ARGB8888.rle", false, false);
TEST_ASSERT_EQUAL_SCREENSHOT("draw/image_format_rle.png");
#endif
}
void test_image_rle_decode_rotate(void)
{
#if LV_USE_RLE
img_create("rleA1", "A:src/test_files/binimages/cogwheel.A1.rle", true, false);
img_create("rleA2", "A:src/test_files/binimages/cogwheel.A2.rle", true, false);
img_create("rleA4", "A:src/test_files/binimages/cogwheel.A4.rle", true, false);
@ -193,10 +196,12 @@ void test_image_rle_decode_rotate(void)
img_create("rleARGB8888", "A:src/test_files/binimages/cogwheel.ARGB8888.rle", true, false);
TEST_ASSERT_EQUAL_SCREENSHOT("draw/image_format_rle_rotate.png");
#endif
}
void test_image_rle_decode_rotate_recolor(void)
{
#if LV_USE_RLE
img_create("rleA1", "A:src/test_files/binimages/cogwheel.A1.rle", true, true);
img_create("rleA2", "A:src/test_files/binimages/cogwheel.A2.rle", true, true);
img_create("rleA4", "A:src/test_files/binimages/cogwheel.A4.rle", true, true);
@ -212,6 +217,70 @@ void test_image_rle_decode_rotate_recolor(void)
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
}
void test_image_rle_compressed_decode(void)
{
#if LV_USE_RLE
img_create("rleA1", "A:src/test_files/rle_compressed/cogwheel.A1.bin", false, false);
img_create("rleA2", "A:src/test_files/rle_compressed/cogwheel.A2.bin", false, false);
img_create("rleA4", "A:src/test_files/rle_compressed/cogwheel.A4.bin", false, false);
img_create("rleA8", "A:src/test_files/rle_compressed/cogwheel.A8.bin", false, false);
img_create("rleI1", "A:src/test_files/rle_compressed/cogwheel.I1.bin", false, false);
img_create("rleI2", "A:src/test_files/rle_compressed/cogwheel.I2.bin", false, false);
img_create("rleI4", "A:src/test_files/rle_compressed/cogwheel.I4.bin", false, false);
img_create("rleI8", "A:src/test_files/rle_compressed/cogwheel.I8.bin", false, false);
img_create("rleRGB565A8", "A:src/test_files/rle_compressed/cogwheel.RGB565A8.bin", false, false);
img_create("rleRGB565", "A:src/test_files/rle_compressed/cogwheel.RGB565.bin", false, false);
img_create("rleRGB888", "A:src/test_files/rle_compressed/cogwheel.RGB888.bin", false, false);
img_create("rleXRGB8888", "A:src/test_files/rle_compressed/cogwheel.XRGB8888.bin", false, false);
img_create("rleARGB8888", "A:src/test_files/rle_compressed/cogwheel.ARGB8888.bin", false, false);
TEST_ASSERT_EQUAL_SCREENSHOT("draw/image_format_rle_compressed.png");
#endif
}
void test_image_rle_compressed_decode_rotate(void)
{
#if LV_USE_RLE
img_create("rleA1", "A:src/test_files/rle_compressed/cogwheel.A1.bin", true, false);
img_create("rleA2", "A:src/test_files/rle_compressed/cogwheel.A2.bin", true, false);
img_create("rleA4", "A:src/test_files/rle_compressed/cogwheel.A4.bin", true, false);
img_create("rleA8", "A:src/test_files/rle_compressed/cogwheel.A8.bin", true, false);
img_create("rleI1", "A:src/test_files/rle_compressed/cogwheel.I1.bin", true, false);
img_create("rleI2", "A:src/test_files/rle_compressed/cogwheel.I2.bin", true, false);
img_create("rleI4", "A:src/test_files/rle_compressed/cogwheel.I4.bin", true, false);
img_create("rleI8", "A:src/test_files/rle_compressed/cogwheel.I8.bin", true, false);
img_create("rleRGB565A8", "A:src/test_files/rle_compressed/cogwheel.RGB565A8.bin", true, false);
img_create("rleRGB565", "A:src/test_files/rle_compressed/cogwheel.RGB565.bin", true, false);
img_create("rleRGB888", "A:src/test_files/rle_compressed/cogwheel.RGB888.bin", true, false);
img_create("rleXRGB8888", "A:src/test_files/rle_compressed/cogwheel.XRGB8888.bin", true, false);
img_create("rleARGB8888", "A:src/test_files/rle_compressed/cogwheel.ARGB8888.bin", true, false);
TEST_ASSERT_EQUAL_SCREENSHOT("draw/image_format_rle_compressed_rotate.png");
#endif
}
void test_image_rle_compressed_decode_rotate_recolor(void)
{
#if LV_USE_RLE
img_create("rleA1", "A:src/test_files/rle_compressed/cogwheel.A1.bin", true, true);
img_create("rleA2", "A:src/test_files/rle_compressed/cogwheel.A2.bin", true, true);
img_create("rleA4", "A:src/test_files/rle_compressed/cogwheel.A4.bin", true, true);
img_create("rleA8", "A:src/test_files/rle_compressed/cogwheel.A8.bin", true, true);
img_create("rleI1", "A:src/test_files/rle_compressed/cogwheel.I1.bin", true, true);
img_create("rleI2", "A:src/test_files/rle_compressed/cogwheel.I2.bin", true, true);
img_create("rleI4", "A:src/test_files/rle_compressed/cogwheel.I4.bin", true, true);
img_create("rleI8", "A:src/test_files/rle_compressed/cogwheel.I8.bin", true, true);
img_create("rleRGB565A8", "A:src/test_files/rle_compressed/cogwheel.RGB565A8.bin", true, true);
img_create("rleRGB565", "A:src/test_files/rle_compressed/cogwheel.RGB565.bin", true, true);
img_create("rleRGB888", "A:src/test_files/rle_compressed/cogwheel.RGB888.bin", true, true);
img_create("rleXRGB8888", "A:src/test_files/rle_compressed/cogwheel.XRGB8888.bin", true, true);
img_create("rleARGB8888", "A:src/test_files/rle_compressed/cogwheel.ARGB8888.bin", true, true);
TEST_ASSERT_EQUAL_SCREENSHOT("draw/image_format_rle_compressed_rotate_recolor.png");
#endif
}
#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.