mirror of
https://github.com/lvgl/lvgl.git
synced 2026-05-23 07:46:36 +08:00
feat(decoder): add indexed image support for GPU (#5087)
Signed-off-by: Xu Xingliang <xuxingliang@xiaomi.com>
This commit is contained in:
@@ -238,6 +238,7 @@ static inline bool lv_draw_buf_has_flag(lv_draw_buf_t * draw_buf, lv_image_flags
|
||||
static inline void lv_draw_buf_from_image(lv_draw_buf_t * buf, const lv_image_dsc_t * img)
|
||||
{
|
||||
lv_memcpy(buf, img, sizeof(lv_image_dsc_t));
|
||||
buf->unaligned_data = buf->data;
|
||||
}
|
||||
|
||||
static inline void lv_draw_buf_to_image(const lv_draw_buf_t * buf, lv_image_dsc_t * img)
|
||||
|
||||
@@ -139,6 +139,7 @@ lv_result_t lv_image_decoder_open(lv_image_decoder_dsc_t * dsc, const void * src
|
||||
.stride_align = LV_DRAW_BUF_STRIDE_ALIGN != 1,
|
||||
.premultiply = false,
|
||||
.no_cache = false,
|
||||
.use_indexed = false,
|
||||
};
|
||||
|
||||
/*Make a copy of args */
|
||||
|
||||
@@ -63,6 +63,7 @@ typedef struct _lv_image_decoder_args_t {
|
||||
bool stride_align; /*Whether stride should be aligned*/
|
||||
bool premultiply; /*Whether image should be premultiplied or not after decoding*/
|
||||
bool no_cache; /*Whether this image should be kept out of cache*/
|
||||
bool use_indexed; /*Decoded indexed image as is. Convert to ARGB8888 if false.*/
|
||||
} lv_image_decoder_args_t;
|
||||
|
||||
/**
|
||||
|
||||
@@ -320,9 +320,6 @@ bool lv_vg_lite_is_src_cf_supported(lv_color_format_t cf)
|
||||
switch(cf) {
|
||||
case LV_COLOR_FORMAT_A4:
|
||||
case LV_COLOR_FORMAT_A8:
|
||||
case LV_COLOR_FORMAT_I1:
|
||||
case LV_COLOR_FORMAT_I2:
|
||||
case LV_COLOR_FORMAT_I4:
|
||||
case LV_COLOR_FORMAT_I8:
|
||||
case LV_COLOR_FORMAT_RGB565:
|
||||
case LV_COLOR_FORMAT_RGB565A8:
|
||||
@@ -581,6 +578,7 @@ bool lv_vg_lite_buffer_open_image(vg_lite_buffer_t * buffer, lv_image_decoder_ds
|
||||
lv_memzero(&args, sizeof(lv_image_decoder_args_t));
|
||||
args.premultiply = !lv_vg_lite_support_blend_normal();
|
||||
args.stride_align = true;
|
||||
args.use_indexed = true;
|
||||
|
||||
lv_result_t res = lv_image_decoder_open(decoder_dsc, src, &args);
|
||||
if(res != LV_RESULT_OK) {
|
||||
|
||||
@@ -58,6 +58,7 @@ typedef struct {
|
||||
static decoder_data_t * get_decoder_data(lv_image_decoder_dsc_t * dsc);
|
||||
static void free_decoder_data(lv_image_decoder_dsc_t * dsc);
|
||||
static lv_result_t decode_indexed(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc);
|
||||
static lv_result_t load_indexed(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc);
|
||||
#if LV_BIN_DECODER_RAM_LOAD
|
||||
static lv_result_t decode_rgb(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc);
|
||||
#endif
|
||||
@@ -209,8 +210,13 @@ lv_result_t lv_bin_decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_d
|
||||
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);
|
||||
if(dsc->args.use_indexed) {
|
||||
/*Palette for indexed image and whole image of A8 image are always loaded to RAM for simplicity*/
|
||||
res = load_indexed(decoder, dsc);
|
||||
}
|
||||
else {
|
||||
res = decode_indexed(decoder, dsc);
|
||||
}
|
||||
}
|
||||
else if(LV_COLOR_FORMAT_IS_ALPHA_ONLY(cf)) {
|
||||
res = decode_alpha_only(decoder, dsc);
|
||||
@@ -249,7 +255,13 @@ lv_result_t lv_bin_decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_d
|
||||
return LV_RESULT_INVALID;
|
||||
}
|
||||
|
||||
res = decode_indexed(decoder, dsc);
|
||||
if(dsc->args.use_indexed) {
|
||||
/*Palette for indexed image and whole image of A8 image are always loaded to RAM for simplicity*/
|
||||
res = load_indexed(decoder, dsc);
|
||||
}
|
||||
else {
|
||||
res = decode_indexed(decoder, dsc);
|
||||
}
|
||||
}
|
||||
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*/
|
||||
@@ -640,6 +652,87 @@ exit_with_buf:
|
||||
#endif
|
||||
}
|
||||
|
||||
static lv_result_t load_indexed(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc)
|
||||
{
|
||||
#if LV_BIN_DECODER_RAM_LOAD == 0
|
||||
LV_UNUSED(decoder); /*Unused*/
|
||||
LV_UNUSED(dsc); /*Unused*/
|
||||
LV_LOG_ERROR("LV_BIN_DECODER_RAM_LOAD is disabled");
|
||||
return LV_RESULT_INVALID;
|
||||
#else
|
||||
|
||||
LV_UNUSED(decoder); /*Unused*/
|
||||
|
||||
lv_result_t res;
|
||||
uint32_t rn;
|
||||
decoder_data_t * decoder_data = dsc->user_data;
|
||||
|
||||
if(dsc->header.flags & LV_IMAGE_FLAGS_COMPRESSED) {
|
||||
/*The decompressed image is already loaded to RAM*/
|
||||
dsc->decoded = decoder_data->decompressed;
|
||||
return LV_RESULT_OK;
|
||||
}
|
||||
|
||||
if(dsc->src_type == LV_IMAGE_SRC_VARIABLE) {
|
||||
lv_image_dsc_t * image = (lv_image_dsc_t *)dsc->src;
|
||||
lv_draw_buf_t * decoded = &decoder_data->c_array;
|
||||
dsc->decoded = decoded;
|
||||
lv_draw_buf_from_image(decoded, image);
|
||||
|
||||
if(decoded->header.stride == 0) {
|
||||
/*Use the auto calculated value from decoder_info callback*/
|
||||
decoded->header.stride = dsc->header.stride;
|
||||
}
|
||||
|
||||
return LV_RESULT_OK;
|
||||
}
|
||||
|
||||
if(dsc->src_type == LV_IMAGE_SRC_FILE) {
|
||||
lv_color_format_t cf = dsc->header.cf;
|
||||
lv_fs_file_t * f = decoder_data->f;
|
||||
lv_draw_buf_t * decoded = lv_draw_buf_create(dsc->header.w, dsc->header.h, cf, dsc->header.stride);
|
||||
if(decoded == NULL) {
|
||||
LV_LOG_ERROR("Draw buffer alloc failed");
|
||||
return LV_RESULT_INVALID;
|
||||
}
|
||||
|
||||
uint8_t * data = decoded->data;
|
||||
uint32_t palette_len = sizeof(lv_color32_t) * LV_COLOR_INDEXED_PALETTE_SIZE(cf);
|
||||
res = fs_read_file_at(f, sizeof(lv_image_header_t), data, palette_len, &rn);
|
||||
if(res != LV_FS_RES_OK || rn != palette_len) {
|
||||
LV_LOG_WARN("Read palette failed: %d", res);
|
||||
lv_draw_buf_destroy(decoded);
|
||||
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_draw_buf_destroy(decoded);
|
||||
return LV_RESULT_INVALID;
|
||||
}
|
||||
|
||||
uint32_t data_offset = sizeof(lv_image_header_t) + palette_len;
|
||||
data_len -= data_offset;
|
||||
data += palette_len;
|
||||
res = fs_read_file_at(f, data_offset, data, data_len, &rn);
|
||||
if(res != LV_FS_RES_OK || rn != data_len) {
|
||||
LV_LOG_WARN("Read indexed image failed: %d", res);
|
||||
lv_draw_buf_destroy(decoded);
|
||||
return LV_RESULT_INVALID;
|
||||
}
|
||||
|
||||
decoder_data->decoded = decoded;
|
||||
dsc->decoded = decoded;
|
||||
return LV_RESULT_OK;
|
||||
}
|
||||
|
||||
LV_LOG_ERROR("Unknown src type: %d", dsc->src_type);
|
||||
return LV_RESULT_INVALID;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if LV_BIN_DECODER_RAM_LOAD
|
||||
static lv_result_t decode_rgb(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc)
|
||||
{
|
||||
@@ -853,7 +946,8 @@ static lv_result_t decode_compressed(lv_image_decoder_t * decoder, lv_image_deco
|
||||
|
||||
lv_color_format_t cf = dsc->header.cf;
|
||||
if(LV_COLOR_FORMAT_IS_INDEXED(cf)) {
|
||||
res = decode_indexed(decoder, dsc);
|
||||
if(dsc->args.use_indexed) res = load_indexed(decoder, dsc);
|
||||
else res = decode_indexed(decoder, dsc);
|
||||
}
|
||||
else if(LV_COLOR_FORMAT_IS_ALPHA_ONLY(cf)) {
|
||||
res = decode_alpha_only(decoder, dsc);
|
||||
|
||||
Reference in New Issue
Block a user