mirror of
https://github.com/lvgl/lvgl.git
synced 2025-01-28 07:03:00 +08:00
feat(png): use draw_buf for decoded image (#4968)
Signed-off-by: Xu Xingliang <xuxingliang@xiaomi.com>
This commit is contained in:
parent
d3ef971479
commit
99b80ec089
@ -154,6 +154,7 @@ lv_result_t lv_image_decoder_open(lv_image_decoder_dsc_t * dsc, const void * src
|
|||||||
|
|
||||||
dsc->error_msg = NULL;
|
dsc->error_msg = NULL;
|
||||||
dsc->img_data = NULL;
|
dsc->img_data = NULL;
|
||||||
|
dsc->decoded = NULL;
|
||||||
dsc->cache_entry = NULL;
|
dsc->cache_entry = NULL;
|
||||||
dsc->user_data = NULL;
|
dsc->user_data = NULL;
|
||||||
dsc->time_to_open = 0;
|
dsc->time_to_open = 0;
|
||||||
|
@ -16,7 +16,7 @@ extern "C" {
|
|||||||
#include "../lv_conf_internal.h"
|
#include "../lv_conf_internal.h"
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "lv_image_buf.h"
|
#include "lv_draw_buf.h"
|
||||||
#include "../misc/lv_fs.h"
|
#include "../misc/lv_fs.h"
|
||||||
#include "../misc/lv_types.h"
|
#include "../misc/lv_types.h"
|
||||||
#include "../misc/lv_area.h"
|
#include "../misc/lv_area.h"
|
||||||
@ -136,6 +136,8 @@ typedef struct _lv_image_decoder_dsc_t {
|
|||||||
* MUST be set in `open` function*/
|
* MUST be set in `open` function*/
|
||||||
const uint8_t * img_data;
|
const uint8_t * img_data;
|
||||||
|
|
||||||
|
const lv_draw_buf_t * decoded; /*A draw buffer to described decoded image.*/
|
||||||
|
|
||||||
const lv_color32_t * palette;
|
const lv_color32_t * palette;
|
||||||
uint32_t palette_size;
|
uint32_t palette_size;
|
||||||
|
|
||||||
@ -158,6 +160,14 @@ typedef struct _lv_image_decoder_dsc_t {
|
|||||||
* GLOBAL PROTOTYPES
|
* GLOBAL PROTOTYPES
|
||||||
**********************/
|
**********************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @todo remove it when all decoder migrates to new draw buf interface.
|
||||||
|
*/
|
||||||
|
static inline const void * _lv_image_decoder_get_data(const lv_image_decoder_dsc_t * dsc)
|
||||||
|
{
|
||||||
|
return dsc->decoded ? dsc->decoded->data : dsc->img_data;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the image decoder module
|
* Initialize the image decoder module
|
||||||
*/
|
*/
|
||||||
|
@ -131,7 +131,7 @@ void lv_draw_sw_arc(lv_draw_unit_t * draw_unit, const lv_draw_arc_dsc_t * dsc, c
|
|||||||
int32_t ofs = decoder_dsc.header.w / 2;
|
int32_t ofs = decoder_dsc.header.w / 2;
|
||||||
lv_area_move(&img_area, dsc->center.x - ofs, dsc->center.y - ofs);
|
lv_area_move(&img_area, dsc->center.x - ofs, dsc->center.y - ofs);
|
||||||
blend_dsc.src_area = &img_area;
|
blend_dsc.src_area = &img_area;
|
||||||
blend_dsc.src_buf = decoder_dsc.img_data;
|
blend_dsc.src_buf = _lv_image_decoder_get_data(&decoder_dsc);
|
||||||
blend_dsc.src_color_format = decoder_dsc.header.cf;
|
blend_dsc.src_color_format = decoder_dsc.header.cf;
|
||||||
blend_dsc.src_stride = decoder_dsc.header.stride;
|
blend_dsc.src_stride = decoder_dsc.header.stride;
|
||||||
}
|
}
|
||||||
|
@ -253,7 +253,7 @@ static void img_decode_and_draw(lv_draw_unit_t * draw_unit, const lv_draw_image_
|
|||||||
sup.palette_size = decoder_dsc->palette_size;
|
sup.palette_size = decoder_dsc->palette_size;
|
||||||
|
|
||||||
/*The whole image is available, just draw it*/
|
/*The whole image is available, just draw it*/
|
||||||
if(decoder_dsc->img_data) {
|
if(decoder_dsc->decoded || decoder_dsc->img_data) {
|
||||||
img_draw_core(draw_unit, draw_dsc, decoder_dsc, &sup, img_area, clipped_img_area);
|
img_draw_core(draw_unit, draw_dsc, decoder_dsc, &sup, img_area, clipped_img_area);
|
||||||
}
|
}
|
||||||
/*Draw in smaller pieces*/
|
/*Draw in smaller pieces*/
|
||||||
@ -298,7 +298,13 @@ static void img_draw_core(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t
|
|||||||
uint32_t img_stride = header->stride;
|
uint32_t img_stride = header->stride;
|
||||||
lv_color_format_t cf = header->cf;
|
lv_color_format_t cf = header->cf;
|
||||||
|
|
||||||
cf = LV_COLOR_FORMAT_IS_INDEXED(cf) ? LV_COLOR_FORMAT_ARGB8888 : cf,
|
cf = LV_COLOR_FORMAT_IS_INDEXED(cf) ? LV_COLOR_FORMAT_ARGB8888 : cf;
|
||||||
|
|
||||||
|
if(decoder_dsc->decoded) {
|
||||||
|
src_buf = decoder_dsc->decoded->data;
|
||||||
|
img_stride = decoder_dsc->decoded->header.stride;
|
||||||
|
cf = decoder_dsc->decoded->header.cf;
|
||||||
|
}
|
||||||
|
|
||||||
lv_memzero(&blend_dsc, sizeof(lv_draw_sw_blend_dsc_t));
|
lv_memzero(&blend_dsc, sizeof(lv_draw_sw_blend_dsc_t));
|
||||||
blend_dsc.opa = draw_dsc->opa;
|
blend_dsc.opa = draw_dsc->opa;
|
||||||
|
@ -297,13 +297,13 @@ static void _set_paint_fill_pattern(Tvg_Paint * obj, Tvg_Canvas * canvas, const
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!decoder_dsc.img_data) {
|
if(!decoder_dsc.decoded && !decoder_dsc.img_data) {
|
||||||
lv_image_decoder_close(&decoder_dsc);
|
lv_image_decoder_close(&decoder_dsc);
|
||||||
LV_LOG_ERROR("Image not ready");
|
LV_LOG_ERROR("Image not ready");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint8_t * src_buf = decoder_dsc.img_data;
|
const uint8_t * src_buf = _lv_image_decoder_get_data(&decoder_dsc);
|
||||||
const lv_image_header_t * header = &decoder_dsc.header;
|
const lv_image_header_t * header = &decoder_dsc.header;
|
||||||
lv_color_format_t cf = header->cf;
|
lv_color_format_t cf = header->cf;
|
||||||
|
|
||||||
|
@ -37,10 +37,12 @@ typedef struct _lv_image_compressed_t {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
lv_fs_file_t * f;
|
lv_fs_file_t * f;
|
||||||
lv_color32_t * palette;
|
lv_color32_t * palette;
|
||||||
uint8_t * img_data;
|
|
||||||
lv_opa_t * opa;
|
lv_opa_t * opa;
|
||||||
uint8_t * decompressed;
|
|
||||||
lv_image_compressed_t compressed;
|
lv_image_compressed_t compressed;
|
||||||
|
lv_draw_buf_t * decoded; /*A draw buf to store decoded image*/
|
||||||
|
lv_draw_buf_t * decompressed; /*Decompressed data could be used directly, thus must also be draw buf*/
|
||||||
|
lv_draw_buf_t c_array; /*An C-array image that need to be converted to a draw buf*/
|
||||||
|
lv_draw_buf_t * decoded_partial; /*A draw buf for decoded image via get_area_cb*/
|
||||||
} decoder_data_t;
|
} decoder_data_t;
|
||||||
|
|
||||||
/**********************
|
/**********************
|
||||||
@ -258,7 +260,35 @@ lv_result_t lv_bin_decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_d
|
|||||||
else {
|
else {
|
||||||
/*In case of uncompressed formats the image stored in the ROM/RAM.
|
/*In case of uncompressed formats the image stored in the ROM/RAM.
|
||||||
*So simply give its pointer*/
|
*So simply give its pointer*/
|
||||||
dsc->img_data = ((lv_image_dsc_t *)dsc->src)->data;
|
|
||||||
|
decoder_data_t * decoder_data = get_decoder_data(dsc);
|
||||||
|
lv_draw_buf_t * decoded = &decoder_data->c_array;
|
||||||
|
dsc->decoded = decoded;
|
||||||
|
lv_draw_buf_from_image(decoded, image);
|
||||||
|
|
||||||
|
if(decoded->header.stride == 0) {
|
||||||
|
/*Use the auto calculated value from decoder_info callback*/
|
||||||
|
decoded->header.stride = dsc->header.stride;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @todo need to convert c-array image stride if not match
|
||||||
|
*
|
||||||
|
* lv_draw_buf_create(); //create new draw buf that meets requirement
|
||||||
|
* lv_draw_buf_copy(); //copy from c-array image to new draw buf
|
||||||
|
*/
|
||||||
|
uint32_t stride_expect = lv_draw_buf_width_to_stride(dsc->header.w, dsc->header.cf);
|
||||||
|
if(dsc->header.stride != stride_expect) {
|
||||||
|
LV_LOG_WARN("Stride mismatch");
|
||||||
|
#if 0
|
||||||
|
/**
|
||||||
|
* @fixme ignore for now
|
||||||
|
*/
|
||||||
|
free_decoder_data(dsc);
|
||||||
|
return LV_RESULT_INVALID;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
res = LV_RESULT_OK;
|
res = LV_RESULT_OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -268,7 +298,7 @@ lv_result_t lv_bin_decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_d
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(dsc->img_data == NULL) return LV_RESULT_OK;
|
if(dsc->decoded == NULL) return LV_RESULT_OK; /*Need to read via get_area_cb*/
|
||||||
|
|
||||||
/*Add it to cache*/
|
/*Add it to cache*/
|
||||||
t = lv_tick_elaps(t);
|
t = lv_tick_elaps(t);
|
||||||
@ -281,7 +311,7 @@ lv_result_t lv_bin_decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_d
|
|||||||
}
|
}
|
||||||
|
|
||||||
cache->weight = t;
|
cache->weight = t;
|
||||||
cache->data = dsc->img_data;
|
cache->data = dsc->decoded;
|
||||||
cache->invalidate_cb = cache_invalidate_cb;
|
cache->invalidate_cb = cache_invalidate_cb;
|
||||||
if(dsc->src_type == LV_IMAGE_SRC_FILE) {
|
if(dsc->src_type == LV_IMAGE_SRC_FILE) {
|
||||||
cache->src = lv_strdup(dsc->src);
|
cache->src = lv_strdup(dsc->src);
|
||||||
@ -293,7 +323,7 @@ lv_result_t lv_bin_decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_d
|
|||||||
}
|
}
|
||||||
|
|
||||||
cache->user_data = dsc->user_data; /*Need to free data on cache invalidate instead of decoder_close*/
|
cache->user_data = dsc->user_data; /*Need to free data on cache invalidate instead of decoder_close*/
|
||||||
dsc->img_data = lv_cache_get_data(cache); /*@note: Must get from cache to increase reference count.*/
|
dsc->decoded = lv_cache_get_data(cache); /*@note: Must get from cache to increase reference count.*/
|
||||||
dsc->cache_entry = cache;
|
dsc->cache_entry = cache;
|
||||||
|
|
||||||
lv_cache_unlock();
|
lv_cache_unlock();
|
||||||
@ -309,10 +339,23 @@ void lv_bin_decoder_close(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t *
|
|||||||
{
|
{
|
||||||
LV_UNUSED(decoder); /*Unused*/
|
LV_UNUSED(decoder); /*Unused*/
|
||||||
|
|
||||||
|
decoder_data_t * decoder_data = dsc->user_data;
|
||||||
|
if(decoder_data && decoder_data->decoded_partial) {
|
||||||
|
lv_draw_buf_destroy(decoder_data->decoded_partial);
|
||||||
|
decoder_data->decoded_partial = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(dsc->cache_entry) {
|
||||||
|
/*Decoded data is in cache, release it from cache's callback*/
|
||||||
lv_cache_lock();
|
lv_cache_lock();
|
||||||
lv_cache_release(dsc->cache_entry);
|
lv_cache_release(dsc->cache_entry);
|
||||||
lv_cache_unlock();
|
lv_cache_unlock();
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
/*Data not in cache, free the memory manually*/
|
||||||
|
free_decoder_data(dsc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
lv_result_t lv_bin_decoder_get_area(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc,
|
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)
|
const lv_area_t * full_area, lv_area_t * decoded_area)
|
||||||
@ -335,32 +378,47 @@ lv_result_t lv_bin_decoder_get_area(lv_image_decoder_t * decoder, lv_image_decod
|
|||||||
|
|
||||||
lv_result_t res = LV_RESULT_INVALID;
|
lv_result_t res = LV_RESULT_INVALID;
|
||||||
decoder_data_t * decoder_data = dsc->user_data;
|
decoder_data_t * decoder_data = dsc->user_data;
|
||||||
|
if(decoder_data == NULL) {
|
||||||
|
LV_LOG_ERROR("Unexpected null decoder data");
|
||||||
|
return LV_RESULT_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
lv_fs_file_t * f = decoder_data->f;
|
lv_fs_file_t * f = decoder_data->f;
|
||||||
uint32_t bpp = lv_color_format_get_bpp(cf);
|
uint32_t bpp = lv_color_format_get_bpp(cf);
|
||||||
int32_t w_px = lv_area_get_width(full_area);
|
int32_t w_px = lv_area_get_width(full_area);
|
||||||
uint8_t * img_data = NULL;
|
uint8_t * img_data = NULL;
|
||||||
uint32_t offset = sizeof(lv_image_header_t); /*All image starts with image header*/
|
lv_draw_buf_t * decoded = NULL;
|
||||||
|
uint32_t offset = 0;
|
||||||
|
|
||||||
/*We only support read line by line for now*/
|
/*We only support read line by line for now*/
|
||||||
if(decoded_area->y1 == LV_COORD_MIN) {
|
if(decoded_area->y1 == LV_COORD_MIN) {
|
||||||
/*Indexed image is converted to ARGB888*/
|
/*Indexed image is converted to ARGB888*/
|
||||||
uint32_t len = LV_COLOR_FORMAT_IS_INDEXED(cf) ? sizeof(lv_color32_t) * 8 : bpp;
|
uint32_t len = LV_COLOR_FORMAT_IS_INDEXED(cf) ? sizeof(lv_color32_t) * 8 : bpp;
|
||||||
|
lv_color_format_t cf_decoded = LV_COLOR_FORMAT_IS_INDEXED(cf) ? LV_COLOR_FORMAT_ARGB8888 : cf;
|
||||||
|
|
||||||
len = (len * w_px) / 8;
|
len = (len * w_px) / 8;
|
||||||
img_data = lv_draw_buf_malloc(len, cf);
|
decoded = decoder_data->decoded_partial;
|
||||||
LV_ASSERT_NULL(img_data);
|
if(decoded && decoded->header.w == w_px) {
|
||||||
if(img_data == NULL)
|
/*Use existing one directly*/
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
decoded = lv_draw_buf_create(w_px, 1, cf_decoded, 0);
|
||||||
|
if(decoded == NULL)
|
||||||
return LV_RESULT_INVALID;
|
return LV_RESULT_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
*decoded_area = *full_area;
|
*decoded_area = *full_area;
|
||||||
decoded_area->y2 = decoded_area->y1;
|
decoded_area->y2 = decoded_area->y1;
|
||||||
decoder_data->img_data = img_data; /*Free on decoder close*/
|
decoder_data->decoded_partial = decoded; /*Free on decoder close*/
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
decoded_area->y1++;
|
decoded_area->y1++;
|
||||||
decoded_area->y2++;
|
decoded_area->y2++;
|
||||||
img_data = decoder_data->img_data;
|
decoded = decoder_data->decoded_partial; /*Already alloced*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
img_data = decoded->data; /*Get the buffer to operate on*/
|
||||||
|
|
||||||
if(decoded_area->y1 > full_area->y2) {
|
if(decoded_area->y1 > full_area->y2) {
|
||||||
return LV_RESULT_INVALID;
|
return LV_RESULT_INVALID;
|
||||||
}
|
}
|
||||||
@ -369,10 +427,12 @@ lv_result_t lv_bin_decoder_get_area(lv_image_decoder_t * decoder, lv_image_decod
|
|||||||
int32_t x_fraction = decoded_area->x1 % (8 / bpp);
|
int32_t x_fraction = decoded_area->x1 % (8 / bpp);
|
||||||
uint32_t len = (w_px * bpp + 7) / 8 + 1; /*10px for 1bpp may across 3bytes*/
|
uint32_t len = (w_px * bpp + 7) / 8 + 1; /*10px for 1bpp may across 3bytes*/
|
||||||
uint8_t * buf = NULL;
|
uint8_t * buf = NULL;
|
||||||
|
|
||||||
offset += dsc->palette_size * 4; /*Skip palette*/
|
offset += dsc->palette_size * 4; /*Skip palette*/
|
||||||
offset += decoded_area->y1 * dsc->header.stride;
|
offset += decoded_area->y1 * dsc->header.stride;
|
||||||
offset += decoded_area->x1 * bpp / 8; /*Move to x1*/
|
offset += decoded_area->x1 * bpp / 8; /*Move to x1*/
|
||||||
if(dsc->src_type == LV_IMAGE_SRC_FILE) {
|
if(dsc->src_type == LV_IMAGE_SRC_FILE) {
|
||||||
|
offset += sizeof(lv_image_header_t); /*File image starts with image header*/
|
||||||
buf = lv_malloc(len);
|
buf = lv_malloc(len);
|
||||||
LV_ASSERT_NULL(buf);
|
LV_ASSERT_NULL(buf);
|
||||||
if(buf == NULL)
|
if(buf == NULL)
|
||||||
@ -393,7 +453,7 @@ lv_result_t lv_bin_decoder_get_area(lv_image_decoder_t * decoder, lv_image_decod
|
|||||||
|
|
||||||
if(dsc->src_type == LV_IMAGE_SRC_FILE) lv_free((void *)buf);
|
if(dsc->src_type == LV_IMAGE_SRC_FILE) lv_free((void *)buf);
|
||||||
|
|
||||||
dsc->img_data = img_data; /*Return decoded image*/
|
dsc->decoded = decoded; /*Return decoded image*/
|
||||||
return LV_RESULT_OK;
|
return LV_RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -407,7 +467,7 @@ lv_result_t lv_bin_decoder_get_area(lv_image_decoder_t * decoder, lv_image_decod
|
|||||||
return LV_RESULT_INVALID;
|
return LV_RESULT_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
dsc->img_data = img_data; /*Return decoded image*/
|
dsc->decoded = decoded; /*Return decoded image*/
|
||||||
return LV_RESULT_OK;
|
return LV_RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -431,7 +491,7 @@ lv_result_t lv_bin_decoder_get_area(lv_image_decoder_t * decoder, lv_image_decod
|
|||||||
return LV_RESULT_INVALID;
|
return LV_RESULT_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
dsc->img_data = img_data; /*Return decoded image*/
|
dsc->decoded = decoded; /*Return decoded image*/
|
||||||
return LV_RESULT_OK;
|
return LV_RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -468,8 +528,8 @@ static void free_decoder_data(lv_image_decoder_dsc_t * dsc)
|
|||||||
lv_free(decoder_data->f);
|
lv_free(decoder_data->f);
|
||||||
}
|
}
|
||||||
|
|
||||||
lv_draw_buf_free(decoder_data->img_data);
|
if(decoder_data->decoded) lv_draw_buf_destroy(decoder_data->decoded);
|
||||||
lv_draw_buf_free(decoder_data->decompressed);
|
if(decoder_data->decompressed) lv_draw_buf_destroy(decoder_data->decompressed);
|
||||||
lv_free(decoder_data->palette);
|
lv_free(decoder_data->palette);
|
||||||
lv_free(decoder_data);
|
lv_free(decoder_data);
|
||||||
dsc->user_data = NULL;
|
dsc->user_data = NULL;
|
||||||
@ -487,11 +547,12 @@ static lv_result_t decode_indexed(lv_image_decoder_t * decoder, lv_image_decoder
|
|||||||
uint32_t palette_len = sizeof(lv_color32_t) * LV_COLOR_INDEXED_PALETTE_SIZE(cf);
|
uint32_t palette_len = sizeof(lv_color32_t) * LV_COLOR_INDEXED_PALETTE_SIZE(cf);
|
||||||
const lv_color32_t * palette;
|
const lv_color32_t * palette;
|
||||||
const uint8_t * indexed_data = NULL;
|
const uint8_t * indexed_data = NULL;
|
||||||
|
lv_draw_buf_t * draw_buf_indexed = NULL;
|
||||||
uint32_t stride = dsc->header.stride;
|
uint32_t stride = dsc->header.stride;
|
||||||
|
|
||||||
bool is_compressed = dsc->header.flags & LV_IMAGE_FLAGS_COMPRESSED;
|
bool is_compressed = dsc->header.flags & LV_IMAGE_FLAGS_COMPRESSED;
|
||||||
if(is_compressed) {
|
if(is_compressed) {
|
||||||
uint8_t * data = decoder_data->decompressed;
|
uint8_t * data = decoder_data->decompressed->data;
|
||||||
palette = (lv_color32_t *)data;
|
palette = (lv_color32_t *)data;
|
||||||
indexed_data = data + palette_len;
|
indexed_data = data + palette_len;
|
||||||
}
|
}
|
||||||
@ -512,13 +573,14 @@ static lv_result_t decode_indexed(lv_image_decoder_t * decoder, lv_image_decoder
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if LV_BIN_DECODER_RAM_LOAD
|
#if LV_BIN_DECODER_RAM_LOAD
|
||||||
indexed_data = lv_draw_buf_malloc(stride * dsc->header.h, cf);
|
draw_buf_indexed = lv_draw_buf_create(dsc->header.w, dsc->header.h, cf, dsc->header.stride);
|
||||||
LV_ASSERT_MALLOC(indexed_data);
|
if(draw_buf_indexed == NULL) {
|
||||||
if(indexed_data == NULL) {
|
|
||||||
LV_LOG_ERROR("Draw buffer alloc failed");
|
LV_LOG_ERROR("Draw buffer alloc failed");
|
||||||
goto exit_with_buf;
|
goto exit_with_buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
indexed_data = draw_buf_indexed->data;
|
||||||
|
|
||||||
uint32_t data_len = 0;
|
uint32_t data_len = 0;
|
||||||
if(lv_fs_seek(f, 0, LV_FS_SEEK_END) != LV_FS_RES_OK ||
|
if(lv_fs_seek(f, 0, LV_FS_SEEK_END) != LV_FS_RES_OK ||
|
||||||
lv_fs_tell(f, &data_len) != LV_FS_RES_OK) {
|
lv_fs_tell(f, &data_len) != LV_FS_RES_OK) {
|
||||||
@ -549,13 +611,16 @@ static lv_result_t decode_indexed(lv_image_decoder_t * decoder, lv_image_decoder
|
|||||||
|
|
||||||
#if LV_BIN_DECODER_RAM_LOAD
|
#if LV_BIN_DECODER_RAM_LOAD
|
||||||
/*Convert to ARGB8888, since sw renderer cannot render it directly even it's in RAM*/
|
/*Convert to ARGB8888, since sw renderer cannot render it directly even it's in RAM*/
|
||||||
stride = lv_draw_buf_width_to_stride(dsc->header.w, LV_COLOR_FORMAT_ARGB8888);
|
lv_draw_buf_t * decoded = lv_draw_buf_create(dsc->header.w, dsc->header.h, LV_COLOR_FORMAT_ARGB8888,
|
||||||
uint8_t * img_data = lv_draw_buf_malloc(stride * dsc->header.h, cf);
|
0);
|
||||||
if(img_data == NULL) {
|
if(decoded == NULL) {
|
||||||
LV_LOG_ERROR("No memory for indexed image");
|
LV_LOG_ERROR("No memory for indexed image");
|
||||||
goto exit_with_buf;
|
goto exit_with_buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stride = decoded->header.stride;
|
||||||
|
uint8_t * img_data = decoded->data;
|
||||||
|
|
||||||
const uint8_t * in = indexed_data;
|
const uint8_t * in = indexed_data;
|
||||||
uint8_t * out = img_data;
|
uint8_t * out = img_data;
|
||||||
for(uint32_t y = 0; y < dsc->header.h; y++) {
|
for(uint32_t y = 0; y < dsc->header.h; y++) {
|
||||||
@ -564,13 +629,11 @@ static lv_result_t decode_indexed(lv_image_decoder_t * decoder, lv_image_decoder
|
|||||||
out += stride;
|
out += stride;
|
||||||
}
|
}
|
||||||
|
|
||||||
dsc->header.stride = stride;
|
dsc->decoded = decoded;
|
||||||
dsc->header.cf = LV_COLOR_FORMAT_ARGB8888;
|
decoder_data->decoded = decoded; /*Free when decoder closes*/
|
||||||
dsc->img_data = img_data;
|
|
||||||
decoder_data->img_data = img_data; /*Free when decoder closes*/
|
|
||||||
if(dsc->src_type == LV_IMAGE_SRC_FILE && !is_compressed) {
|
if(dsc->src_type == LV_IMAGE_SRC_FILE && !is_compressed) {
|
||||||
decoder_data->palette = (void *)palette; /*Free decoder data on close*/
|
decoder_data->palette = (void *)palette; /*Free decoder data on close*/
|
||||||
lv_draw_buf_free((void *)indexed_data);
|
lv_draw_buf_destroy(draw_buf_indexed);
|
||||||
}
|
}
|
||||||
|
|
||||||
return LV_RESULT_OK;
|
return LV_RESULT_OK;
|
||||||
@ -583,6 +646,7 @@ exit_with_buf:
|
|||||||
#else
|
#else
|
||||||
LV_UNUSED(stride);
|
LV_UNUSED(stride);
|
||||||
LV_UNUSED(indexed_data);
|
LV_UNUSED(indexed_data);
|
||||||
|
LV_UNUSED(draw_buf_indexed);
|
||||||
/*It needs to be read by get_area_cb later*/
|
/*It needs to be read by get_area_cb later*/
|
||||||
return LV_RESULT_OK;
|
return LV_RESULT_OK;
|
||||||
#endif
|
#endif
|
||||||
@ -602,13 +666,14 @@ static lv_result_t decode_rgb(lv_image_decoder_t * decoder, lv_image_decoder_dsc
|
|||||||
len += (dsc->header.stride / 2) * dsc->header.h; /*A8 mask*/
|
len += (dsc->header.stride / 2) * dsc->header.h; /*A8 mask*/
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t * img_data = lv_draw_buf_malloc(len, cf);
|
lv_draw_buf_t * decoded = lv_draw_buf_create(dsc->header.w, dsc->header.h, cf, dsc->header.stride);
|
||||||
LV_ASSERT_MALLOC(img_data);
|
if(decoded == NULL) {
|
||||||
if(img_data == NULL) {
|
|
||||||
LV_LOG_ERROR("No memory for rgb file read");
|
LV_LOG_ERROR("No memory for rgb file read");
|
||||||
return LV_RESULT_INVALID;
|
return LV_RESULT_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t * img_data = decoded->data;
|
||||||
|
|
||||||
uint32_t rn;
|
uint32_t rn;
|
||||||
res = fs_read_file_at(f, sizeof(lv_image_header_t), img_data, len, &rn);
|
res = fs_read_file_at(f, sizeof(lv_image_header_t), img_data, len, &rn);
|
||||||
if(res != LV_FS_RES_OK || rn != len) {
|
if(res != LV_FS_RES_OK || rn != len) {
|
||||||
@ -617,8 +682,8 @@ static lv_result_t decode_rgb(lv_image_decoder_t * decoder, lv_image_decoder_dsc
|
|||||||
return LV_RESULT_INVALID;
|
return LV_RESULT_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
dsc->img_data = img_data;
|
dsc->decoded = decoded;
|
||||||
decoder_data->img_data = img_data; /*Free when decoder closes*/
|
decoder_data->decoded = decoded; /*Free when decoder closes*/
|
||||||
return LV_RESULT_OK;
|
return LV_RESULT_OK;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -633,24 +698,26 @@ static lv_result_t decode_alpha_only(lv_image_decoder_t * decoder, lv_image_deco
|
|||||||
uint32_t w = (dsc->header.stride * 8) / bpp;
|
uint32_t w = (dsc->header.stride * 8) / bpp;
|
||||||
uint32_t buf_stride = (w * 8 + 7) >> 3; /*stride for img_data*/
|
uint32_t buf_stride = (w * 8 + 7) >> 3; /*stride for img_data*/
|
||||||
uint32_t buf_len = w * dsc->header.h; /*always decode to A8 format*/
|
uint32_t buf_len = w * dsc->header.h; /*always decode to A8 format*/
|
||||||
uint8_t * img_data = lv_draw_buf_malloc(buf_len, dsc->header.cf);
|
lv_draw_buf_t * decoded;
|
||||||
uint32_t file_len = (uint32_t)dsc->header.stride * dsc->header.h;
|
uint32_t file_len = (uint32_t)dsc->header.stride * dsc->header.h;
|
||||||
|
|
||||||
LV_ASSERT_MALLOC(img_data);
|
decoded = lv_draw_buf_create(w, dsc->header.h, LV_COLOR_FORMAT_A8, buf_stride);
|
||||||
if(img_data == NULL) {
|
if(decoded == NULL) {
|
||||||
LV_LOG_ERROR("Out of memory");
|
LV_LOG_ERROR("Out of memory");
|
||||||
return LV_RESULT_INVALID;
|
return LV_RESULT_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t * img_data = decoded->data;
|
||||||
|
|
||||||
if(dsc->header.flags & LV_IMAGE_FLAGS_COMPRESSED) {
|
if(dsc->header.flags & LV_IMAGE_FLAGS_COMPRESSED) {
|
||||||
/*Copy from image data*/
|
/*Copy from image data*/
|
||||||
lv_memcpy(img_data, decoder_data->decompressed, file_len);
|
lv_memcpy(img_data, decoder_data->decompressed->data, file_len);
|
||||||
}
|
}
|
||||||
else if(dsc->src_type == LV_IMAGE_SRC_FILE) {
|
else if(dsc->src_type == LV_IMAGE_SRC_FILE) {
|
||||||
res = fs_read_file_at(decoder_data->f, sizeof(lv_image_header_t), img_data, file_len, &rn);
|
res = fs_read_file_at(decoder_data->f, sizeof(lv_image_header_t), img_data, file_len, &rn);
|
||||||
if(res != LV_FS_RES_OK || rn != file_len) {
|
if(res != LV_FS_RES_OK || rn != file_len) {
|
||||||
LV_LOG_WARN("Read header failed: %d", res);
|
LV_LOG_WARN("Read header failed: %d", res);
|
||||||
lv_draw_buf_free(img_data);
|
lv_draw_buf_destroy(decoded);
|
||||||
return LV_RESULT_INVALID;
|
return LV_RESULT_INVALID;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -691,10 +758,8 @@ static lv_result_t decode_alpha_only(lv_image_decoder_t * decoder, lv_image_deco
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
decoder_data->img_data = img_data;
|
decoder_data->decoded = decoded;
|
||||||
dsc->img_data = img_data;
|
dsc->decoded = decoded;
|
||||||
dsc->header.stride = buf_stride;
|
|
||||||
dsc->header.cf = LV_COLOR_FORMAT_A8;
|
|
||||||
return LV_RESULT_OK;
|
return LV_RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -796,7 +861,7 @@ static lv_result_t decode_compressed(lv_image_decoder_t * decoder, lv_image_deco
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/*The decompressed data is the original image data.*/
|
/*The decompressed data is the original image data.*/
|
||||||
dsc->img_data = decoder_data->decompressed;
|
dsc->decoded = decoder_data->decompressed;
|
||||||
res = LV_RESULT_OK;
|
res = LV_RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -877,17 +942,25 @@ static lv_result_t decompress_image(lv_image_decoder_dsc_t * dsc, const lv_image
|
|||||||
return LV_RESULT_INVALID;
|
return LV_RESULT_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t * decompressed;
|
uint8_t * img_data;
|
||||||
uint32_t input_len = compressed->compressed_size;
|
uint32_t input_len = compressed->compressed_size;
|
||||||
uint32_t out_len = compressed->decompressed_size;
|
uint32_t out_len = compressed->decompressed_size;
|
||||||
|
|
||||||
/*Note, stride must match.*/
|
lv_draw_buf_t * decompressed = lv_draw_buf_create(dsc->header.w, dsc->header.h, dsc->header.cf,
|
||||||
decompressed = lv_draw_buf_malloc(out_len, dsc->header.cf);
|
dsc->header.stride);
|
||||||
if(decompressed == NULL) {
|
if(decompressed == NULL) {
|
||||||
LV_LOG_WARN("No memory for decompressed image, input: %" LV_PRIu32 ", output: %" LV_PRIu32, input_len, out_len);
|
LV_LOG_WARN("No memory for decompressed image, input: %" LV_PRIu32 ", output: %" LV_PRIu32, input_len, out_len);
|
||||||
return LV_RESULT_INVALID;
|
return LV_RESULT_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(decompressed->data_size < out_len) {
|
||||||
|
LV_LOG_WARN("decompressed size mismatch: %" LV_PRIu32 ", %" LV_PRIu32, decompressed->data_size, out_len);
|
||||||
|
lv_draw_buf_destroy(decompressed);
|
||||||
|
return LV_RESULT_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
img_data = decompressed->data;
|
||||||
|
|
||||||
if(compressed->method == LV_IMAGE_COMPRESS_RLE) {
|
if(compressed->method == LV_IMAGE_COMPRESS_RLE) {
|
||||||
#if LV_USE_RLE
|
#if LV_USE_RLE
|
||||||
/*Compress always happen on byte*/
|
/*Compress always happen on byte*/
|
||||||
@ -897,37 +970,43 @@ static lv_result_t decompress_image(lv_image_decoder_dsc_t * dsc, const lv_image
|
|||||||
else
|
else
|
||||||
pixel_byte = (lv_color_format_get_bpp(dsc->header.cf) + 7) >> 3;
|
pixel_byte = (lv_color_format_get_bpp(dsc->header.cf) + 7) >> 3;
|
||||||
const uint8_t * input = compressed->data;
|
const uint8_t * input = compressed->data;
|
||||||
uint8_t * output = decompressed;
|
uint8_t * output = img_data;
|
||||||
uint32_t len;
|
uint32_t len;
|
||||||
len = lv_rle_decompress(input, input_len, output, out_len, pixel_byte);
|
len = lv_rle_decompress(input, input_len, output, out_len, pixel_byte);
|
||||||
if(len != compressed->decompressed_size) {
|
if(len != compressed->decompressed_size) {
|
||||||
LV_LOG_WARN("Decompress failed: %" LV_PRIu32 ", got: %" LV_PRIu32, out_len, len);
|
LV_LOG_WARN("Decompress failed: %" LV_PRIu32 ", got: %" LV_PRIu32, out_len, len);
|
||||||
lv_draw_buf_free(decompressed);
|
lv_draw_buf_destroy(decompressed);
|
||||||
return LV_RESULT_INVALID;
|
return LV_RESULT_INVALID;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
LV_LOG_WARN("RLE decompress is not enabled");
|
LV_LOG_WARN("RLE decompress is not enabled");
|
||||||
lv_draw_buf_free(decompressed);
|
lv_draw_buf_destroy(decompressed);
|
||||||
return LV_RESULT_INVALID;
|
return LV_RESULT_INVALID;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else if(compressed->method == LV_IMAGE_COMPRESS_LZ4) {
|
else if(compressed->method == LV_IMAGE_COMPRESS_LZ4) {
|
||||||
#if LV_USE_LZ4
|
#if LV_USE_LZ4
|
||||||
const char * input = (const char *)compressed->data;
|
const char * input = (const char *)compressed->data;
|
||||||
char * output = (char *)decompressed;
|
char * output = (char *)img_data;
|
||||||
int len;
|
int len;
|
||||||
len = LZ4_decompress_safe(input, output, input_len, out_len);
|
len = LZ4_decompress_safe(input, output, input_len, out_len);
|
||||||
if(len < 0 || (uint32_t)len != compressed->decompressed_size) {
|
if(len < 0 || (uint32_t)len != compressed->decompressed_size) {
|
||||||
LV_LOG_WARN("Decompress failed: %" LV_PRId32 ", got: %" LV_PRId32, out_len, len);
|
LV_LOG_WARN("Decompress failed: %" LV_PRId32 ", got: %" LV_PRId32, out_len, len);
|
||||||
lv_draw_buf_free(decompressed);
|
lv_draw_buf_destroy(decompressed);
|
||||||
return LV_RESULT_INVALID;
|
return LV_RESULT_INVALID;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
LV_LOG_WARN("LZ4 decompress is not enabled");
|
LV_LOG_WARN("LZ4 decompress is not enabled");
|
||||||
lv_draw_buf_free(decompressed);
|
lv_draw_buf_destroy(decompressed);
|
||||||
return LV_RESULT_INVALID;
|
return LV_RESULT_INVALID;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
LV_UNUSED(img_data);
|
||||||
|
LV_LOG_WARN("Unknown compression method: %d", compressed->method);
|
||||||
|
lv_draw_buf_destroy(decompressed);
|
||||||
|
return LV_RESULT_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
decoder_data->decompressed = decompressed; /*Free on decoder close*/
|
decoder_data->decompressed = decompressed; /*Free on decoder close*/
|
||||||
return LV_RESULT_OK;
|
return LV_RESULT_OK;
|
||||||
@ -941,27 +1020,7 @@ static lv_result_t try_cache(lv_image_decoder_dsc_t * dsc)
|
|||||||
|
|
||||||
lv_cache_entry_t * cache = lv_cache_find_by_src(NULL, fn, LV_CACHE_SRC_TYPE_PATH);
|
lv_cache_entry_t * cache = lv_cache_find_by_src(NULL, fn, LV_CACHE_SRC_TYPE_PATH);
|
||||||
if(cache) {
|
if(cache) {
|
||||||
dsc->img_data = lv_cache_get_data(cache);
|
dsc->decoded = lv_cache_get_data(cache);
|
||||||
/**
|
|
||||||
* The img_data may not be consistent with dsc->header.cf
|
|
||||||
* For indexed image, it could be converted to ARGB8888 when enabled.
|
|
||||||
* For alpha only image, it's always converted to A8 format.
|
|
||||||
*/
|
|
||||||
if(LV_COLOR_FORMAT_IS_ALPHA_ONLY(dsc->header.cf)) {
|
|
||||||
uint8_t bpp = lv_color_format_get_bpp(dsc->header.cf);
|
|
||||||
lv_image_header_t header;
|
|
||||||
lv_image_decoder_get_info(dsc->src, &header);
|
|
||||||
uint32_t w = (header.stride * 8) / bpp;
|
|
||||||
uint32_t buf_stride = (w * 8 + 7) >> 3; /*stride for img_data*/
|
|
||||||
dsc->header.cf = LV_COLOR_FORMAT_A8;
|
|
||||||
dsc->header.stride = buf_stride;
|
|
||||||
}
|
|
||||||
#if LV_BIN_DECODER_RAM_LOAD
|
|
||||||
else if(LV_COLOR_FORMAT_IS_INDEXED(dsc->header.cf)) {
|
|
||||||
dsc->header.stride = lv_draw_buf_width_to_stride(dsc->header.w, LV_COLOR_FORMAT_ARGB8888);
|
|
||||||
dsc->header.cf = LV_COLOR_FORMAT_ARGB8888;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
dsc->cache_entry = cache; /*Save the cache to release it in decoder_close*/
|
dsc->cache_entry = cache; /*Save the cache to release it in decoder_close*/
|
||||||
lv_cache_unlock();
|
lv_cache_unlock();
|
||||||
return LV_RESULT_OK;
|
return LV_RESULT_OK;
|
||||||
@ -973,7 +1032,7 @@ static lv_result_t try_cache(lv_image_decoder_dsc_t * dsc)
|
|||||||
|
|
||||||
lv_cache_entry_t * cache = lv_cache_find_by_src(NULL, img_dsc, LV_CACHE_SRC_TYPE_POINTER);
|
lv_cache_entry_t * cache = lv_cache_find_by_src(NULL, img_dsc, LV_CACHE_SRC_TYPE_POINTER);
|
||||||
if(cache) {
|
if(cache) {
|
||||||
dsc->img_data = lv_cache_get_data(cache);
|
dsc->decoded = lv_cache_get_data(cache);
|
||||||
dsc->cache_entry = cache; /*Save the cache to release it in decoder_close*/
|
dsc->cache_entry = cache; /*Save the cache to release it in decoder_close*/
|
||||||
lv_cache_unlock();
|
lv_cache_unlock();
|
||||||
return LV_RESULT_OK;
|
return LV_RESULT_OK;
|
||||||
|
@ -76,7 +76,7 @@ void lv_bmp_deinit(void)
|
|||||||
**********************/
|
**********************/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get info about a PNG image
|
* Get info about a BMP image
|
||||||
* @param src can be file name or pointer to a C array
|
* @param src can be file name or pointer to a C array
|
||||||
* @param header store the info here
|
* @param header store the info here
|
||||||
* @return LV_RESULT_OK: no error; LV_RESULT_INVALID: can't get the info
|
* @return LV_RESULT_OK: no error; LV_RESULT_INVALID: can't get the info
|
||||||
@ -135,7 +135,7 @@ static lv_result_t decoder_info(lv_image_decoder_t * decoder, const void * src,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open a PNG image and return the decided image
|
* Open a BMP image and return the decided image
|
||||||
* @param src can be file name or pointer to a C array
|
* @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)
|
* @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
|
* @return pointer to the decoded image or `LV_IMAGE_DECODER_OPEN_FAIL` if failed
|
||||||
@ -146,7 +146,7 @@ static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_d
|
|||||||
LV_UNUSED(decoder);
|
LV_UNUSED(decoder);
|
||||||
LV_UNUSED(args);
|
LV_UNUSED(args);
|
||||||
|
|
||||||
/*If it's a PNG file...*/
|
/*If it's a BMP file...*/
|
||||||
if(dsc->src_type == LV_IMAGE_SRC_FILE) {
|
if(dsc->src_type == LV_IMAGE_SRC_FILE) {
|
||||||
const char * fn = dsc->src;
|
const char * fn = dsc->src;
|
||||||
|
|
||||||
@ -178,7 +178,6 @@ static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_d
|
|||||||
LV_ASSERT_MALLOC(dsc->user_data);
|
LV_ASSERT_MALLOC(dsc->user_data);
|
||||||
if(dsc->user_data == NULL) return LV_RESULT_INVALID;
|
if(dsc->user_data == NULL) return LV_RESULT_INVALID;
|
||||||
lv_memcpy(dsc->user_data, &b, sizeof(b));
|
lv_memcpy(dsc->user_data, &b, sizeof(b));
|
||||||
dsc->img_data = NULL;
|
|
||||||
return LV_RESULT_OK;
|
return LV_RESULT_OK;
|
||||||
}
|
}
|
||||||
/* BMP file as data not supported for simplicity.
|
/* BMP file as data not supported for simplicity.
|
||||||
@ -195,12 +194,13 @@ static lv_result_t decoder_get_area(lv_image_decoder_t * decoder, lv_image_decod
|
|||||||
{
|
{
|
||||||
LV_UNUSED(decoder);
|
LV_UNUSED(decoder);
|
||||||
bmp_dsc_t * b = dsc->user_data;
|
bmp_dsc_t * b = dsc->user_data;
|
||||||
uint32_t line_width_byte = lv_area_get_width(full_area) * (b->bpp / 8);
|
lv_draw_buf_t * decoded = (void *)dsc->decoded;
|
||||||
|
|
||||||
if(decoded_area->y1 == LV_COORD_MIN) {
|
if(decoded_area->y1 == LV_COORD_MIN) {
|
||||||
*decoded_area = *full_area;
|
*decoded_area = *full_area;
|
||||||
decoded_area->y2 = decoded_area->y1;
|
decoded_area->y2 = decoded_area->y1;
|
||||||
dsc->img_data = lv_malloc(line_width_byte);
|
if(decoded == NULL) decoded = lv_draw_buf_create(lv_area_get_width(full_area), 1, dsc->header.cf, 0);
|
||||||
|
dsc->decoded = decoded;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
decoded_area->y1++;
|
decoded_area->y1++;
|
||||||
@ -215,7 +215,8 @@ static lv_result_t decoder_get_area(lv_image_decoder_t * decoder, lv_image_decod
|
|||||||
uint32_t p = b->px_offset + b->row_size_bytes * y;
|
uint32_t p = b->px_offset + b->row_size_bytes * y;
|
||||||
p += (decoded_area->x1) * (b->bpp / 8);
|
p += (decoded_area->x1) * (b->bpp / 8);
|
||||||
lv_fs_seek(&b->f, p, LV_FS_SEEK_SET);
|
lv_fs_seek(&b->f, p, LV_FS_SEEK_SET);
|
||||||
lv_fs_read(&b->f, (void *)dsc->img_data, line_width_byte, NULL);
|
uint32_t line_width_byte = lv_area_get_width(full_area) * (b->bpp / 8);
|
||||||
|
lv_fs_read(&b->f, decoded->data, line_width_byte, NULL);
|
||||||
|
|
||||||
return LV_RESULT_OK;
|
return LV_RESULT_OK;
|
||||||
}
|
}
|
||||||
@ -230,7 +231,7 @@ static void decoder_close(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t *
|
|||||||
bmp_dsc_t * b = dsc->user_data;
|
bmp_dsc_t * b = dsc->user_data;
|
||||||
lv_fs_close(&b->f);
|
lv_fs_close(&b->f);
|
||||||
lv_free(dsc->user_data);
|
lv_free(dsc->user_data);
|
||||||
if(dsc->img_data) lv_free((void *)dsc->img_data);
|
if(dsc->decoded) lv_draw_buf_destroy((void *)dsc->decoded);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ static lv_result_t decoder_info(lv_image_decoder_t * decoder, const void * src,
|
|||||||
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);
|
const lv_image_decoder_args_t * args);
|
||||||
static void decoder_close(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 const void * decode_jpeg_file(const char * filename, size_t * size);
|
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);
|
static bool get_jpeg_size(const char * filename, uint32_t * width, uint32_t * height);
|
||||||
static void error_exit(j_common_ptr cinfo);
|
static void error_exit(j_common_ptr cinfo);
|
||||||
static lv_result_t try_cache(lv_image_decoder_dsc_t * dsc);
|
static lv_result_t try_cache(lv_image_decoder_dsc_t * dsc);
|
||||||
@ -161,11 +161,15 @@ static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_d
|
|||||||
const char * fn = dsc->src;
|
const char * fn = dsc->src;
|
||||||
size_t decoded_size = 0;
|
size_t decoded_size = 0;
|
||||||
uint32_t t = lv_tick_get();
|
uint32_t t = lv_tick_get();
|
||||||
const void * decoded_img = decode_jpeg_file(fn, &decoded_size);
|
lv_draw_buf_t * decoded = decode_jpeg_file(fn);
|
||||||
|
if(decoded == NULL) {
|
||||||
|
LV_LOG_WARN("decode jpeg file failed");
|
||||||
|
return LV_RESULT_INVALID;
|
||||||
|
}
|
||||||
t = lv_tick_elaps(t);
|
t = lv_tick_elaps(t);
|
||||||
|
|
||||||
lv_cache_lock();
|
lv_cache_lock();
|
||||||
lv_cache_entry_t * cache = lv_cache_add(decoded_img, decoded_size, decoder->cache_data_type,
|
lv_cache_entry_t * cache = lv_cache_add(decoded, decoded_size, decoder->cache_data_type,
|
||||||
decoded_size);
|
decoded_size);
|
||||||
if(cache == NULL) {
|
if(cache == NULL) {
|
||||||
lv_cache_unlock();
|
lv_cache_unlock();
|
||||||
@ -183,7 +187,7 @@ static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_d
|
|||||||
cache->src = dsc->src;
|
cache->src = dsc->src;
|
||||||
}
|
}
|
||||||
|
|
||||||
dsc->img_data = lv_cache_get_data(cache);
|
dsc->decoded = lv_cache_get_data(cache);
|
||||||
dsc->cache_entry = cache;
|
dsc->cache_entry = cache;
|
||||||
|
|
||||||
lv_cache_unlock();
|
lv_cache_unlock();
|
||||||
@ -212,7 +216,7 @@ static lv_result_t try_cache(lv_image_decoder_dsc_t * dsc)
|
|||||||
|
|
||||||
lv_cache_entry_t * cache = lv_cache_find_by_src(NULL, fn, LV_CACHE_SRC_TYPE_PATH);
|
lv_cache_entry_t * cache = lv_cache_find_by_src(NULL, fn, LV_CACHE_SRC_TYPE_PATH);
|
||||||
if(cache) {
|
if(cache) {
|
||||||
dsc->img_data = lv_cache_get_data(cache);
|
dsc->decoded = lv_cache_get_data(cache);
|
||||||
dsc->cache_entry = cache; /*Save the cache to release it in decoder_close*/
|
dsc->cache_entry = cache; /*Save the cache to release it in decoder_close*/
|
||||||
lv_cache_unlock();
|
lv_cache_unlock();
|
||||||
return LV_RESULT_OK;
|
return LV_RESULT_OK;
|
||||||
@ -278,7 +282,7 @@ failed:
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const void * decode_jpeg_file(const char * filename, size_t * size)
|
static lv_draw_buf_t * decode_jpeg_file(const char * filename)
|
||||||
{
|
{
|
||||||
/* This struct contains the JPEG decompression parameters and pointers to
|
/* This struct contains the JPEG decompression parameters and pointers to
|
||||||
* working space (which is allocated as needed by the JPEG library).
|
* working space (which is allocated as needed by the JPEG library).
|
||||||
@ -370,17 +374,16 @@ static const void * decode_jpeg_file(const char * filename, size_t * size)
|
|||||||
* In this example, we need to make an output work buffer of the right size.
|
* In this example, we need to make an output work buffer of the right size.
|
||||||
*/
|
*/
|
||||||
/* JSAMPLEs per row in output buffer */
|
/* JSAMPLEs per row in output buffer */
|
||||||
|
lv_draw_buf_t * decoded;
|
||||||
row_stride = cinfo.output_width * cinfo.output_components;
|
row_stride = cinfo.output_width * cinfo.output_components;
|
||||||
/* Make a one-row-high sample array that will go away when done with image */
|
/* Make a one-row-high sample array that will go away when done with image */
|
||||||
buffer = (*cinfo.mem->alloc_sarray)
|
buffer = (*cinfo.mem->alloc_sarray)
|
||||||
((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
|
((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
|
||||||
|
|
||||||
size_t output_buffer_size = cinfo.output_width * cinfo.output_height * JPEG_PIXEL_SIZE;
|
decoded = lv_draw_buf_create(cinfo.output_width, cinfo.output_height, LV_COLOR_FORMAT_RGB888, 0);
|
||||||
output_buffer = lv_draw_buf_malloc(output_buffer_size, LV_COLOR_FORMAT_RGB888);
|
if(decoded != NULL) {
|
||||||
if(output_buffer) {
|
uint8_t * cur_pos = decoded->data;
|
||||||
uint8_t * cur_pos = output_buffer;
|
|
||||||
size_t stride = cinfo.output_width * JPEG_PIXEL_SIZE;
|
size_t stride = cinfo.output_width * JPEG_PIXEL_SIZE;
|
||||||
if(size) *size = output_buffer_size;
|
|
||||||
|
|
||||||
/* while (scan lines remain to be read) */
|
/* while (scan lines remain to be read) */
|
||||||
/* jpeg_read_scanlines(...); */
|
/* jpeg_read_scanlines(...); */
|
||||||
@ -397,7 +400,7 @@ static const void * decode_jpeg_file(const char * filename, size_t * size)
|
|||||||
|
|
||||||
/* Assume put_scanline_someplace wants a pointer and sample count. */
|
/* Assume put_scanline_someplace wants a pointer and sample count. */
|
||||||
lv_memcpy(cur_pos, buffer[0], stride);
|
lv_memcpy(cur_pos, buffer[0], stride);
|
||||||
cur_pos += stride;
|
cur_pos += decoded->header.stride;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -426,7 +429,7 @@ static const void * decode_jpeg_file(const char * filename, size_t * size)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* And we're done! */
|
/* And we're done! */
|
||||||
return output_buffer;
|
return decoded;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool get_jpeg_size(const char * filename, uint32_t * width, uint32_t * height)
|
static bool get_jpeg_size(const char * filename, uint32_t * width, uint32_t * height)
|
||||||
@ -482,7 +485,7 @@ static void error_exit(j_common_ptr cinfo)
|
|||||||
static void cache_invalidate_cb(lv_cache_entry_t * entry)
|
static void cache_invalidate_cb(lv_cache_entry_t * entry)
|
||||||
{
|
{
|
||||||
if(entry->src_type == LV_CACHE_SRC_TYPE_PATH) lv_free((void *)entry->src);
|
if(entry->src_type == LV_CACHE_SRC_TYPE_PATH) lv_free((void *)entry->src);
|
||||||
lv_free((void *)entry->data);
|
lv_draw_buf_destroy((lv_draw_buf_t *)entry->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /*LV_USE_LIBJPEG_TURBO*/
|
#endif /*LV_USE_LIBJPEG_TURBO*/
|
||||||
|
@ -27,7 +27,7 @@ static lv_result_t decoder_info(lv_image_decoder_t * decoder, const void * src,
|
|||||||
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);
|
const lv_image_decoder_args_t * args);
|
||||||
static void decoder_close(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 const void * decode_png_file(const char * filename);
|
static lv_draw_buf_t * decode_png_file(const char * filename);
|
||||||
static lv_result_t try_cache(lv_image_decoder_dsc_t * dsc);
|
static lv_result_t try_cache(lv_image_decoder_dsc_t * dsc);
|
||||||
static void cache_invalidate_cb(lv_cache_entry_t * entry);
|
static void cache_invalidate_cb(lv_cache_entry_t * entry);
|
||||||
|
|
||||||
@ -135,12 +135,31 @@ static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_d
|
|||||||
if(dsc->src_type == LV_IMAGE_SRC_FILE) {
|
if(dsc->src_type == LV_IMAGE_SRC_FILE) {
|
||||||
const char * fn = dsc->src;
|
const char * fn = dsc->src;
|
||||||
uint32_t t = lv_tick_get();
|
uint32_t t = lv_tick_get();
|
||||||
const void * decoded_img = decode_png_file(fn);
|
lv_draw_buf_t * decoded = decode_png_file(fn);
|
||||||
|
if(decoded == NULL) {
|
||||||
|
return LV_RESULT_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*Stride check and adjustment accordingly*/
|
||||||
|
if(args && args->stride_align) {
|
||||||
|
uint32_t expected = lv_draw_buf_width_to_stride(decoded->header.w, decoded->header.cf);
|
||||||
|
if(expected != decoded->header.stride) {
|
||||||
|
LV_LOG_INFO("Convert PNG stride to %" LV_PRId32, expected);
|
||||||
|
lv_draw_buf_t * aligned = lv_draw_buf_adjust_stride(decoded, expected);
|
||||||
|
lv_draw_buf_destroy(decoded);
|
||||||
|
if(aligned == NULL) {
|
||||||
|
LV_LOG_ERROR("png stride adjust failed");
|
||||||
|
return LV_RESULT_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
decoded = aligned;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
t = lv_tick_elaps(t);
|
t = lv_tick_elaps(t);
|
||||||
|
|
||||||
lv_cache_lock();
|
lv_cache_lock();
|
||||||
lv_cache_entry_t * cache = lv_cache_add(decoded_img, 0, decoder->cache_data_type,
|
lv_cache_entry_t * cache = lv_cache_add(decoded, 0, decoder->cache_data_type, decoded->data_size);
|
||||||
dsc->header.w * dsc->header.h * sizeof(uint32_t));
|
|
||||||
if(cache == NULL) {
|
if(cache == NULL) {
|
||||||
lv_cache_unlock();
|
lv_cache_unlock();
|
||||||
return LV_RESULT_INVALID;
|
return LV_RESULT_INVALID;
|
||||||
@ -157,7 +176,7 @@ static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_d
|
|||||||
cache->src = dsc->src;
|
cache->src = dsc->src;
|
||||||
}
|
}
|
||||||
|
|
||||||
dsc->img_data = lv_cache_get_data(cache);
|
dsc->decoded = lv_cache_get_data(cache);
|
||||||
dsc->cache_entry = cache;
|
dsc->cache_entry = cache;
|
||||||
|
|
||||||
lv_cache_unlock();
|
lv_cache_unlock();
|
||||||
@ -187,7 +206,7 @@ static lv_result_t try_cache(lv_image_decoder_dsc_t * dsc)
|
|||||||
|
|
||||||
lv_cache_entry_t * cache = lv_cache_find_by_src(NULL, fn, LV_CACHE_SRC_TYPE_PATH);
|
lv_cache_entry_t * cache = lv_cache_find_by_src(NULL, fn, LV_CACHE_SRC_TYPE_PATH);
|
||||||
if(cache) {
|
if(cache) {
|
||||||
dsc->img_data = lv_cache_get_data(cache);
|
dsc->decoded = lv_cache_get_data(cache);
|
||||||
dsc->cache_entry = cache; /*Save the cache to release it in decoder_close*/
|
dsc->cache_entry = cache; /*Save the cache to release it in decoder_close*/
|
||||||
lv_cache_unlock();
|
lv_cache_unlock();
|
||||||
return LV_RESULT_OK;
|
return LV_RESULT_OK;
|
||||||
@ -253,7 +272,7 @@ failed:
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const void * decode_png_file(const char * filename)
|
static lv_draw_buf_t * decode_png_file(const char * filename)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@ -281,33 +300,32 @@ static const void * decode_png_file(const char * filename)
|
|||||||
image.format = PNG_FORMAT_BGRA;
|
image.format = PNG_FORMAT_BGRA;
|
||||||
|
|
||||||
/*Alloc image buffer*/
|
/*Alloc image buffer*/
|
||||||
|
lv_draw_buf_t * decoded;
|
||||||
|
decoded = lv_draw_buf_create(image.width, image.height, LV_COLOR_FORMAT_ARGB8888, PNG_IMAGE_ROW_STRIDE(image));
|
||||||
|
if(decoded == NULL) {
|
||||||
size_t image_size = PNG_IMAGE_SIZE(image);
|
size_t image_size = PNG_IMAGE_SIZE(image);
|
||||||
void * image_data = lv_draw_buf_malloc(image_size, LV_COLOR_FORMAT_ARGB8888);
|
LV_LOG_ERROR("png draw buff alloc %zu failed: %s", image_size, filename);
|
||||||
|
lv_free(data);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if(image_data) {
|
|
||||||
/*Start decoding*/
|
/*Start decoding*/
|
||||||
ret = png_image_finish_read(&image, NULL, image_data, 0, NULL);
|
ret = png_image_finish_read(&image, NULL, decoded->data, 0, NULL);
|
||||||
if(!ret) {
|
|
||||||
LV_LOG_ERROR("png decode failed: %d", ret);
|
|
||||||
lv_draw_buf_free(image_data);
|
|
||||||
image_data = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
LV_LOG_ERROR("png alloc %zu failed", image_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*free decoder*/
|
|
||||||
png_image_free(&image);
|
png_image_free(&image);
|
||||||
lv_free(data);
|
lv_free(data);
|
||||||
|
if(!ret) {
|
||||||
|
LV_LOG_ERROR("png decode failed: %d", ret);
|
||||||
|
lv_draw_buf_destroy(decoded);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return image_data;
|
return decoded;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cache_invalidate_cb(lv_cache_entry_t * entry)
|
static void cache_invalidate_cb(lv_cache_entry_t * entry)
|
||||||
{
|
{
|
||||||
lv_free((void *)entry->src);
|
lv_free((void *)entry->src);
|
||||||
lv_free((void *)entry->data);
|
lv_draw_buf_destroy((lv_draw_buf_t *)entry->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /*LV_USE_LIBPNG*/
|
#endif /*LV_USE_LIBPNG*/
|
||||||
|
@ -5307,13 +5307,17 @@ static void decodeGeneric(unsigned char ** out, unsigned * w, unsigned * h,
|
|||||||
lodepng_free(idat);
|
lodepng_free(idat);
|
||||||
|
|
||||||
if(!state->error) {
|
if(!state->error) {
|
||||||
outsize = lodepng_get_raw_size(*w, *h, &state->info_png.color);
|
lv_draw_buf_t * decoded = lv_draw_buf_create(*w, *h, LV_COLOR_FORMAT_ARGB8888, 4 * *w);
|
||||||
*out = (unsigned char *)lv_draw_buf_malloc(outsize, LV_COLOR_FORMAT_ARGB8888);
|
if(decoded) {
|
||||||
if(!*out) state->error = 83; /*alloc fail*/
|
*out = (unsigned char*)decoded;
|
||||||
|
outsize = decoded->data_size;
|
||||||
|
}
|
||||||
|
else state->error = 83; /*alloc fail*/
|
||||||
}
|
}
|
||||||
if(!state->error) {
|
if(!state->error) {
|
||||||
lodepng_memset(*out, 0, outsize);
|
lv_draw_buf_t * decoded = (lv_draw_buf_t *)*out;
|
||||||
state->error = postProcessScanlines(*out, scanlines, *w, *h, &state->info_png);
|
lodepng_memset(decoded->data, 0, outsize);
|
||||||
|
state->error = postProcessScanlines(decoded->data, scanlines, *w, *h, &state->info_png);
|
||||||
}
|
}
|
||||||
lodepng_free(scanlines);
|
lodepng_free(scanlines);
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_d
|
|||||||
const lv_image_decoder_args_t * args);
|
const lv_image_decoder_args_t * args);
|
||||||
static void decoder_close(lv_image_decoder_t * dec, 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 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);
|
static lv_draw_buf_t * decode_png_data(const void * png_data, size_t png_data_size);
|
||||||
static lv_result_t try_cache(lv_image_decoder_dsc_t * dsc);
|
static lv_result_t try_cache(lv_image_decoder_dsc_t * dsc);
|
||||||
static void cache_invalidate_cb(lv_cache_entry_t * entry);
|
static void cache_invalidate_cb(lv_cache_entry_t * entry);
|
||||||
|
|
||||||
@ -150,7 +150,7 @@ static lv_result_t decoder_info(struct _lv_image_decoder_t * decoder, const void
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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 decoder pointer to the decoder where this function belongs
|
||||||
* @param dsc decoded image descriptor
|
* @param dsc decoded image descriptor
|
||||||
* @return LV_RESULT_OK: no error; LV_RESULT_INVALID: can't open the image
|
* @return LV_RESULT_OK: no error; LV_RESULT_INVALID: can't open the image
|
||||||
@ -197,10 +197,26 @@ static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_d
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint32_t t = lv_tick_get();
|
uint32_t t = lv_tick_get();
|
||||||
const void * decoded_img = decode_png_data(png_data, png_data_size);
|
lv_draw_buf_t * decoded = decode_png_data(png_data, png_data_size);
|
||||||
|
/*Stride check and adjustment accordingly*/
|
||||||
|
if(args && args->stride_align) {
|
||||||
|
uint32_t expected = lv_draw_buf_width_to_stride(decoded->header.w, decoded->header.cf);
|
||||||
|
if(expected != decoded->header.stride) {
|
||||||
|
LV_LOG_INFO("Convert PNG stride to %" LV_PRId32, expected);
|
||||||
|
lv_draw_buf_t * aligned = lv_draw_buf_adjust_stride(decoded, expected);
|
||||||
|
lv_draw_buf_destroy(decoded);
|
||||||
|
if(aligned == NULL) {
|
||||||
|
LV_LOG_ERROR("png stride adjust failed");
|
||||||
|
return LV_RESULT_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
decoded = aligned;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
t = lv_tick_elaps(t);
|
t = lv_tick_elaps(t);
|
||||||
cache->weight = t;
|
cache->weight = t;
|
||||||
cache->data = decoded_img;
|
cache->data = decoded;
|
||||||
cache->invalidate_cb = cache_invalidate_cb;
|
cache->invalidate_cb = cache_invalidate_cb;
|
||||||
if(dsc->src_type == LV_IMAGE_SRC_FILE) {
|
if(dsc->src_type == LV_IMAGE_SRC_FILE) {
|
||||||
cache->src = lv_strdup(dsc->src);
|
cache->src = lv_strdup(dsc->src);
|
||||||
@ -212,7 +228,7 @@ static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_d
|
|||||||
cache->src = dsc->src;
|
cache->src = dsc->src;
|
||||||
}
|
}
|
||||||
|
|
||||||
dsc->img_data = lv_cache_get_data(cache);
|
dsc->decoded = lv_cache_get_data(cache);
|
||||||
dsc->cache_entry = cache;
|
dsc->cache_entry = cache;
|
||||||
|
|
||||||
lv_cache_unlock();
|
lv_cache_unlock();
|
||||||
@ -242,7 +258,7 @@ static lv_result_t try_cache(lv_image_decoder_dsc_t * dsc)
|
|||||||
|
|
||||||
lv_cache_entry_t * cache = lv_cache_find_by_src(NULL, fn, LV_CACHE_SRC_TYPE_PATH);
|
lv_cache_entry_t * cache = lv_cache_find_by_src(NULL, fn, LV_CACHE_SRC_TYPE_PATH);
|
||||||
if(cache) {
|
if(cache) {
|
||||||
dsc->img_data = lv_cache_get_data(cache);
|
dsc->decoded = lv_cache_get_data(cache);
|
||||||
dsc->cache_entry = cache; /*Save the cache to release it in decoder_close*/
|
dsc->cache_entry = cache; /*Save the cache to release it in decoder_close*/
|
||||||
lv_cache_unlock();
|
lv_cache_unlock();
|
||||||
return LV_RESULT_OK;
|
return LV_RESULT_OK;
|
||||||
@ -254,7 +270,7 @@ static lv_result_t try_cache(lv_image_decoder_dsc_t * dsc)
|
|||||||
|
|
||||||
lv_cache_entry_t * cache = lv_cache_find_by_src(NULL, img_dsc, LV_CACHE_SRC_TYPE_POINTER);
|
lv_cache_entry_t * cache = lv_cache_find_by_src(NULL, img_dsc, LV_CACHE_SRC_TYPE_POINTER);
|
||||||
if(cache) {
|
if(cache) {
|
||||||
dsc->img_data = lv_cache_get_data(cache);
|
dsc->decoded = lv_cache_get_data(cache);
|
||||||
dsc->cache_entry = cache; /*Save the cache to release it in decoder_close*/
|
dsc->cache_entry = cache; /*Save the cache to release it in decoder_close*/
|
||||||
lv_cache_unlock();
|
lv_cache_unlock();
|
||||||
return LV_RESULT_OK;
|
return LV_RESULT_OK;
|
||||||
@ -265,24 +281,24 @@ static lv_result_t try_cache(lv_image_decoder_dsc_t * dsc)
|
|||||||
return LV_RESULT_INVALID;
|
return LV_RESULT_INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const void * decode_png_data(const void * png_data, size_t png_data_size)
|
static lv_draw_buf_t * decode_png_data(const void * png_data, size_t png_data_size)
|
||||||
{
|
{
|
||||||
unsigned png_width; /*Not used, just required by the decoder*/
|
unsigned png_width; /*Not used, just required by the decoder*/
|
||||||
unsigned png_height; /*Not used, just required by the decoder*/
|
unsigned png_height; /*Not used, just required by the decoder*/
|
||||||
uint8_t * img_data = NULL;
|
uint8_t * img_data = NULL;
|
||||||
|
|
||||||
|
lv_draw_buf_t * decoded;
|
||||||
/*Decode the image in ARGB8888 */
|
/*Decode the image in ARGB8888 */
|
||||||
unsigned error = lodepng_decode32(&img_data, &png_width, &png_height, png_data, png_data_size);
|
unsigned error = lodepng_decode32((unsigned char **)&decoded, &png_width, &png_height, png_data, png_data_size);
|
||||||
|
|
||||||
if(error) {
|
if(error) {
|
||||||
if(img_data != NULL) lv_free(img_data);
|
if(img_data != NULL) lv_draw_buf_destroy(decoded);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*Convert the image to the system's color depth*/
|
/*Convert the image to the system's color depth*/
|
||||||
convert_color_depth(img_data, png_width * png_height);
|
convert_color_depth(decoded->data, png_width * png_height);
|
||||||
|
|
||||||
return img_data;
|
return decoded;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -304,7 +320,7 @@ static void convert_color_depth(uint8_t * img_p, uint32_t px_cnt)
|
|||||||
static void cache_invalidate_cb(lv_cache_entry_t * entry)
|
static void cache_invalidate_cb(lv_cache_entry_t * entry)
|
||||||
{
|
{
|
||||||
if(entry->src_type == LV_CACHE_SRC_TYPE_PATH) lv_free((void *)entry->src);
|
if(entry->src_type == LV_CACHE_SRC_TYPE_PATH) lv_free((void *)entry->src);
|
||||||
lv_free((void *)entry->data);
|
lv_draw_buf_destroy((lv_draw_buf_t *)entry->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /*LV_USE_LODEPNG*/
|
#endif /*LV_USE_LODEPNG*/
|
||||||
|
@ -206,6 +206,9 @@ static lv_result_t decoder_get_area(lv_image_decoder_t * decoder, lv_image_decod
|
|||||||
LV_UNUSED(full_area);
|
LV_UNUSED(full_area);
|
||||||
|
|
||||||
JDEC * jd = dsc->user_data;
|
JDEC * jd = dsc->user_data;
|
||||||
|
lv_draw_buf_t * decoded = (void *)dsc->decoded;
|
||||||
|
if(decoded == NULL) decoded = lv_malloc_zeroed(sizeof(lv_draw_buf_t));
|
||||||
|
dsc->decoded = decoded;
|
||||||
|
|
||||||
uint32_t mx, my;
|
uint32_t mx, my;
|
||||||
mx = jd->msx * 8;
|
mx = jd->msx * 8;
|
||||||
@ -217,10 +220,11 @@ static lv_result_t decoder_get_area(lv_image_decoder_t * decoder, lv_image_decod
|
|||||||
decoded_area->x2 = -1;
|
decoded_area->x2 = -1;
|
||||||
jd->scale = 0;
|
jd->scale = 0;
|
||||||
jd->dcv[2] = jd->dcv[1] = jd->dcv[0] = 0; /* Initialize DC values */
|
jd->dcv[2] = jd->dcv[1] = jd->dcv[0] = 0; /* Initialize DC values */
|
||||||
dsc->img_data = jd->workbuf;
|
|
||||||
jd->rst = 0;
|
jd->rst = 0;
|
||||||
jd->rsc = 0;
|
jd->rsc = 0;
|
||||||
dsc->header.stride = mx * 3;
|
decoded->data = jd->workbuf;
|
||||||
|
decoded->header = dsc->header;
|
||||||
|
decoded->header.stride = mx * 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
decoded_area->x1 += mx;
|
decoded_area->x1 += mx;
|
||||||
@ -233,6 +237,10 @@ static lv_result_t decoder_get_area(lv_image_decoder_t * decoder, lv_image_decod
|
|||||||
decoded_area->y2 += my;
|
decoded_area->y2 += my;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
decoded->header.w = mx;
|
||||||
|
decoded->header.h = my;
|
||||||
|
decoded->data_size = decoded->header.stride * decoded->header.h;
|
||||||
|
|
||||||
/* Process restart interval if enabled */
|
/* Process restart interval if enabled */
|
||||||
JRESULT rc;
|
JRESULT rc;
|
||||||
if(jd->nrst && jd->rst++ == jd->nrst) {
|
if(jd->nrst && jd->rst++ == jd->nrst) {
|
||||||
@ -265,6 +273,7 @@ static void decoder_close(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t *
|
|||||||
lv_free(jd->device);
|
lv_free(jd->device);
|
||||||
lv_free(jd->pool_original);
|
lv_free(jd->pool_original);
|
||||||
lv_free(jd);
|
lv_free(jd);
|
||||||
|
lv_free((void *)dsc->decoded);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int is_jpg(const uint8_t * raw_data, size_t len)
|
static int is_jpg(const uint8_t * raw_data, size_t len)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user