mirror of
https://github.com/lvgl/lvgl.git
synced 2026-05-28 13:36:27 +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)
|
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));
|
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)
|
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,
|
.stride_align = LV_DRAW_BUF_STRIDE_ALIGN != 1,
|
||||||
.premultiply = false,
|
.premultiply = false,
|
||||||
.no_cache = false,
|
.no_cache = false,
|
||||||
|
.use_indexed = false,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*Make a copy of args */
|
/*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 stride_align; /*Whether stride should be aligned*/
|
||||||
bool premultiply; /*Whether image should be premultiplied or not after decoding*/
|
bool premultiply; /*Whether image should be premultiplied or not after decoding*/
|
||||||
bool no_cache; /*Whether this image should be kept out of cache*/
|
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;
|
} lv_image_decoder_args_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -320,9 +320,6 @@ bool lv_vg_lite_is_src_cf_supported(lv_color_format_t cf)
|
|||||||
switch(cf) {
|
switch(cf) {
|
||||||
case LV_COLOR_FORMAT_A4:
|
case LV_COLOR_FORMAT_A4:
|
||||||
case LV_COLOR_FORMAT_A8:
|
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_I8:
|
||||||
case LV_COLOR_FORMAT_RGB565:
|
case LV_COLOR_FORMAT_RGB565:
|
||||||
case LV_COLOR_FORMAT_RGB565A8:
|
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));
|
lv_memzero(&args, sizeof(lv_image_decoder_args_t));
|
||||||
args.premultiply = !lv_vg_lite_support_blend_normal();
|
args.premultiply = !lv_vg_lite_support_blend_normal();
|
||||||
args.stride_align = true;
|
args.stride_align = true;
|
||||||
|
args.use_indexed = true;
|
||||||
|
|
||||||
lv_result_t res = lv_image_decoder_open(decoder_dsc, src, &args);
|
lv_result_t res = lv_image_decoder_open(decoder_dsc, src, &args);
|
||||||
if(res != LV_RESULT_OK) {
|
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 decoder_data_t * get_decoder_data(lv_image_decoder_dsc_t * dsc);
|
||||||
static void free_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 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
|
#if LV_BIN_DECODER_RAM_LOAD
|
||||||
static lv_result_t decode_rgb(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc);
|
static lv_result_t decode_rgb(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc);
|
||||||
#endif
|
#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);
|
res = decode_compressed(decoder, dsc);
|
||||||
}
|
}
|
||||||
else if(LV_COLOR_FORMAT_IS_INDEXED(cf)) {
|
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*/
|
if(dsc->args.use_indexed) {
|
||||||
res = decode_indexed(decoder, dsc);
|
/*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)) {
|
else if(LV_COLOR_FORMAT_IS_ALPHA_ONLY(cf)) {
|
||||||
res = decode_alpha_only(decoder, dsc);
|
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;
|
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)) {
|
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*/
|
/*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
|
#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
|
#if LV_BIN_DECODER_RAM_LOAD
|
||||||
static lv_result_t decode_rgb(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc)
|
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;
|
lv_color_format_t cf = dsc->header.cf;
|
||||||
if(LV_COLOR_FORMAT_IS_INDEXED(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)) {
|
else if(LV_COLOR_FORMAT_IS_ALPHA_ONLY(cf)) {
|
||||||
res = decode_alpha_only(decoder, dsc);
|
res = decode_alpha_only(decoder, dsc);
|
||||||
|
|||||||
Reference in New Issue
Block a user