diff --git a/docs/overview/img.rst b/docs/overview/img.rst index d249a0ca6..27c6c54b7 100644 --- a/docs/overview/img.rst +++ b/docs/overview/img.rst @@ -343,7 +343,8 @@ to open is an animation. lv_result_t res; lv_image_decoder_dsc_t dsc; - res = lv_image_decoder_open(&dsc, &my_img_dsc, color, frame_id); + lv_image_decoder_args_t args = { 0 }; /*Custom decoder behavior via args*/ + res = lv_image_decoder_open(&dsc, &my_img_dsc, &args); if(res == LV_RESULT_OK) { /*Do something with `dsc->img_data`*/ @@ -457,7 +458,7 @@ See the detailed code below: { ... lv_image_decoder_dsc_t decoder_dsc; - lv_result_t res = lv_image_decoder_open(&decoder_dsc, draw_dsc->src, draw_dsc->recolor, -1); + lv_result_t res = lv_image_decoder_open(&decoder_dsc, draw_dsc->src, NULL); if(res != LV_RESULT_OK) { LV_LOG_ERROR("Failed to open image"); return; diff --git a/src/draw/lv_image_decoder.c b/src/draw/lv_image_decoder.c index 261a33763..580e5f240 100644 --- a/src/draw/lv_image_decoder.c +++ b/src/draw/lv_image_decoder.c @@ -90,9 +90,8 @@ lv_result_t lv_image_decoder_get_info(const void * src, lv_image_header_t * head return res; } -lv_result_t lv_image_decoder_open(lv_image_decoder_dsc_t * dsc, const void * src, lv_color_t color, int32_t frame_id) +lv_result_t lv_image_decoder_open(lv_image_decoder_dsc_t * dsc, const void * src, const lv_image_decoder_args_t * args) { - LV_UNUSED(color); lv_memzero(dsc, sizeof(lv_image_decoder_dsc_t)); if(src == NULL) return LV_RESULT_INVALID; @@ -103,7 +102,7 @@ lv_result_t lv_image_decoder_open(lv_image_decoder_dsc_t * dsc, const void * src } dsc->src_type = src_type; - dsc->frame_id = frame_id; + if(args) dsc->frame_id = args->frame_id; if(dsc->src_type == LV_IMAGE_SRC_FILE) { size_t fnlen = lv_strlen(src); @@ -122,6 +121,20 @@ lv_result_t lv_image_decoder_open(lv_image_decoder_dsc_t * dsc, const void * src lv_result_t res = LV_RESULT_INVALID; lv_image_decoder_t * decoder; + lv_image_decoder_args_t * args_copy = NULL; + + /*Make a copy of args */ + if(args) { + args_copy = lv_malloc(sizeof(lv_image_decoder_args_t)); + LV_ASSERT_MALLOC(args_copy); + if(args_copy == NULL) { + LV_LOG_WARN("Out of memory"); + return LV_RESULT_INVALID; + } + lv_memcpy(args_copy, args, sizeof(lv_image_decoder_args_t)); + dsc->args = args_copy; + } + _LV_LL_READ(img_decoder_ll_p, decoder) { /*Info and Open callbacks are required*/ if(decoder->info_cb == NULL || decoder->open_cb == NULL) continue; @@ -132,7 +145,7 @@ lv_result_t lv_image_decoder_open(lv_image_decoder_dsc_t * dsc, const void * src if(dsc->header.stride == 0) dsc->header.stride = img_width_to_stride(&dsc->header); dsc->decoder = decoder; - res = decoder->open_cb(decoder, dsc); + 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; @@ -150,6 +163,8 @@ lv_result_t lv_image_decoder_open(lv_image_decoder_dsc_t * dsc, const void * src if(dsc->src_type == LV_IMAGE_SRC_FILE) lv_free((void *)dsc->src); + if(args_copy) lv_free(args_copy); + return res; } @@ -178,6 +193,7 @@ void lv_image_decoder_close(lv_image_decoder_dsc_t * dsc) { if(dsc->decoder) { if(dsc->decoder->close_cb) dsc->decoder->close_cb(dsc->decoder, dsc); + if(dsc->args) lv_free(dsc->args); if(dsc->src_type == LV_IMAGE_SRC_FILE) { lv_free((void *)dsc->src); diff --git a/src/draw/lv_image_decoder.h b/src/draw/lv_image_decoder.h index 2047dda6c..578641150 100644 --- a/src/draw/lv_image_decoder.h +++ b/src/draw/lv_image_decoder.h @@ -49,6 +49,22 @@ struct _lv_image_decoder_dsc_t; struct _lv_image_decoder_t; struct _lv_cache_entry_t; +/** + * Image decoder args. + * It determines how to decoder an image, e.g. whether to premultiply the alpha or not. + * It should be passed to lv_img_decoder_open() function. If NULL is provided, default + * args are used. + * + * Default args: + * all field are zero or false. + */ +typedef struct _lv_image_decoder_args_t { + int32_t frame_id; /*A not use args*/ + 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*/ +} lv_image_decoder_args_t; + /** * Get info from an image and store in the `header` * @param src the image source. Can be a pointer to a C array or a file name (Use @@ -63,9 +79,11 @@ typedef lv_result_t (*lv_image_decoder_info_f_t)(struct _lv_image_decoder_t * de * 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)(struct _lv_image_decoder_t * decoder, - struct _lv_image_decoder_dsc_t * dsc); + struct _lv_image_decoder_dsc_t * dsc, + const lv_image_decoder_args_t * args); /** * Decode `len` pixels starting from the given `x`, `y` coordinates and store them in `buf`. @@ -103,6 +121,9 @@ typedef struct _lv_image_decoder_dsc_t { /**The decoder which was able to open the image source*/ lv_image_decoder_t * decoder; + /*A copy of parameters of how this image is decoded*/ + lv_image_decoder_args_t * args; + /**The image source. A file path like "S:my_img.png" or pointer to an `lv_image_dsc_t` variable*/ const void * src; @@ -172,11 +193,11 @@ lv_result_t lv_image_decoder_get_info(const void * src, lv_image_header_t * head * 2) Variable: Pointer to an `lv_image_dsc_t` variable * 3) Symbol: E.g. `LV_SYMBOL_OK` * @param color The color of the image with `LV_IMAGE_CF_ALPHA_...` - * @param frame_id the index of the frame. Used only with animated images, set 0 for normal images + * @param args args about how the image should be opened. * @return LV_RESULT_OK: opened the image. `dsc->img_data` and `dsc->header` are set. * LV_RESULT_INVALID: none of the registered image decoders were able to open the image. */ -lv_result_t lv_image_decoder_open(lv_image_decoder_dsc_t * dsc, const void * src, lv_color_t color, int32_t frame_id); +lv_result_t lv_image_decoder_open(lv_image_decoder_dsc_t * dsc, const void * src, const lv_image_decoder_args_t * args); /** * Decode an area of the opened image diff --git a/src/draw/sw/lv_draw_sw_arc.c b/src/draw/sw/lv_draw_sw_arc.c index 17a4926e3..c51ac5433 100644 --- a/src/draw/sw/lv_draw_sw_arc.c +++ b/src/draw/sw/lv_draw_sw_arc.c @@ -124,7 +124,7 @@ void lv_draw_sw_arc(lv_draw_unit_t * draw_unit, const lv_draw_arc_dsc_t * dsc, c } else { lv_image_decoder_dsc_t decoder_dsc; - lv_image_decoder_open(&decoder_dsc, dsc->img_src, dsc->color, 0); + 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; diff --git a/src/draw/sw/lv_draw_sw_img.c b/src/draw/sw/lv_draw_sw_img.c index 692468c31..6d6b0d6bf 100644 --- a/src/draw/sw/lv_draw_sw_img.c +++ b/src/draw/sw/lv_draw_sw_img.c @@ -195,7 +195,7 @@ static void img_draw_normal(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_ } lv_image_decoder_dsc_t decoder_dsc; - lv_result_t res = lv_image_decoder_open(&decoder_dsc, draw_dsc->src, draw_dsc->recolor, -1); + lv_result_t res = lv_image_decoder_open(&decoder_dsc, draw_dsc->src, NULL); if(res != LV_RESULT_OK) { LV_LOG_ERROR("Failed to open image"); return; @@ -210,7 +210,7 @@ static void img_draw_tiled(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t const lv_area_t * coords) { lv_image_decoder_dsc_t decoder_dsc; - lv_result_t res = lv_image_decoder_open(&decoder_dsc, draw_dsc->src, draw_dsc->recolor, -1); + lv_result_t res = lv_image_decoder_open(&decoder_dsc, draw_dsc->src, NULL); if(res != LV_RESULT_OK) { LV_LOG_ERROR("Failed to open image"); return; diff --git a/src/draw/sw/lv_draw_sw_vector.c b/src/draw/sw/lv_draw_sw_vector.c index bf024fccc..85bd392e5 100644 --- a/src/draw/sw/lv_draw_sw_vector.c +++ b/src/draw/sw/lv_draw_sw_vector.c @@ -291,7 +291,7 @@ static void _set_paint_fill_pattern(Tvg_Paint * obj, Tvg_Canvas * canvas, const const lv_matrix_t * m) { lv_image_decoder_dsc_t decoder_dsc; - lv_result_t res = lv_image_decoder_open(&decoder_dsc, p->src, p->recolor, -1); + lv_result_t res = lv_image_decoder_open(&decoder_dsc, p->src, NULL); if(res != LV_RESULT_OK) { LV_LOG_ERROR("Failed to open image"); return; diff --git a/src/libs/bin_decoder/lv_bin_decoder.c b/src/libs/bin_decoder/lv_bin_decoder.c index bfe3427d6..ee1eadd7e 100644 --- a/src/libs/bin_decoder/lv_bin_decoder.c +++ b/src/libs/bin_decoder/lv_bin_decoder.c @@ -134,11 +134,14 @@ lv_result_t lv_bin_decoder_info(lv_image_decoder_t * decoder, const void * src, * Open a lvgl binary image * @param decoder the decoder where this function belongs * @param dsc pointer to decoder descriptor. `src`, `color` are already initialized in it. + * @param args arguments of how to decode the image. * @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) +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_UNUSED(decoder); + LV_UNUSED(args); lv_fs_res_t res = LV_RESULT_INVALID; /*Open the file if it's a file*/ diff --git a/src/libs/bin_decoder/lv_bin_decoder.h b/src/libs/bin_decoder/lv_bin_decoder.h index 2966dac39..c5e6294f6 100644 --- a/src/libs/bin_decoder/lv_bin_decoder.h +++ b/src/libs/bin_decoder/lv_bin_decoder.h @@ -50,7 +50,8 @@ 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); +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); /** * Close the pending decoding. Free resources etc. diff --git a/src/libs/bmp/lv_bmp.c b/src/libs/bmp/lv_bmp.c index 5ef6cc420..95f718701 100644 --- a/src/libs/bmp/lv_bmp.c +++ b/src/libs/bmp/lv_bmp.c @@ -32,7 +32,8 @@ 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 * dec, lv_image_decoder_dsc_t * dsc); +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_get_area(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc, const lv_area_t * full_area, lv_area_t * decoded_area); @@ -139,9 +140,11 @@ static lv_result_t decoder_info(lv_image_decoder_t * decoder, const void * src, * @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 */ -static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc) +static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc, + const lv_image_decoder_args_t * args) { LV_UNUSED(decoder); + LV_UNUSED(args); /*If it's a PNG 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 34e6e3724..497a932bc 100644 --- a/src/libs/ffmpeg/lv_ffmpeg.c +++ b/src/libs/ffmpeg/lv_ffmpeg.c @@ -66,7 +66,8 @@ 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 * dec, lv_image_decoder_dsc_t * dsc); +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 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); @@ -268,9 +269,11 @@ 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) +static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc, + const lv_image_decoder_args_t * args) { 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 0c68c6eaf..0aa6a7b81 100644 --- a/src/libs/libjpeg_turbo/lv_libjpeg_turbo.c +++ b/src/libs/libjpeg_turbo/lv_libjpeg_turbo.c @@ -33,7 +33,8 @@ 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); +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 void decoder_close(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc); static const void * decode_jpeg_file(const char * filename); static bool get_jpeg_size(const char * filename, uint32_t * width, uint32_t * height); @@ -146,9 +147,11 @@ static lv_result_t decoder_info(lv_image_decoder_t * decoder, const void * src, * @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 */ -static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc) +static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc, + const lv_image_decoder_args_t * args) { LV_UNUSED(decoder); /*Unused*/ + LV_UNUSED(args); /*Unused*/ /*Check the cache first*/ if(try_cache(dsc) == LV_RESULT_OK) return LV_RESULT_OK; diff --git a/src/libs/libpng/lv_libpng.c b/src/libs/libpng/lv_libpng.c index f517a8c0b..fbd657dfe 100644 --- a/src/libs/libpng/lv_libpng.c +++ b/src/libs/libpng/lv_libpng.c @@ -24,7 +24,8 @@ * 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); +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 void decoder_close(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc); static const void * decode_png_file(const char * filename); static lv_result_t try_cache(lv_image_decoder_dsc_t * dsc); @@ -121,9 +122,11 @@ static lv_result_t decoder_info(lv_image_decoder_t * decoder, const void * src, * @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 */ -static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc) +static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc, + const lv_image_decoder_args_t * args) { LV_UNUSED(decoder); /*Unused*/ + LV_UNUSED(args); /*Unused*/ /*Check the cache first*/ if(try_cache(dsc) == LV_RESULT_OK) return LV_RESULT_OK; diff --git a/src/libs/lodepng/lv_lodepng.c b/src/libs/lodepng/lv_lodepng.c index db753ba06..4cbe69d6d 100644 --- a/src/libs/lodepng/lv_lodepng.c +++ b/src/libs/lodepng/lv_lodepng.c @@ -28,7 +28,8 @@ typedef struct { * STATIC PROTOTYPES **********************/ static lv_result_t decoder_info(struct _lv_image_decoder_t * decoder, const void * src, lv_image_header_t * header); -static lv_result_t decoder_open(lv_image_decoder_t * dec, lv_image_decoder_dsc_t * dsc); +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 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 const void * decode_png_data(const void * png_data, size_t png_data_size); @@ -154,9 +155,11 @@ static lv_result_t decoder_info(struct _lv_image_decoder_t * decoder, const void * @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) +static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc, + const lv_image_decoder_args_t * args) { - (void) decoder; /*Unused*/ + LV_UNUSED(decoder); + LV_UNUSED(args); /*Check the cache first*/ if(try_cache(dsc) == LV_RESULT_OK) return LV_RESULT_OK; diff --git a/src/libs/rle/lv_rle_decoder.c b/src/libs/rle/lv_rle_decoder.c index ac08ddce6..13d80f730 100644 --- a/src/libs/rle/lv_rle_decoder.c +++ b/src/libs/rle/lv_rle_decoder.c @@ -53,8 +53,8 @@ typedef struct { **********************/ static lv_res_t decoder_info(struct _lv_image_decoder_t * decoder, const void * src, lv_image_header_t * header); -static lv_res_t decoder_open(lv_image_decoder_t * dec, - lv_image_decoder_dsc_t * dsc); +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 void decoder_close(lv_image_decoder_t * dec, lv_image_decoder_dsc_t * dsc); /********************** @@ -452,9 +452,10 @@ static inline lv_res_t decode_from_variable(lv_image_decoder_t * decoder, return LV_RES_OK; } -static lv_res_t decoder_open(lv_image_decoder_t * decoder, - lv_image_decoder_dsc_t * dsc) +static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc, + const lv_image_decoder_args_t * args) { + LV_UNUSED(args); lv_fs_res_t res; lv_rle_file_header_t fileheader; lv_rle_decoder_data_t * data; @@ -491,7 +492,7 @@ static lv_res_t decoder_open(lv_image_decoder_t * decoder, data->decoder_dsc.src_type = LV_IMAGE_SRC_VARIABLE; data->decoder_dsc.src = &data->img_dsc; - res = lv_bin_decoder_open(decoder, &data->decoder_dsc); + res = lv_bin_decoder_open(decoder, &data->decoder_dsc, dsc->args); if(res != LV_RES_OK) { lv_free(img_data); lv_free(data); diff --git a/src/libs/tjpgd/lv_tjpgd.c b/src/libs/tjpgd/lv_tjpgd.c index e9fc2d6bc..fb618b41f 100644 --- a/src/libs/tjpgd/lv_tjpgd.c +++ b/src/libs/tjpgd/lv_tjpgd.c @@ -27,7 +27,8 @@ * 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); +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_get_area(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc, const lv_area_t * full_area, lv_area_t * decoded_area); @@ -142,9 +143,11 @@ 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) +static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc, + const lv_image_decoder_args_t * args) { 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