From d26eac8f3a6cbddf12d13c78fd1a51ffec4a9410 Mon Sep 17 00:00:00 2001 From: Benign X <1341398182@qq.com> Date: Mon, 22 Jan 2024 19:44:14 +0800 Subject: [PATCH] feat(decoder): add image header cache (#5407) --- .devcontainer/__lv_conf.h__ | 4 + Kconfig | 12 ++ env_support/cmsis-pack/lv_conf_cmsis.h | 4 + lv_conf_template.h | 4 + src/core/lv_global.h | 4 + src/draw/lv_image_decoder.c | 248 ++++++++++++++-------- src/draw/lv_image_decoder.h | 13 +- src/draw/sw/lv_draw_sw_arc.c | 6 +- src/draw/sw/lv_draw_sw_vector.c | 2 +- src/draw/vg_lite/lv_draw_vg_lite_img.c | 2 +- src/draw/vg_lite/lv_vg_lite_decoder.c | 13 +- src/libs/bin_decoder/lv_bin_decoder.c | 10 +- src/libs/bin_decoder/lv_bin_decoder.h | 3 +- src/libs/bmp/lv_bmp.c | 13 +- src/libs/ffmpeg/lv_ffmpeg.c | 13 +- src/libs/libjpeg_turbo/lv_libjpeg_turbo.c | 13 +- src/libs/libpng/lv_libpng.c | 13 +- src/libs/lodepng/lv_lodepng.c | 7 +- src/libs/tjpgd/lv_tjpgd.c | 13 +- src/lv_conf_internal.h | 10 + 20 files changed, 258 insertions(+), 149 deletions(-) diff --git a/.devcontainer/__lv_conf.h__ b/.devcontainer/__lv_conf.h__ index b022d4020..eba6b2ec4 100644 --- a/.devcontainer/__lv_conf.h__ +++ b/.devcontainer/__lv_conf.h__ @@ -271,6 +271,10 @@ *If size is 0, the cache function is not enabled and the decoded mem will be released immediately after use.*/ #define LV_CACHE_DEF_SIZE 0 +/*Default number of image header cache entries. The cache is used to store the headers of images + *The main logic is like `LV_CACHE_DEF_SIZE` but for image headers.*/ +#define LV_IMAGE_HEADER_CACHE_DEF_CNT 0 + /*Number of stops allowed per gradient. Increase this to allow more stops. *This adds (sizeof(lv_color_t) + 1) bytes per additional stop*/ #define LV_GRADIENT_MAX_STOPS 2 diff --git a/Kconfig b/Kconfig index 54d06693a..e17e7b72e 100644 --- a/Kconfig +++ b/Kconfig @@ -269,6 +269,18 @@ menu "LVGL configuration" save the continuous open/decode of images. However the opened images might consume additional RAM. + config LV_IMAGE_HEADER_CACHE_DEF_CNT + int "Default image header cache count. 0 to disable caching." + default 0 + depends on LV_USE_DRAW_SW + help + If only the built-in image formats are used there is no real advantage of caching. + (I.e. no new image decoder is added). + + With complex image decoders (e.g. PNG or JPG) caching can + save the continuous getting header information of images. + However the records of opened images headers might consume additional RAM. + config LV_GRADIENT_MAX_STOPS int "Number of stops allowed per gradient." default 2 diff --git a/env_support/cmsis-pack/lv_conf_cmsis.h b/env_support/cmsis-pack/lv_conf_cmsis.h index f638fe88f..08f085b30 100644 --- a/env_support/cmsis-pack/lv_conf_cmsis.h +++ b/env_support/cmsis-pack/lv_conf_cmsis.h @@ -261,6 +261,10 @@ *will be dropped immediately after usage.*/ #define LV_CACHE_DEF_SIZE 0 +/*Default number of image header cache entries. The cache is used to store the headers of images + *The main logic is like `LV_CACHE_DEF_SIZE` but for image headers.*/ +#define LV_IMAGE_HEADER_CACHE_DEF_CNT 0 + /*Number of stops allowed per gradient. Increase this to allow more stops. *This adds (sizeof(lv_color_t) + 1) bytes per additional stop*/ #define LV_GRADIENT_MAX_STOPS 2 diff --git a/lv_conf_template.h b/lv_conf_template.h index f20e840e5..8405cc734 100644 --- a/lv_conf_template.h +++ b/lv_conf_template.h @@ -271,6 +271,10 @@ *If size is 0, the cache function is not enabled and the decoded mem will be released immediately after use.*/ #define LV_CACHE_DEF_SIZE 0 +/*Default number of image header cache entries. The cache is used to store the headers of images + *The main logic is like `LV_CACHE_DEF_SIZE` but for image headers.*/ +#define LV_IMAGE_HEADER_CACHE_DEF_CNT 0 + /*Number of stops allowed per gradient. Increase this to allow more stops. *This adds (sizeof(lv_color_t) + 1) bytes per additional stop*/ #define LV_GRADIENT_MAX_STOPS 2 diff --git a/src/core/lv_global.h b/src/core/lv_global.h index fdbf7394d..ed006224c 100644 --- a/src/core/lv_global.h +++ b/src/core/lv_global.h @@ -101,6 +101,10 @@ typedef struct _lv_global_t { lv_cache_t * img_cache; #endif +#if LV_IMAGE_HEADER_CACHE_DEF_CNT > 0 + lv_cache_t * img_header_cache; +#endif + lv_draw_global_info_t draw_info; #if defined(LV_DRAW_SW_SHADOW_CACHE_SIZE) && LV_DRAW_SW_SHADOW_CACHE_SIZE > 0 lv_draw_sw_shadow_cache_t sw_shadow_cache; diff --git a/src/draw/lv_image_decoder.c b/src/draw/lv_image_decoder.c index fb8ac193d..204edf994 100644 --- a/src/draw/lv_image_decoder.c +++ b/src/draw/lv_image_decoder.c @@ -18,6 +18,7 @@ *********************/ #define img_decoder_ll_p &(LV_GLOBAL_DEFAULT()->img_decoder_ll) #define img_cache_p (LV_GLOBAL_DEFAULT()->img_cache) +#define img_header_cache_p (LV_GLOBAL_DEFAULT()->img_header_cache) /********************** * TYPEDEFS @@ -29,6 +30,20 @@ static uint32_t img_width_to_stride(lv_image_header_t * header); +/** + * Get the header info of an image source, and return the a pointer to the decoder that can open it. + * @param src The image source (e.g. a filename or a pointer to a C array) + * @param header The header of the image + * @return The decoder that can open the image source or NULL if not found (or can't open it). + */ +static lv_image_decoder_t * image_decoder_get_info(const void * src, lv_image_header_t * header); + +#if LV_IMAGE_HEADER_CACHE_DEF_CNT > 0 +static lv_cache_compare_res_t image_decoder_header_cache_compare_cb(const lv_image_header_cache_data_t * lhs, + const lv_image_header_cache_data_t * rhs); +static void image_decoder_header_cache_free_cb(lv_image_header_cache_data_t * entry, void * user_data); +#endif + #if LV_CACHE_DEF_SIZE > 0 static lv_cache_compare_res_t image_decoder_cache_compare_cb(const lv_image_cache_data_t * lhs, const lv_image_cache_data_t * rhs); @@ -62,6 +77,16 @@ void _lv_image_decoder_init(void) .create_cb = NULL, .free_cb = (lv_cache_free_cb_t)image_decoder_cache_free_cb, }); + +#endif + +#if LV_IMAGE_HEADER_CACHE_DEF_CNT > 0 + img_header_cache_p = lv_cache_create(&lv_cache_class_lru_rb_count, + sizeof(lv_image_header_cache_data_t), LV_IMAGE_HEADER_CACHE_DEF_CNT, (lv_cache_ops_t) { + .compare_cb = (lv_cache_compare_cb_t)image_decoder_header_cache_compare_cb, + .create_cb = NULL, + .free_cb = (lv_cache_free_cb_t)image_decoder_header_cache_free_cb + }); #endif } @@ -73,34 +98,19 @@ void _lv_image_decoder_deinit(void) #if LV_CACHE_DEF_SIZE > 0 lv_cache_destroy(img_cache_p, NULL); #endif + +#if LV_IMAGE_HEADER_CACHE_DEF_CNT > 0 + lv_cache_destroy(img_header_cache_p, NULL); +#endif _lv_ll_clear(img_decoder_ll_p); } lv_result_t lv_image_decoder_get_info(const void * src, lv_image_header_t * header) { - lv_memzero(header, sizeof(lv_image_header_t)); + lv_image_decoder_t * decoder = image_decoder_get_info(src, header); + if(decoder == NULL) return LV_RESULT_INVALID; - if(src == NULL) return LV_RESULT_INVALID; - - lv_image_src_t src_type = lv_image_src_get_type(src); - if(src_type == LV_IMAGE_SRC_VARIABLE) { - const lv_image_dsc_t * img_dsc = src; - if(img_dsc->data == NULL) return LV_RESULT_INVALID; - } - - lv_result_t res = LV_RESULT_INVALID; - lv_image_decoder_t * decoder; - _LV_LL_READ(img_decoder_ll_p, decoder) { - if(decoder->info_cb) { - res = decoder->info_cb(decoder, src, header); - if(res == LV_RESULT_OK) { - if(header->stride == 0) header->stride = img_width_to_stride(header); - break; - } - } - } - - return res; + return LV_RESULT_OK; } lv_result_t lv_image_decoder_open(lv_image_decoder_dsc_t * dsc, const void * src, const lv_image_decoder_args_t * args) @@ -108,70 +118,38 @@ lv_result_t lv_image_decoder_open(lv_image_decoder_dsc_t * dsc, const void * src lv_memzero(dsc, sizeof(lv_image_decoder_dsc_t)); if(src == NULL) return LV_RESULT_INVALID; - lv_image_src_t src_type = lv_image_src_get_type(src); - if(src_type == LV_IMAGE_SRC_VARIABLE) { - const lv_image_dsc_t * img_dsc = src; - if(img_dsc->data == NULL) return LV_RESULT_INVALID; - } + dsc->src = src; + dsc->src_type = lv_image_src_get_type(src); - dsc->src_type = src_type; +#if LV_CACHE_DEF_SIZE > 0 + dsc->cache = img_cache_p; + /* + * Check the cache first + * If the image is found in the cache, just return it.*/ + if(try_cache(dsc) == LV_RESULT_OK) return LV_RESULT_OK; +#endif - if(dsc->src_type == LV_IMAGE_SRC_FILE) { - dsc->src = lv_strdup(src); - } - else { - dsc->src = src; - } + /*Find the decoder that can open the image source, and get the header info in the same time.*/ + dsc->decoder = image_decoder_get_info(src, &dsc->header); + if(dsc->decoder == NULL) return LV_RESULT_INVALID; - lv_result_t res = LV_RESULT_INVALID; + /*Duplicate the source if it's a file*/ + if(dsc->src_type == LV_IMAGE_SRC_FILE) dsc->src = lv_strdup(dsc->src); - lv_image_decoder_t * decoder; - - static const lv_image_decoder_args_t def_args = { + /*Make a copy of args*/ + dsc->args = args ? *args : (lv_image_decoder_args_t) { .stride_align = LV_DRAW_BUF_STRIDE_ALIGN != 1, .premultiply = false, .no_cache = false, .use_indexed = false, }; - /*Make a copy of args */ - dsc->args = args ? *args : def_args; - - _LV_LL_READ(img_decoder_ll_p, decoder) { - /*Info and Open callbacks are required*/ - if(decoder->info_cb == NULL || decoder->open_cb == NULL) continue; - - res = decoder->info_cb(decoder, src, &dsc->header); - if(res != LV_RESULT_OK) continue; - - if(dsc->header.stride == 0) dsc->header.stride = img_width_to_stride(&dsc->header); - - dsc->decoder = decoder; - -#if LV_CACHE_DEF_SIZE > 0 - dsc->cache = img_cache_p; - - /*Check the cache first*/ - if(try_cache(dsc) == LV_RESULT_OK) return LV_RESULT_OK; -#endif - - res = decoder->open_cb(decoder, dsc, args); - - /*Opened successfully. It is a good decoder for this image source*/ - if(res == LV_RESULT_OK) return res; - - /*Prepare for the next loop*/ - lv_memzero(&dsc->header, sizeof(lv_image_header_t)); - - dsc->error_msg = NULL; - dsc->decoded = NULL; - dsc->cache_entry = NULL; - dsc->user_data = NULL; - dsc->time_to_open = 0; - } - - if(dsc->src_type == LV_IMAGE_SRC_FILE) - lv_free((void *)dsc->src); + /* + * We assume that if a decoder can get the info, it can open the image. + * If decoder open failed, free the source and return error. + * If decoder open succeed, add the image to cache if enabled. + * */ + lv_result_t res = dsc->decoder->open_cb(dsc->decoder, dsc); return res; } @@ -321,6 +299,70 @@ lv_draw_buf_t * lv_image_decoder_post_process(lv_image_decoder_dsc_t * dsc, lv_d return decoded; } +/********************** + * STATIC FUNCTIONS + **********************/ + +static lv_image_decoder_t * image_decoder_get_info(const void * src, lv_image_header_t * header) +{ + lv_memzero(header, sizeof(lv_image_header_t)); + + if(src == NULL) return NULL; + + lv_image_src_t src_type = lv_image_src_get_type(src); + if(src_type == LV_IMAGE_SRC_VARIABLE) { + const lv_image_dsc_t * img_dsc = src; + if(img_dsc->data == NULL) return NULL; + } + + lv_image_decoder_t * decoder; + +#if LV_IMAGE_HEADER_CACHE_DEF_CNT > 0 + lv_image_header_cache_data_t search_key; + search_key.src_type = src_type; + search_key.src = src; + + lv_cache_entry_t * entry = lv_cache_acquire(img_header_cache_p, &search_key, NULL); + + if(entry) { + lv_image_header_cache_data_t * cached_data = lv_cache_entry_get_data(entry); + *header = cached_data->header; + decoder = cached_data->decoder; + lv_cache_release(img_header_cache_p, entry, NULL); + return decoder; + } +#endif + + _LV_LL_READ(img_decoder_ll_p, decoder) { + /*Info and Open callbacks are required*/ + if(decoder->info_cb && decoder->open_cb) { + lv_result_t res = decoder->info_cb(decoder, src, header); + if(res == LV_RESULT_OK) { + if(header->stride == 0) header->stride = img_width_to_stride(header); + break; + } + } + } + +#if LV_IMAGE_HEADER_CACHE_DEF_CNT > 0 + if(decoder) { + if(src_type == LV_IMAGE_SRC_FILE) search_key.src = lv_strdup(src); + search_key.decoder = decoder; + search_key.header = *header; + entry = lv_cache_add(img_header_cache_p, &search_key, NULL); + + if(entry == NULL) { + if(src_type == LV_IMAGE_SRC_FILE) lv_free((void *)search_key.src); + return NULL; + } + + lv_cache_release(img_header_cache_p, entry, NULL); + } +#endif + + return decoder; +} + static uint32_t img_width_to_stride(lv_image_header_t * header) { if(header->cf == LV_COLOR_FORMAT_RGB565A8) { @@ -331,26 +373,50 @@ static uint32_t img_width_to_stride(lv_image_header_t * header) } } +#if LV_CACHE_DEF_SIZE > 0 || LV_IMAGE_HEADER_CACHE_DEF_CNT > 0 +inline static lv_cache_compare_res_t image_decoder_common_compare(const void * lhs_src, lv_image_src_t lhs_src_type, + const void * rhs_src, lv_image_src_t rhs_src_type) +{ + if(lhs_src_type == rhs_src_type) { + if(lhs_src_type == LV_IMAGE_SRC_FILE) { + int32_t cmp_res = lv_strcmp(lhs_src, rhs_src); + if(cmp_res != 0) { + return cmp_res > 0 ? 1 : -1; + } + } + else if(lhs_src_type == LV_IMAGE_SRC_VARIABLE) { + if(lhs_src != rhs_src) { + return lhs_src > rhs_src ? 1 : -1; + } + } + return 0; + } + return lhs_src_type > rhs_src_type ? 1 : -1; +} +#endif + +#if LV_IMAGE_HEADER_CACHE_DEF_CNT > 0 +static lv_cache_compare_res_t image_decoder_header_cache_compare_cb( + const lv_image_header_cache_data_t * lhs, + const lv_image_header_cache_data_t * rhs) +{ + return image_decoder_common_compare(lhs->src, lhs->src_type, rhs->src, rhs->src_type); +} + +static void image_decoder_header_cache_free_cb(lv_image_header_cache_data_t * entry, void * user_data) +{ + LV_UNUSED(user_data); /*Unused*/ + + if(entry->src_type == LV_IMAGE_SRC_FILE) lv_free((void *)entry->src); +} +#endif + #if LV_CACHE_DEF_SIZE > 0 static lv_cache_compare_res_t image_decoder_cache_compare_cb( const lv_image_cache_data_t * lhs, const lv_image_cache_data_t * rhs) { - if(lhs->src_type == rhs->src_type) { - if(lhs->src_type == LV_IMAGE_SRC_FILE) { - int32_t cmp_res = lv_strcmp(lhs->src, rhs->src); - if(cmp_res != 0) { - return cmp_res > 0 ? 1 : -1; - } - } - else if(lhs->src_type == LV_IMAGE_SRC_VARIABLE) { - if(lhs->src != rhs->src) { - return lhs->src > rhs->src ? 1 : -1; - } - } - return 0; - } - return lhs->src_type > rhs->src_type ? 1 : -1; + return image_decoder_common_compare(lhs->src, lhs->src_type, rhs->src, rhs->src_type); } static void image_decoder_cache_free_cb(lv_image_cache_data_t * entry, void * user_data) diff --git a/src/draw/lv_image_decoder.h b/src/draw/lv_image_decoder.h index 8e19f1937..2979f08fc 100644 --- a/src/draw/lv_image_decoder.h +++ b/src/draw/lv_image_decoder.h @@ -79,11 +79,8 @@ typedef lv_result_t (*lv_image_decoder_info_f_t)(lv_image_decoder_t * decoder, c * Open an image for decoding. Prepare it as it is required to read it later * @param decoder pointer to the decoder the function associated with * @param dsc pointer to decoder descriptor. `src`, `color` are already initialized in it. - * @param args arguments of how to decode the image. see `lv_image_decoder_args_t`. */ -typedef lv_result_t (*lv_image_decoder_open_f_t)(lv_image_decoder_t * decoder, - lv_image_decoder_dsc_t * dsc, - const lv_image_decoder_args_t * args); +typedef lv_result_t (*lv_image_decoder_open_f_t)(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc); /** * Decode `len` pixels starting from the given `x`, `y` coordinates and store them in `buf`. @@ -128,6 +125,14 @@ typedef struct _lv_image_decoder_cache_data_t { void * user_data; } lv_image_cache_data_t; +typedef struct _lv_image_decoder_header_cache_data_t { + const void * src; + lv_image_src_t src_type; + + lv_image_header_t header; + lv_image_decoder_t * decoder; +} lv_image_header_cache_data_t; + /**Describe an image decoding session. Stores data about the decoding*/ struct _lv_image_decoder_dsc_t { /**The decoder which was able to open the image source*/ diff --git a/src/draw/sw/lv_draw_sw_arc.c b/src/draw/sw/lv_draw_sw_arc.c index c80878040..8172e10bd 100644 --- a/src/draw/sw/lv_draw_sw_arc.c +++ b/src/draw/sw/lv_draw_sw_arc.c @@ -126,9 +126,9 @@ void lv_draw_sw_arc(lv_draw_unit_t * draw_unit, const lv_draw_arc_dsc_t * dsc, c lv_image_decoder_open(&decoder_dsc, dsc->img_src, NULL); img_area.x1 = 0; img_area.y1 = 0; - img_area.x2 = decoder_dsc.header.w - 1; - img_area.y2 = decoder_dsc.header.h - 1; - int32_t ofs = decoder_dsc.header.w / 2; + img_area.x2 = decoder_dsc.decoded->header.w - 1; + img_area.y2 = decoder_dsc.decoded->header.h - 1; + int32_t ofs = decoder_dsc.decoded->header.w / 2; lv_area_move(&img_area, dsc->center.x - ofs, dsc->center.y - ofs); blend_dsc.src_area = &img_area; blend_dsc.src_buf = decoder_dsc.decoded->data; diff --git a/src/draw/sw/lv_draw_sw_vector.c b/src/draw/sw/lv_draw_sw_vector.c index d5a45bd48..bd20df39c 100644 --- a/src/draw/sw/lv_draw_sw_vector.c +++ b/src/draw/sw/lv_draw_sw_vector.c @@ -305,7 +305,7 @@ static void _set_paint_fill_pattern(Tvg_Paint * obj, Tvg_Canvas * canvas, const } const uint8_t * src_buf = decoder_dsc.decoded->data; - const lv_image_header_t * header = &decoder_dsc.header; + const lv_image_header_t * header = &decoder_dsc.decoded->header; lv_color_format_t cf = header->cf; if(cf != LV_COLOR_FORMAT_ARGB8888) { diff --git a/src/draw/vg_lite/lv_draw_vg_lite_img.c b/src/draw/vg_lite/lv_draw_vg_lite_img.c index 4654b9bb1..05c8debd0 100644 --- a/src/draw/vg_lite/lv_draw_vg_lite_img.c +++ b/src/draw/vg_lite/lv_draw_vg_lite_img.c @@ -76,7 +76,7 @@ void lv_draw_vg_lite_img(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t * } vg_lite_color_t color = 0; - if(LV_COLOR_FORMAT_IS_ALPHA_ONLY(decoder_dsc.header.cf) || dsc->recolor_opa > LV_OPA_MIN) { + if(LV_COLOR_FORMAT_IS_ALPHA_ONLY(decoder_dsc.decoded->header.cf) || dsc->recolor_opa > LV_OPA_MIN) { /* alpha image and image recolor */ src_buf.image_mode = VG_LITE_MULTIPLY_IMAGE_MODE; color = lv_vg_lite_color(dsc->recolor, LV_OPA_MIX2(dsc->opa, dsc->recolor_opa), true); diff --git a/src/draw/vg_lite/lv_vg_lite_decoder.c b/src/draw/vg_lite/lv_vg_lite_decoder.c index 8e3b479cc..59dc6f754 100644 --- a/src/draw/vg_lite/lv_vg_lite_decoder.c +++ b/src/draw/vg_lite/lv_vg_lite_decoder.c @@ -37,8 +37,7 @@ typedef struct { **********************/ static lv_result_t decoder_info(lv_image_decoder_t * decoder, const void * src, lv_image_header_t * header); -static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc, - const lv_image_decoder_args_t * args); +static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc); static void decoder_close(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc); static void decoder_cache_free(lv_image_cache_data_t * cached_data, void * user_data); static void image_try_self_pre_mul(lv_image_decoder_dsc_t * dsc); @@ -367,10 +366,14 @@ failed: return LV_RESULT_INVALID; } -static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc, - const lv_image_decoder_args_t * args) +/** + * Decode an image using the vg_lite gpu. + * @param decoder pointer to the decoder + * @param dsc pointer to the decoder descriptor + * @return LV_RESULT_OK: no error; LV_RESULT_INVALID: can't open the image + */ +static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc) { - LV_UNUSED(args); /*Unused*/ lv_result_t res = LV_RESULT_INVALID; diff --git a/src/libs/bin_decoder/lv_bin_decoder.c b/src/libs/bin_decoder/lv_bin_decoder.c index 374cc8edb..21ed30e3a 100644 --- a/src/libs/bin_decoder/lv_bin_decoder.c +++ b/src/libs/bin_decoder/lv_bin_decoder.c @@ -167,11 +167,15 @@ lv_result_t lv_bin_decoder_info(lv_image_decoder_t * decoder, const void * src, return LV_RESULT_OK; } -lv_result_t lv_bin_decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc, - const lv_image_decoder_args_t * args) +/** + * Decode an image from a binary file + * @param decoder pointer to the decoder + * @param dsc pointer to the decoder descriptor + * @return LV_RESULT_OK: no error; LV_RESULT_INVALID: can't open the image + */ +lv_result_t lv_bin_decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc) { LV_UNUSED(decoder); - LV_UNUSED(args); lv_fs_res_t res = LV_RESULT_INVALID; bool use_directly = false; /*If the image is already decoded and can be used directly*/ diff --git a/src/libs/bin_decoder/lv_bin_decoder.h b/src/libs/bin_decoder/lv_bin_decoder.h index c5e6294f6..2966dac39 100644 --- a/src/libs/bin_decoder/lv_bin_decoder.h +++ b/src/libs/bin_decoder/lv_bin_decoder.h @@ -50,8 +50,7 @@ lv_result_t lv_bin_decoder_get_area(lv_image_decoder_t * decoder, lv_image_decod * @param dsc pointer to decoder descriptor. `src`, `style` are already initialized in it. * @return LV_RESULT_OK: the info is successfully stored in `header`; LV_RESULT_INVALID: unknown format or other error. */ -lv_result_t lv_bin_decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc, - const lv_image_decoder_args_t * args); +lv_result_t lv_bin_decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc); /** * Close the pending decoding. Free resources etc. diff --git a/src/libs/bmp/lv_bmp.c b/src/libs/bmp/lv_bmp.c index 2951a74f3..c36f2cc12 100644 --- a/src/libs/bmp/lv_bmp.c +++ b/src/libs/bmp/lv_bmp.c @@ -32,8 +32,7 @@ typedef struct { * STATIC PROTOTYPES **********************/ static lv_result_t decoder_info(lv_image_decoder_t * decoder, const void * src, lv_image_header_t * header); -static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc, - const lv_image_decoder_args_t * args); +static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc); static lv_result_t decoder_get_area(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc, const lv_area_t * full_area, lv_area_t * decoded_area); @@ -136,15 +135,13 @@ static lv_result_t decoder_info(lv_image_decoder_t * decoder, const void * src, /** * Open a BMP image and return the decided image - * @param src can be file name or pointer to a C array - * @param style style of the image object (unused now but certain formats might use it) - * @return pointer to the decoded image or `LV_IMAGE_DECODER_OPEN_FAIL` if failed + * @param decoder pointer to the decoder + * @param dsc pointer to the decoder descriptor + * @return LV_RESULT_OK: no error; LV_RESULT_INVALID: can't open the image */ -static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc, - const lv_image_decoder_args_t * args) +static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc) { LV_UNUSED(decoder); - LV_UNUSED(args); /*If it's a BMP file...*/ if(dsc->src_type == LV_IMAGE_SRC_FILE) { diff --git a/src/libs/ffmpeg/lv_ffmpeg.c b/src/libs/ffmpeg/lv_ffmpeg.c index 453bacac1..7efc5773a 100644 --- a/src/libs/ffmpeg/lv_ffmpeg.c +++ b/src/libs/ffmpeg/lv_ffmpeg.c @@ -67,8 +67,7 @@ struct lv_image_pixel_color_s { **********************/ static lv_result_t decoder_info(lv_image_decoder_t * decoder, const void * src, lv_image_header_t * header); -static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc, - const lv_image_decoder_args_t * args); +static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc); static void decoder_close(lv_image_decoder_t * dec, lv_image_decoder_dsc_t * dsc); static struct ffmpeg_context_s * ffmpeg_open_file(const char * path); @@ -270,11 +269,15 @@ static lv_result_t decoder_info(lv_image_decoder_t * decoder, const void * src, return LV_RESULT_INVALID; } -static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc, - const lv_image_decoder_args_t * args) +/** + * Decode an image using ffmpeg library + * @param decoder pointer to the decoder + * @param dsc pointer to the decoder descriptor + * @return LV_RESULT_OK: no error; LV_RESULT_INVALID: can't open the image + */ +static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc) { LV_UNUSED(decoder); - LV_UNUSED(args); if(dsc->src_type == LV_IMAGE_SRC_FILE) { const char * path = dsc->src; diff --git a/src/libs/libjpeg_turbo/lv_libjpeg_turbo.c b/src/libs/libjpeg_turbo/lv_libjpeg_turbo.c index 5f31841c0..59803323c 100644 --- a/src/libs/libjpeg_turbo/lv_libjpeg_turbo.c +++ b/src/libs/libjpeg_turbo/lv_libjpeg_turbo.c @@ -33,8 +33,7 @@ typedef struct error_mgr_s { * STATIC PROTOTYPES **********************/ static lv_result_t decoder_info(lv_image_decoder_t * decoder, const void * src, lv_image_header_t * header); -static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc, - const lv_image_decoder_args_t * args); +static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc); static void decoder_close(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc); static lv_draw_buf_t * decode_jpeg_file(const char * filename); static bool get_jpeg_size(const char * filename, uint32_t * width, uint32_t * height); @@ -141,15 +140,13 @@ static lv_result_t decoder_info(lv_image_decoder_t * decoder, const void * src, /** * Open a JPEG image and return the decided image - * @param src can be file name or pointer to a C array - * @param style style of the image object (unused now but certain formats might use it) - * @return pointer to the decoded image or `LV_IMAGE_DECODER_OPEN_FAIL` if failed + * @param decoder pointer to the decoder + * @param dsc pointer to the decoder descriptor + * @return LV_RESULT_OK: no error; LV_RESULT_INVALID: can't open the image */ -static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc, - const lv_image_decoder_args_t * args) +static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc) { LV_UNUSED(decoder); /*Unused*/ - LV_UNUSED(args); /*Unused*/ /*If it's a JPEG file...*/ if(dsc->src_type == LV_IMAGE_SRC_FILE) { diff --git a/src/libs/libpng/lv_libpng.c b/src/libs/libpng/lv_libpng.c index 0671a84d2..2776e6c2d 100644 --- a/src/libs/libpng/lv_libpng.c +++ b/src/libs/libpng/lv_libpng.c @@ -24,8 +24,7 @@ * STATIC PROTOTYPES **********************/ static lv_result_t decoder_info(lv_image_decoder_t * decoder, const void * src, lv_image_header_t * header); -static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc, - const lv_image_decoder_args_t * args); +static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc); static void decoder_close(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc); static lv_draw_buf_t * decode_png_file(const char * filename); @@ -117,15 +116,13 @@ static lv_result_t decoder_info(lv_image_decoder_t * decoder, const void * src, /** * Open a PNG image and return the decided image - * @param src can be file name or pointer to a C array - * @param style style of the image object (unused now but certain formats might use it) - * @return pointer to the decoded image or `LV_IMAGE_DECODER_OPEN_FAIL` if failed + * @param decoder pointer to the decoder + * @param dsc pointer to the decoder descriptor + * @return LV_RESULT_OK: no error; LV_RESULT_INVALID: can't open the image */ -static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc, - const lv_image_decoder_args_t * args) +static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc) { LV_UNUSED(decoder); /*Unused*/ - LV_UNUSED(args); /*Unused*/ /*If it's a PNG file...*/ if(dsc->src_type == LV_IMAGE_SRC_FILE) { diff --git a/src/libs/lodepng/lv_lodepng.c b/src/libs/lodepng/lv_lodepng.c index 5f094c6b3..49a1e8825 100644 --- a/src/libs/lodepng/lv_lodepng.c +++ b/src/libs/lodepng/lv_lodepng.c @@ -25,8 +25,7 @@ * STATIC PROTOTYPES **********************/ static lv_result_t decoder_info(lv_image_decoder_t * decoder, const void * src, lv_image_header_t * header); -static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc, - const lv_image_decoder_args_t * args); +static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc); static void decoder_close(lv_image_decoder_t * dec, lv_image_decoder_dsc_t * dsc); static void convert_color_depth(uint8_t * img_p, uint32_t px_cnt); static lv_draw_buf_t * decode_png_data(const void * png_data, size_t png_data_size); @@ -150,11 +149,9 @@ static lv_result_t decoder_info(lv_image_decoder_t * decoder, const void * src, * @param dsc decoded image descriptor * @return LV_RESULT_OK: no error; LV_RESULT_INVALID: can't open the image */ -static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc, - const lv_image_decoder_args_t * args) +static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc) { LV_UNUSED(decoder); - LV_UNUSED(args); const uint8_t * png_data = NULL; size_t png_data_size = 0; diff --git a/src/libs/tjpgd/lv_tjpgd.c b/src/libs/tjpgd/lv_tjpgd.c index 72bf70543..2185c2828 100644 --- a/src/libs/tjpgd/lv_tjpgd.c +++ b/src/libs/tjpgd/lv_tjpgd.c @@ -27,8 +27,7 @@ * STATIC PROTOTYPES **********************/ static lv_result_t decoder_info(lv_image_decoder_t * decoder, const void * src, lv_image_header_t * header); -static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc, - const lv_image_decoder_args_t * args); +static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc); static lv_result_t decoder_get_area(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc, const lv_area_t * full_area, lv_area_t * decoded_area); @@ -143,11 +142,15 @@ static size_t input_func(JDEC * jd, uint8_t * buff, size_t ndata) return 0; } -static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc, - const lv_image_decoder_args_t * args) +/** + * Decode a JPG image and return the decoded data. + * @param decoder pointer to the decoder + * @param dsc pointer to the decoder descriptor + * @return LV_RESULT_OK: no error; LV_RESULT_INVALID: can't open the image + */ +static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc) { LV_UNUSED(decoder); - LV_UNUSED(args); lv_fs_file_t * f = lv_malloc(sizeof(lv_fs_file_t)); if(dsc->src_type == LV_IMAGE_SRC_VARIABLE) { #if LV_USE_FS_MEMFS diff --git a/src/lv_conf_internal.h b/src/lv_conf_internal.h index 47ed197bc..98dff9594 100644 --- a/src/lv_conf_internal.h +++ b/src/lv_conf_internal.h @@ -771,6 +771,16 @@ #endif #endif +/*Default number of image header cache entries. The cache is used to store the headers of images + *The main logic is like `LV_CACHE_DEF_SIZE` but for image headers.*/ +#ifndef LV_IMAGE_HEADER_CACHE_DEF_CNT + #ifdef CONFIG_LV_IMAGE_HEADER_CACHE_DEF_CNT + #define LV_IMAGE_HEADER_CACHE_DEF_CNT CONFIG_LV_IMAGE_HEADER_CACHE_DEF_CNT + #else + #define LV_IMAGE_HEADER_CACHE_DEF_CNT 0 + #endif +#endif + /*Number of stops allowed per gradient. Increase this to allow more stops. *This adds (sizeof(lv_color_t) + 1) bytes per additional stop*/ #ifndef LV_GRADIENT_MAX_STOPS