1
0
mirror of https://github.com/lvgl/lvgl.git synced 2025-01-28 07:03:00 +08:00

feat(image): support C array type of alpha-only image in the built-in decoder (#4797)

Signed-off-by: Xu Xingliang <xuxingliang@xiaomi.com>
This commit is contained in:
Neo Xu 2023-11-14 01:14:36 +08:00 committed by GitHub
parent 56d707a869
commit 8e076cc230
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 59 additions and 20 deletions

View File

@ -71,7 +71,7 @@ void _lv_image_decoder_init(void)
decoder = lv_image_decoder_create();
LV_ASSERT_MALLOC(decoder);
if(decoder == NULL) {
LV_LOG_WARN("out of memory");
LV_LOG_WARN("Out of memory");
return;
}
@ -143,7 +143,7 @@ lv_result_t lv_image_decoder_open(lv_image_decoder_dsc_t * dsc, const void * src
dsc->src = lv_malloc(fnlen + 1);
LV_ASSERT_MALLOC(dsc->src);
if(dsc->src == NULL) {
LV_LOG_WARN("out of memory");
LV_LOG_WARN("Out of memory");
return LV_RESULT_INVALID;
}
lv_strcpy((char *)dsc->src, src);
@ -327,7 +327,7 @@ lv_result_t lv_image_decoder_built_in_info(lv_image_decoder_t * decoder, const v
res = lv_fs_read(&f, header, sizeof(lv_image_header_t), &rn);
lv_fs_close(&f);
if(res != LV_FS_RES_OK || rn != sizeof(lv_image_header_t)) {
LV_LOG_WARN("Image get info get read file header");
LV_LOG_WARN("Read file header failed: %d", res);
return LV_RESULT_INVALID;
}
}
@ -378,7 +378,7 @@ lv_result_t lv_image_decoder_built_in_open(lv_image_decoder_t * decoder, lv_imag
lv_fs_res_t res = lv_fs_open(f, dsc->src, LV_FS_MODE_RD);
if(res != LV_FS_RES_OK) {
LV_LOG_WARN("open file failed");
LV_LOG_WARN("Open file failed: %d", res);
lv_free(f);
free_decoder_data(dsc);
return LV_RESULT_INVALID;
@ -456,6 +456,15 @@ lv_result_t lv_image_decoder_built_in_open(lv_image_decoder_t * decoder, lv_imag
decode_indexed_line(cf, dsc->palette, 0, y, img_dsc->header.w, in, out);
}
}
else if(LV_COLOR_FORMAT_IS_ALPHA_ONLY(cf)) {
/*Alpha only image will need decoder data to store pointer to decoded image, to free it when decoder closes*/
lv_image_decoder_built_in_data_t * decoder_data = get_decoder_data(dsc);
if(decoder_data == NULL) {
return LV_RESULT_INVALID;
}
return decode_alpha_only(decoder, dsc);
}
else {
/*In case of uncompressed formats the image stored in the ROM/RAM.
*So simply give its pointer*/
@ -603,7 +612,7 @@ static lv_image_decoder_built_in_data_t * get_decoder_data(lv_image_decoder_dsc_
data = lv_malloc_zeroed(sizeof(lv_image_decoder_built_in_data_t));
LV_ASSERT_MALLOC(data);
if(data == NULL) {
LV_LOG_ERROR("out of memory");
LV_LOG_ERROR("Out of memory");
return NULL;
}
@ -643,13 +652,13 @@ static lv_result_t decode_indexed(lv_image_decoder_t * decoder, lv_image_decoder
lv_color32_t * palette = lv_malloc(palette_len);
LV_ASSERT_MALLOC(palette);
if(palette == NULL) {
LV_LOG_ERROR("out of memory");
LV_LOG_ERROR("Out of memory");
return LV_RESULT_INVALID;
}
res = fs_read_file_at(f, sizeof(lv_image_header_t), (uint8_t *)palette, palette_len, &rn);
if(res != LV_FS_RES_OK || rn != palette_len) {
LV_LOG_WARN("read palette failed");
LV_LOG_WARN("Read palette failed: %d", res);
lv_free(palette);
return LV_RESULT_INVALID;
}
@ -662,14 +671,14 @@ static lv_result_t decode_indexed(lv_image_decoder_t * decoder, lv_image_decoder
uint8_t * file_buf = lv_draw_buf_malloc(stride * dsc->header.h, cf);
LV_ASSERT_MALLOC(file_buf);
if(file_buf == NULL) {
LV_LOG_ERROR("draw buffer alloc failed");
LV_LOG_ERROR("Draw buffer alloc failed");
return LV_RESULT_INVALID;
}
uint32_t data_len = 0;
if(lv_fs_seek(f, 0, LV_FS_SEEK_END) != LV_FS_RES_OK ||
lv_fs_tell(f, &data_len) != LV_FS_RES_OK) {
LV_LOG_WARN("failed to get file to size");
LV_LOG_WARN("Failed to get file to size");
goto exit_with_buf;
}
@ -677,7 +686,7 @@ static lv_result_t decode_indexed(lv_image_decoder_t * decoder, lv_image_decoder
data_len -= data_offset;
res = fs_read_file_at(f, data_offset, (uint8_t *)file_buf, data_len, &rn);
if(res != LV_FS_RES_OK || rn != data_len) {
LV_LOG_WARN("read palette failed");
LV_LOG_WARN("Read indexed image failed: %d", res);
goto exit_with_buf;
}
@ -685,7 +694,7 @@ static lv_result_t decode_indexed(lv_image_decoder_t * decoder, lv_image_decoder
stride = lv_draw_buf_width_to_stride(dsc->header.w, LV_COLOR_FORMAT_ARGB8888);
uint8_t * img_data = lv_draw_buf_malloc(stride * dsc->header.h, cf);
if(img_data == NULL) {
LV_LOG_ERROR("no memory for indexed image");
LV_LOG_ERROR("No memory for indexed image");
goto exit_with_buf;
}
@ -733,14 +742,14 @@ static lv_result_t decode_rgb(lv_image_decoder_t * decoder, lv_image_decoder_dsc
uint8_t * img_data = lv_draw_buf_malloc(len, cf);
LV_ASSERT_MALLOC(img_data);
if(img_data == NULL) {
LV_LOG_ERROR("no memory for rgb file read");
LV_LOG_ERROR("No memory for rgb file read");
return LV_RESULT_INVALID;
}
uint32_t rn;
res = fs_read_file_at(f, sizeof(lv_image_header_t), img_data, len, &rn);
if(res != LV_FS_RES_OK || rn != len) {
LV_LOG_WARN("read rgb file failed");
LV_LOG_WARN("Read rgb file failed: %d", res);
lv_draw_buf_free(img_data);
return LV_RESULT_INVALID;
}
@ -766,15 +775,21 @@ static lv_result_t decode_alpha_only(lv_image_decoder_t * decoder, lv_image_deco
LV_ASSERT_MALLOC(img_data);
if(img_data == NULL) {
LV_LOG_ERROR("out of memory");
LV_LOG_ERROR("Out of memory");
return LV_RESULT_INVALID;
}
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("Built-in image decoder can't read the palette");
lv_draw_buf_free(img_data);
return LV_RESULT_INVALID;
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);
lv_draw_buf_free(img_data);
return LV_RESULT_INVALID;
}
}
else if(dsc->src_type == LV_IMAGE_SRC_VARIABLE) {
/*Copy from image data*/
lv_memcpy(img_data, ((lv_image_dsc_t *)dsc->src)->data, file_len);
}
if(dsc->header.cf != LV_COLOR_FORMAT_A8) {
@ -784,7 +799,22 @@ static lv_result_t decode_alpha_only(lv_image_decoder_t * decoder, lv_image_deco
uint8_t mask = (1 << bpp) - 1;
uint8_t shift = 0;
for(uint32_t i = 0; i < buf_len; i++) {
*out = ((*in >> shift) & mask) << (8 - bpp);
/**
* Rounding error:
* Take bpp = 4 as example, alpha value of 0x0 to 0x0F should be
* mapped to 0x00 to 0xFF, thus the equation should be below Equation 3.
*
* But it involves division and multiplication, which is slow. So, if
* we ignore the rounding errors, Equation1, 2 could be faster. But it
* will either has error when alpha is 0xff or 0x00.
*
* We use Equation 3 here for maximum accuracy.
*
* Equation 1: *out = ((*in >> shift) & mask) << (8 - bpp);
* Equation 2: *out = ((((*in >> shift) & mask) + 1) << (8 - bpp)) - 1;
* Equation 3: *out = ((*in >> shift) & mask) * 255 / ((1L << bpp) - 1) ;
*/
*out = ((*in >> shift) & mask) * 255L / ((1L << bpp) - 1) ;
shift += bpp;
if(shift >= 8) {
shift = 0;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 103 KiB

After

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 95 KiB

After

Width:  |  Height:  |  Size: 112 KiB

View File

@ -159,6 +159,9 @@ void test_image_built_in_decode_rotate_and_recolor(void)
void test_image_rle_decode(void)
{
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);
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);
@ -175,6 +178,9 @@ void test_image_rle_decode(void)
void test_image_rle_decode_rotate(void)
{
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);
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);
@ -191,6 +197,9 @@ void test_image_rle_decode_rotate(void)
void test_image_rle_decode_rotate_recolor(void)
{
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);
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);