From daa7fefb3a4bd058f1c5b5166871085876d0ada4 Mon Sep 17 00:00:00 2001 From: Benign X <1341398182@qq.com> Date: Tue, 16 Apr 2024 16:21:32 +0800 Subject: [PATCH] feat(image_decoder): refactor image decoder to reduce file operation on get_info --- src/draw/lv_image_decoder.h | 4 +- src/draw/vg_lite/lv_vg_lite_decoder.c | 6 +-- src/libs/bin_decoder/lv_bin_decoder.c | 49 +++++++++++------------ src/libs/bin_decoder/lv_bin_decoder.h | 4 +- src/libs/bmp/lv_bmp.c | 15 +++---- src/libs/ffmpeg/lv_ffmpeg.c | 7 ++-- src/libs/libjpeg_turbo/lv_libjpeg_turbo.c | 32 ++++++--------- src/libs/libpng/lv_libpng.c | 18 +++------ src/libs/lodepng/lv_lodepng.c | 21 +++++----- src/libs/tjpgd/lv_tjpgd.c | 19 ++++----- 10 files changed, 75 insertions(+), 100 deletions(-) diff --git a/src/draw/lv_image_decoder.h b/src/draw/lv_image_decoder.h index 82691609e..411bd2cb1 100644 --- a/src/draw/lv_image_decoder.h +++ b/src/draw/lv_image_decoder.h @@ -72,7 +72,7 @@ typedef struct _lv_image_decoder_args_t { * @param header store the info here * @return LV_RESULT_OK: info written correctly; LV_RESULT_INVALID: failed */ -typedef lv_result_t (*lv_image_decoder_info_f_t)(lv_image_decoder_t * decoder, const void * src, +typedef lv_result_t (*lv_image_decoder_info_f_t)(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc, lv_image_header_t * header); /** @@ -147,7 +147,7 @@ struct _lv_image_decoder_dsc_t { /**Type of the source: file or variable. Can be set in `open` function if required*/ lv_image_src_t src_type; - lv_fs_file_t * fp; + lv_fs_file_t file; /**Info about the opened image: color format, size, etc. MUST be set in `open` function*/ lv_image_header_t header; diff --git a/src/draw/vg_lite/lv_vg_lite_decoder.c b/src/draw/vg_lite/lv_vg_lite_decoder.c index c433e92b3..822db0dfb 100644 --- a/src/draw/vg_lite/lv_vg_lite_decoder.c +++ b/src/draw/vg_lite/lv_vg_lite_decoder.c @@ -43,7 +43,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_info(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * src, lv_image_header_t * header); 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 image_color32_pre_mul(lv_color32_t * img_data, uint32_t px_size); @@ -148,9 +148,9 @@ static void image_decode_to_index8_line(uint8_t * dest, const uint8_t * src, int } } -static lv_result_t decoder_info(lv_image_decoder_t * decoder, const void * src, lv_image_header_t * header) +static lv_result_t decoder_info(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc, lv_image_header_t * header) { - lv_result_t res = lv_bin_decoder_info(decoder, src, header); + lv_result_t res = lv_bin_decoder_info(decoder, dsc, header); if(res != LV_RESULT_OK) { return res; } diff --git a/src/libs/bin_decoder/lv_bin_decoder.c b/src/libs/bin_decoder/lv_bin_decoder.c index 5000982b9..5e8a5dbf6 100644 --- a/src/libs/bin_decoder/lv_bin_decoder.c +++ b/src/libs/bin_decoder/lv_bin_decoder.c @@ -110,11 +110,13 @@ void lv_bin_decoder_init(void) decoder->name = DECODER_NAME; } -lv_result_t lv_bin_decoder_info(lv_image_decoder_t * decoder, const void * src, lv_image_header_t * header) +lv_result_t lv_bin_decoder_info(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc, lv_image_header_t * header) { LV_UNUSED(decoder); /*Unused*/ - lv_image_src_t src_type = lv_image_src_get_type(src); + const void * src = dsc->src; + lv_image_src_t src_type = dsc->src_type; + if(src_type == LV_IMAGE_SRC_VARIABLE) { lv_image_dsc_t * image = (lv_image_dsc_t *)src; lv_memcpy(header, &image->header, sizeof(lv_image_header_t)); @@ -123,31 +125,28 @@ lv_result_t lv_bin_decoder_info(lv_image_decoder_t * decoder, const void * src, /*Support only "*.bin" files*/ if(lv_strcmp(lv_fs_get_ext(src), "bin")) return LV_RESULT_INVALID; - lv_fs_file_t f; - lv_fs_res_t res = lv_fs_open(&f, src, LV_FS_MODE_RD); - if(res == LV_FS_RES_OK) { - uint32_t rn; - res = lv_fs_read(&f, header, sizeof(lv_image_header_t), &rn); - lv_fs_close(&f); - if(res != LV_FS_RES_OK || rn != sizeof(lv_image_header_t)) { - LV_LOG_WARN("Read file header failed: %d", res); - return LV_RESULT_INVALID; - } + lv_fs_res_t res; + uint32_t rn; + res = lv_fs_read(&dsc->file, header, sizeof(lv_image_header_t), &rn); - /** - * @todo - * This is a temp backward compatibility solution after adding - * magic in image header. - */ - if(header->magic != LV_IMAGE_HEADER_MAGIC) { - LV_LOG_WARN("Legacy bin image detected: %s", (char *)src); - header->cf = header->magic; - header->magic = LV_IMAGE_HEADER_MAGIC; - } - - /*File is always read to buf, thus data can be modified.*/ - header->flags |= LV_IMAGE_FLAGS_MODIFIABLE; + if(res != LV_FS_RES_OK || rn != sizeof(lv_image_header_t)) { + LV_LOG_WARN("Read file header failed: %d", res); + return LV_RESULT_INVALID; } + + /** + * @todo + * This is a temp backward compatibility solution after adding + * magic in image header. + */ + if(header->magic != LV_IMAGE_HEADER_MAGIC) { + LV_LOG_WARN("Legacy bin image detected: %s", (char *)src); + header->cf = header->magic; + header->magic = LV_IMAGE_HEADER_MAGIC; + } + + /*File is always read to buf, thus data can be modified.*/ + header->flags |= LV_IMAGE_FLAGS_MODIFIABLE; } else if(src_type == LV_IMAGE_SRC_SYMBOL) { /*The size depend on the font but it is unknown here. It should be handled outside of the diff --git a/src/libs/bin_decoder/lv_bin_decoder.h b/src/libs/bin_decoder/lv_bin_decoder.h index 2966dac39..d441230d0 100644 --- a/src/libs/bin_decoder/lv_bin_decoder.h +++ b/src/libs/bin_decoder/lv_bin_decoder.h @@ -35,11 +35,11 @@ void lv_bin_decoder_init(void); /** * Get info about a lvgl binary image * @param decoder the decoder where this function belongs - * @param src the image source: pointer to an `lv_image_dsc_t` variable, a file path or a symbol + * @param dsc image descriptor containing the source and type of the image and other info. * @param header store the image data here * @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_info(lv_image_decoder_t * decoder, const void * src, lv_image_header_t * header); +lv_result_t lv_bin_decoder_info(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc, lv_image_header_t * header); lv_result_t lv_bin_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); diff --git a/src/libs/bmp/lv_bmp.c b/src/libs/bmp/lv_bmp.c index 515324be5..f23ae6ceb 100644 --- a/src/libs/bmp/lv_bmp.c +++ b/src/libs/bmp/lv_bmp.c @@ -35,7 +35,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_info(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * 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_get_area(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc, @@ -82,34 +82,31 @@ void lv_bmp_deinit(void) /** * Get info about a BMP image - * @param src can be file name or pointer to a C array + * @param dsc image descriptor containing the source and type of the image and other info. * @param header store the info here * @return LV_RESULT_OK: no error; LV_RESULT_INVALID: can't get the info */ -static lv_result_t decoder_info(lv_image_decoder_t * decoder, const void * src, lv_image_header_t * header) +static lv_result_t decoder_info(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc, lv_image_header_t * header) { LV_UNUSED(decoder); - lv_image_src_t src_type = lv_image_src_get_type(src); /*Get the source type*/ + const void * src = dsc->src; + lv_image_src_t src_type = dsc->src_type; /*Get the source type*/ /*If it's a BMP file...*/ if(src_type == LV_IMAGE_SRC_FILE) { const char * fn = src; if(lv_strcmp(lv_fs_get_ext(fn), "bmp") == 0) { /*Check the extension*/ /*Save the data in the header*/ - lv_fs_file_t f; - lv_fs_res_t res = lv_fs_open(&f, src, LV_FS_MODE_RD); - if(res != LV_FS_RES_OK) return LV_RESULT_INVALID; uint8_t headers[54]; - lv_fs_read(&f, headers, 54, NULL); + lv_fs_read(&dsc->file, headers, 54, NULL); uint32_t w; uint32_t h; lv_memcpy(&w, headers + 18, 4); lv_memcpy(&h, headers + 22, 4); header->w = w; header->h = h; - lv_fs_close(&f); uint16_t bpp; lv_memcpy(&bpp, headers + 28, 2); diff --git a/src/libs/ffmpeg/lv_ffmpeg.c b/src/libs/ffmpeg/lv_ffmpeg.c index bf09dbc3a..a86a6627d 100644 --- a/src/libs/ffmpeg/lv_ffmpeg.c +++ b/src/libs/ffmpeg/lv_ffmpeg.c @@ -69,7 +69,7 @@ struct lv_image_pixel_color_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_info(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * src, lv_image_header_t * header); 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); @@ -253,12 +253,13 @@ void lv_ffmpeg_player_set_auto_restart(lv_obj_t * obj, bool en) * STATIC FUNCTIONS **********************/ -static lv_result_t decoder_info(lv_image_decoder_t * decoder, const void * src, lv_image_header_t * header) +static lv_result_t decoder_info(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc, lv_image_header_t * header) { LV_UNUSED(decoder); /* Get the source type */ - lv_image_src_t src_type = lv_image_src_get_type(src); + const void * src = dsc->src; + lv_image_src_t src_type = dsc->src_type; if(src_type == LV_IMAGE_SRC_FILE) { const char * fn = src; diff --git a/src/libs/libjpeg_turbo/lv_libjpeg_turbo.c b/src/libs/libjpeg_turbo/lv_libjpeg_turbo.c index f82834c24..c4309be7f 100644 --- a/src/libs/libjpeg_turbo/lv_libjpeg_turbo.c +++ b/src/libs/libjpeg_turbo/lv_libjpeg_turbo.c @@ -38,7 +38,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_info(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc, lv_image_header_t * header); 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); @@ -98,42 +98,34 @@ void lv_libjpeg_turbo_deinit(void) /** * Get info about a JPEG image - * @param src can be file name or pointer to a C array + * @param dsc image descriptor containing the source and type of the image and other info. * @param header store the info here * @return LV_RESULT_OK: no error; LV_RESULT_INVALID: can't get the info */ -static lv_result_t decoder_info(lv_image_decoder_t * decoder, const void * src, lv_image_header_t * header) +static lv_result_t decoder_info(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc, lv_image_header_t * header) { LV_UNUSED(decoder); /*Unused*/ - lv_image_src_t src_type = lv_image_src_get_type(src); /*Get the source type*/ + lv_image_src_t src_type = dsc->src_type; /*Get the source type*/ /*If it's a JPEG file...*/ if(src_type == LV_IMAGE_SRC_FILE) { - const char * fn = src; - - lv_fs_file_t f; - lv_fs_res_t res = lv_fs_open(&f, fn, LV_FS_MODE_RD); - if(res != LV_FS_RES_OK) { - LV_LOG_WARN("Can't open file: %s", fn); - return LV_RESULT_INVALID; - } - + const char * src = dsc->src; uint32_t jpg_signature = 0; uint32_t rn; - lv_fs_read(&f, &jpg_signature, sizeof(jpg_signature), &rn); - lv_fs_close(&f); + lv_fs_read(&dsc->file, &jpg_signature, sizeof(jpg_signature), &rn); if(rn != sizeof(jpg_signature)) { - LV_LOG_WARN("file: %s signature len = %" LV_PRIu32 " error", fn, rn); + LV_LOG_WARN("file: %s signature len = %" LV_PRIu32 " error", src, rn); return LV_RESULT_INVALID; } - bool is_jpeg_ext = (lv_strcmp(lv_fs_get_ext(fn), "jpg") == 0) - || (lv_strcmp(lv_fs_get_ext(fn), "jpeg") == 0); + const char * ext = lv_fs_get_ext(src); + bool is_jpeg_ext = (lv_strcmp(ext, "jpg") == 0) + || (lv_strcmp(ext, "jpeg") == 0); if(!IS_JPEG_SIGNATURE(jpg_signature)) { if(is_jpeg_ext) { - LV_LOG_WARN("file: %s signature = 0X%" LV_PRIX32 " error", fn, jpg_signature); + LV_LOG_WARN("file: %s signature = 0X%" LV_PRIX32 " error", src, jpg_signature); } return LV_RESULT_INVALID; } @@ -142,7 +134,7 @@ static lv_result_t decoder_info(lv_image_decoder_t * decoder, const void * src, uint32_t height; uint32_t orientation = 0; - if(!get_jpeg_head_info(fn, &width, &height, &orientation)) { + if(!get_jpeg_head_info(src, &width, &height, &orientation)) { return LV_RESULT_INVALID; } diff --git a/src/libs/libpng/lv_libpng.c b/src/libs/libpng/lv_libpng.c index 5e2f55c35..738834f84 100644 --- a/src/libs/libpng/lv_libpng.c +++ b/src/libs/libpng/lv_libpng.c @@ -28,7 +28,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_info(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * src, lv_image_header_t * header); 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(lv_image_decoder_dsc_t * dsc, const char * filename); @@ -75,31 +75,25 @@ void lv_libpng_deinit(void) /** * Get info about a PNG image - * @param src can be file name or pointer to a C array + * @param dsc can be file name or pointer to a C array * @param header store the info here * @return LV_RESULT_OK: no error; LV_RESULT_INVALID: can't get the info */ -static lv_result_t decoder_info(lv_image_decoder_t * decoder, const void * src, lv_image_header_t * header) +static lv_result_t decoder_info(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc, lv_image_header_t * header) { LV_UNUSED(decoder); /*Unused*/ - lv_image_src_t src_type = lv_image_src_get_type(src); /*Get the source type*/ + + lv_image_src_t src_type = dsc->src_type; /*Get the source type*/ /*If it's a PNG file...*/ if(src_type == LV_IMAGE_SRC_FILE) { - const char * fn = src; - - lv_fs_file_t f; - lv_fs_res_t res = lv_fs_open(&f, fn, LV_FS_MODE_RD); - if(res != LV_FS_RES_OK) return LV_RESULT_INVALID; - /* Read the width and height from the file. They have a constant location: * [16..19]: width * [20..23]: height */ uint8_t buf[24]; uint32_t rn; - lv_fs_read(&f, buf, sizeof(buf), &rn); - lv_fs_close(&f); + lv_fs_read(&dsc->file, buf, sizeof(buf), &rn); if(rn != sizeof(buf)) return LV_RESULT_INVALID; diff --git a/src/libs/lodepng/lv_lodepng.c b/src/libs/lodepng/lv_lodepng.c index f690b7b19..7e7ec22a9 100644 --- a/src/libs/lodepng/lv_lodepng.c +++ b/src/libs/lodepng/lv_lodepng.c @@ -28,7 +28,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_info(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * src, lv_image_header_t * header); 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); @@ -76,14 +76,16 @@ void lv_lodepng_deinit(void) /** * Get info about a PNG image * @param decoder pointer to the decoder where this function belongs - * @param src can be file name or pointer to a C array + * @param dsc image descriptor containing the source and type of the image and other info. * @param header image information is set in header parameter * @return LV_RESULT_OK: no error; LV_RESULT_INVALID: can't get the info */ -static lv_result_t decoder_info(lv_image_decoder_t * decoder, const void * src, lv_image_header_t * header) +static lv_result_t decoder_info(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc, lv_image_header_t * header) { LV_UNUSED(decoder); /*Unused*/ - lv_image_src_t src_type = lv_image_src_get_type(src); /*Get the source type*/ + + const void * src = dsc->src; + lv_image_src_t src_type = dsc->src_type; /*Get the source type*/ /*If it's a PNG file...*/ if(src_type == LV_IMAGE_SRC_FILE) { @@ -95,15 +97,10 @@ static lv_result_t decoder_info(lv_image_decoder_t * decoder, const void * src, * [24..27]: height */ uint32_t size[2]; - lv_fs_file_t f; - lv_fs_res_t res = lv_fs_open(&f, fn, LV_FS_MODE_RD); - if(res != LV_FS_RES_OK) return LV_RESULT_INVALID; - - lv_fs_seek(&f, 16, LV_FS_SEEK_SET); - uint32_t rn; - lv_fs_read(&f, &size, 8, &rn); - lv_fs_close(&f); + + lv_fs_seek(&dsc->file, 16, LV_FS_SEEK_SET); + lv_fs_read(&dsc->file, &size, 8, &rn); if(rn != 8) return LV_RESULT_INVALID; diff --git a/src/libs/tjpgd/lv_tjpgd.c b/src/libs/tjpgd/lv_tjpgd.c index 7c87f1993..551a03dac 100644 --- a/src/libs/tjpgd/lv_tjpgd.c +++ b/src/libs/tjpgd/lv_tjpgd.c @@ -30,7 +30,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_info(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc, 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_get_area(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc, @@ -77,11 +77,12 @@ void lv_tjpgd_deinit(void) * STATIC FUNCTIONS **********************/ -static lv_result_t decoder_info(lv_image_decoder_t * decoder, const void * src, lv_image_header_t * header) +static lv_result_t decoder_info(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc, lv_image_header_t * header) { LV_UNUSED(decoder); - lv_image_src_t src_type = lv_image_src_get_type(src); + const void * src = dsc->src; + lv_image_src_t src_type = dsc->src_type; if(src_type == LV_IMAGE_SRC_VARIABLE) { const lv_image_dsc_t * img_dsc = src; @@ -103,18 +104,13 @@ static lv_result_t decoder_info(lv_image_decoder_t * decoder, const void * src, } else if(src_type == LV_IMAGE_SRC_FILE) { const char * fn = src; - if((lv_strcmp(lv_fs_get_ext(fn), "jpg") == 0) || (lv_strcmp(lv_fs_get_ext(fn), "jpeg") == 0)) { - lv_fs_file_t f; - lv_fs_res_t res; - res = lv_fs_open(&f, fn, LV_FS_MODE_RD); - if(res != LV_FS_RES_OK) return LV_RESULT_INVALID; - + const char * ext = lv_fs_get_ext(fn); + if((lv_strcmp(ext, "jpg") == 0) || (lv_strcmp(ext, "jpeg") == 0)) { uint8_t workb[TJPGD_WORKBUFF_SIZE]; JDEC jd; - JRESULT rc = jd_prepare(&jd, input_func, workb, TJPGD_WORKBUFF_SIZE, &f); + JRESULT rc = jd_prepare(&jd, input_func, workb, TJPGD_WORKBUFF_SIZE, &dsc->file); if(rc) { LV_LOG_WARN("jd_prepare error: %d", rc); - lv_fs_close(&f); return LV_RESULT_INVALID; } header->cf = LV_COLOR_FORMAT_RAW; @@ -122,7 +118,6 @@ static lv_result_t decoder_info(lv_image_decoder_t * decoder, const void * src, header->h = jd.height; header->stride = jd.width * 3; - lv_fs_close(&f); return LV_RESULT_OK; } }