feat(decoder): remove img_data and use decoded draw buffer instead (#4985)
Signed-off-by: Xu Xingliang <xuxingliang@xiaomi.com>
This commit is contained in:
@@ -258,7 +258,7 @@ open/close the PNG files. It should look like this:
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a PNG image and decode it into dsc.img_data
|
||||
* Open a PNG image and decode it into dsc.decoded
|
||||
* @param decoder pointer to the decoder where this function belongs
|
||||
* @param dsc image descriptor
|
||||
* @return LV_RESULT_OK: no error; LV_RESULT_INVALID: can't open the image
|
||||
@@ -270,11 +270,11 @@ open/close the PNG files. It should look like this:
|
||||
/*Check whether the type `src` is known by the decoder*/
|
||||
if(is_png(dsc->src) == false) return LV_RESULT_INVALID;
|
||||
|
||||
/*Decode and store the image. If `dsc->img_data` is `NULL`, the `read_line` function will be called to get the image data line-by-line*/
|
||||
dsc->img_data = my_png_decoder(dsc->src);
|
||||
/*Decode and store the image. If `dsc->decoded` is `NULL`, the `read_line` function will be called to get the image data line-by-line*/
|
||||
dsc->decoded = my_png_decoder(dsc->src);
|
||||
|
||||
/*Change the color format if required. For PNG usually 'Raw' is fine*/
|
||||
dsc->header.cf = LV_COLOR_FORMAT_...
|
||||
/*Change the color format if decoded image format is different than original format. For PNG it's usually decoded to ARGB8888 format*/
|
||||
dsc->decoded.header.cf = LV_COLOR_FORMAT_...
|
||||
|
||||
/*Call a binary image decoder function if required. It's not required if `my_png_decoder` opened the image in true color format.*/
|
||||
lv_result_t res = lv_bin_decoder_open(decoder, dsc);
|
||||
@@ -316,13 +316,13 @@ So in summary:
|
||||
- In ``decoder_open``, you should try to open the image source pointed by
|
||||
``dsc->src``. Its type is already in ``dsc->src_type == LV_IMG_SRC_FILE/VARIABLE``.
|
||||
If this format/type is not supported by the decoder, return :cpp:enumerator:`LV_RESULT_INVALID`.
|
||||
However, if you can open the image, a pointer to the decoded *True color* image should be
|
||||
set in ``dsc->img_data``. If the format is known, but you don't want to
|
||||
decode the entire image (e.g. no memory for it), set ``dsc->img_data = NULL`` and
|
||||
However, if you can open the image, a pointer to the decoded image should be
|
||||
set in ``dsc->decoded``. If the format is known, but you don't want to
|
||||
decode the entire image (e.g. no memory for it), set ``dsc->decoded = NULL`` and
|
||||
use ``decoder_get_area`` to get the image area pixels.
|
||||
- In ``decoder_close`` you should free all allocated resources.
|
||||
- ``decoder_get_area`` is optional. In this case you should decode the whole image In
|
||||
``decoder_open`` function and store image data in ``dsc->img_data``.
|
||||
``decoder_open`` function and store image data in ``dsc->decoded``.
|
||||
Decoding the whole image requires extra memory and some computational overhead.
|
||||
|
||||
|
||||
@@ -346,7 +346,7 @@ images to tell color of the image.
|
||||
res = lv_image_decoder_open(&dsc, &my_img_dsc, &args);
|
||||
|
||||
if(res == LV_RESULT_OK) {
|
||||
/*Do something with `dsc->img_data`*/
|
||||
/*Do something with `dsc->decoded`. You can copy out the decoded image by `lv_draw_buf_dup(dsc.decoded)`*/
|
||||
lv_image_decoder_close(&dsc);
|
||||
}
|
||||
|
||||
@@ -385,61 +385,26 @@ See the detailed code below:
|
||||
lv_cache_entry_t * entry = dsc->cache_entry;
|
||||
|
||||
if(!(entry->process_state & IMAGE_PROCESS_STATE_PREMULTIPLIED_ALPHA)) {
|
||||
lv_color32_t * image = (lv_color32_t *)dsc->img_data;
|
||||
uint32_t px_cnt = dsc->header.w * dsc->header.h;
|
||||
|
||||
/* premultiply alpha */
|
||||
while(px_cnt--) {
|
||||
image->red = LV_UDIV255(image->red * image->alpha);
|
||||
image->green = LV_UDIV255(image->green * image->alpha);
|
||||
image->blue = LV_UDIV255(image->blue * image->alpha);
|
||||
image++;
|
||||
}
|
||||
|
||||
lv_draw_buf_premultiply(dsc->decoded);
|
||||
LV_LOG_USER("premultiplied alpha OK");
|
||||
|
||||
entry->process_state |= IMAGE_PROCESS_STATE_PREMULTIPLIED_ALPHA;
|
||||
}
|
||||
|
||||
if(!(entry->process_state & IMAGE_PROCESS_STATE_STRIDE_ALIGNED)) {
|
||||
int32_t image_w = dsc->header.w;
|
||||
int32_t image_h = dsc->header.h;
|
||||
uint32_t width_byte = image_w * lv_color_format_get_size(color_format);
|
||||
uint32_t stride = lv_draw_buf_width_to_stride(image_w, color_format);
|
||||
uint32_t stride_expect = lv_draw_buf_width_to_stride(decoded->header.w, decoded->header.cf);
|
||||
if(decoded->header.stride != stride_expect) {
|
||||
LV_LOG_WARN("Stride mismatch");
|
||||
lv_draw_buf_t * aligned = lv_draw_buf_adjust_stride(decoded, stride_expect);
|
||||
if(aligned == NULL) {
|
||||
LV_LOG_ERROR("No memory for Stride adjust.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Check stride alignment requirements */
|
||||
if(stride != width_byte) {
|
||||
LV_LOG_USER("need to realign stride: %" LV_PRIu32 " -> %" LV_PRIu32, width_byte, stride);
|
||||
decoded = aligned;
|
||||
}
|
||||
|
||||
const uint8_t * ori_image = lv_cache_get_data(entry);
|
||||
size_t size_bytes = stride * dsc->header.h;
|
||||
uint8_t * new_image = lv_draw_buf_malloc(size_bytes, color_format);
|
||||
if(!new_image) {
|
||||
LV_LOG_ERROR("alloc failed");
|
||||
res = LV_RESULT_INVALID;
|
||||
goto alloc_failed;
|
||||
}
|
||||
|
||||
/* Replace the image data pointer */
|
||||
entry->data = new_image;
|
||||
dsc->img_data = new_image;
|
||||
|
||||
/* Copy image data */
|
||||
const uint8_t * cur = ori_image;
|
||||
for(int32_t y = 0; y < image_h; y++) {
|
||||
lv_memcpy(new_image, cur, width_byte);
|
||||
new_image += stride;
|
||||
cur += width_byte;
|
||||
}
|
||||
|
||||
/* free memory for old image */
|
||||
lv_draw_buf_free((void *)ori_image);
|
||||
}
|
||||
else {
|
||||
LV_LOG_USER("no need to realign stride: %" LV_PRIu32, stride);
|
||||
}
|
||||
|
||||
entry->process_state |= IMAGE_PROCESS_STATE_STRIDE_ALIGNED;
|
||||
entry->process_state |= IMAGE_PROCESS_STATE_STRIDE_ALIGNED;
|
||||
}
|
||||
|
||||
alloc_failed:
|
||||
@@ -482,7 +447,7 @@ inefficient and detrimental to the user experience.
|
||||
|
||||
Therefore, LVGL caches image data. Caching means some
|
||||
images will be left open, hence LVGL can quickly access them from
|
||||
``dsc->img_data`` instead of needing to decode them again.
|
||||
``dsc->decoded`` instead of needing to decode them again.
|
||||
|
||||
Of course, caching images is resource intensive as it uses more RAM to
|
||||
store the decoded image. LVGL tries to optimize the process as much as
|
||||
|
||||
Reference in New Issue
Block a user