mirror of
https://github.com/lvgl/lvgl.git
synced 2024-11-23 17:53:45 +08:00
feat(decoder): add image header cache (#5407)
This commit is contained in:
parent
356f3ed018
commit
d26eac8f3a
@ -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
|
||||
|
12
Kconfig
12
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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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*/
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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*/
|
||||
|
@ -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.
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user