diff --git a/src/draw/lv_draw_buf.h b/src/draw/lv_draw_buf.h index 5d2ee4bc6f..08cefe81d0 100644 --- a/src/draw/lv_draw_buf.h +++ b/src/draw/lv_draw_buf.h @@ -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) diff --git a/src/draw/lv_image_decoder.c b/src/draw/lv_image_decoder.c index e24c2e7e86..fe0e7bee64 100644 --- a/src/draw/lv_image_decoder.c +++ b/src/draw/lv_image_decoder.c @@ -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 */ diff --git a/src/draw/lv_image_decoder.h b/src/draw/lv_image_decoder.h index b5f77e77a3..5d4235beeb 100644 --- a/src/draw/lv_image_decoder.h +++ b/src/draw/lv_image_decoder.h @@ -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; /** diff --git a/src/draw/vg_lite/lv_vg_lite_utils.c b/src/draw/vg_lite/lv_vg_lite_utils.c index 5f2c415fb4..b60d9997e7 100644 --- a/src/draw/vg_lite/lv_vg_lite_utils.c +++ b/src/draw/vg_lite/lv_vg_lite_utils.c @@ -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) { diff --git a/src/libs/bin_decoder/lv_bin_decoder.c b/src/libs/bin_decoder/lv_bin_decoder.c index 787634ccd8..b5974fd9ef 100644 --- a/src/libs/bin_decoder/lv_bin_decoder.c +++ b/src/libs/bin_decoder/lv_bin_decoder.c @@ -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);