mirror of
https://github.com/lvgl/lvgl.git
synced 2025-01-14 06:42:58 +08:00
feat(libpng): add parsing variable to libpng (#6553)
Signed-off-by: lhdjply <lhdjply@126.com>
This commit is contained in:
parent
210e4ba069
commit
1e36521018
1318
examples/libs/libpng/img_png_demo.c
Normal file
1318
examples/libs/libpng/img_png_demo.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
||||
Open a PNG image from file
|
||||
--------------------------
|
||||
Open a PNG image from file and variable
|
||||
---------------------------------------
|
||||
|
||||
.. lv_example:: libs/libpng/lv_example_libpng_1
|
||||
:language: c
|
||||
|
@ -8,13 +8,18 @@
|
||||
*/
|
||||
void lv_example_libpng_1(void)
|
||||
{
|
||||
LV_IMAGE_DECLARE(img_png_demo);
|
||||
lv_obj_t * img;
|
||||
|
||||
img = lv_image_create(lv_screen_active());
|
||||
lv_image_set_src(img, &img_png_demo);
|
||||
lv_obj_align(img, LV_ALIGN_LEFT_MID, 10, 0);
|
||||
|
||||
img = lv_image_create(lv_screen_active());
|
||||
/* Assuming a File system is attached to letter 'A'
|
||||
* E.g. set LV_USE_FS_STDIO 'A' in lv_conf.h */
|
||||
lv_image_set_src(img, "A:lvgl/examples/libs/libpng/png_demo.png");
|
||||
lv_obj_center(img);
|
||||
lv_obj_align(img, LV_ALIGN_RIGHT_MID, -10, 0);
|
||||
}
|
||||
|
||||
#else
|
||||
|
@ -31,7 +31,7 @@
|
||||
static lv_result_t decoder_info(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * src, lv_image_header_t * header);
|
||||
static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc);
|
||||
static void decoder_close(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc);
|
||||
static lv_draw_buf_t * decode_png_file(lv_image_decoder_dsc_t * dsc, const char * filename);
|
||||
static lv_draw_buf_t * decode_png(lv_image_decoder_dsc_t * dsc);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
@ -85,22 +85,36 @@ static lv_result_t decoder_info(lv_image_decoder_t * decoder, lv_image_decoder_d
|
||||
|
||||
lv_image_src_t src_type = dsc->src_type; /*Get the source type*/
|
||||
|
||||
/*If it's a PNG file...*/
|
||||
if(src_type == LV_IMAGE_SRC_FILE) {
|
||||
/* Read the width and height from the file. They have a constant location:
|
||||
* [16..19]: width
|
||||
* [20..23]: height
|
||||
*/
|
||||
if(src_type == LV_IMAGE_SRC_FILE || src_type == LV_IMAGE_SRC_VARIABLE) {
|
||||
uint32_t * size;
|
||||
static const uint8_t magic[] = {0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a};
|
||||
uint8_t buf[24];
|
||||
uint32_t rn;
|
||||
lv_fs_read(&dsc->file, buf, sizeof(buf), &rn);
|
||||
|
||||
if(rn != sizeof(buf)) return LV_RESULT_INVALID;
|
||||
/*If it's a PNG file...*/
|
||||
if(src_type == LV_IMAGE_SRC_FILE) {
|
||||
/* Read the width and height from the file. They have a constant location:
|
||||
* [16..19]: width
|
||||
* [20..23]: height
|
||||
*/
|
||||
uint32_t rn;
|
||||
lv_fs_read(&dsc->file, buf, sizeof(buf), &rn);
|
||||
|
||||
const uint8_t magic[] = {0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a};
|
||||
if(memcmp(buf, magic, sizeof(magic)) != 0) return LV_RESULT_INVALID;
|
||||
if(rn != sizeof(buf)) return LV_RESULT_INVALID;
|
||||
|
||||
if(lv_memcmp(buf, magic, sizeof(magic)) != 0) return LV_RESULT_INVALID;
|
||||
|
||||
size = (uint32_t *)&buf[16];
|
||||
}
|
||||
/*If it's a PNG file in a C array...*/
|
||||
else {
|
||||
const lv_image_dsc_t * img_dsc = dsc->src;
|
||||
const uint32_t data_size = img_dsc->data_size;
|
||||
size = ((uint32_t *)img_dsc->data) + 4;
|
||||
|
||||
if(data_size < sizeof(magic)) return LV_RESULT_INVALID;
|
||||
if(lv_memcmp(img_dsc->data, magic, sizeof(magic)) != 0) return LV_RESULT_INVALID;
|
||||
}
|
||||
|
||||
uint32_t * size = (uint32_t *)&buf[16];
|
||||
/*Save the data in the header*/
|
||||
header->cf = LV_COLOR_FORMAT_ARGB8888;
|
||||
/*The width and height are stored in Big endian format so convert them to little endian*/
|
||||
@ -122,52 +136,47 @@ static lv_result_t decoder_info(lv_image_decoder_t * decoder, lv_image_decoder_d
|
||||
static lv_result_t decoder_open(lv_image_decoder_t * decoder, lv_image_decoder_dsc_t * dsc)
|
||||
{
|
||||
LV_UNUSED(decoder); /*Unused*/
|
||||
lv_draw_buf_t * decoded;
|
||||
decoded = decode_png(dsc);
|
||||
|
||||
/*If it's a PNG file...*/
|
||||
if(dsc->src_type == LV_IMAGE_SRC_FILE) {
|
||||
const char * fn = dsc->src;
|
||||
lv_draw_buf_t * decoded = decode_png_file(dsc, fn);
|
||||
if(decoded == NULL) {
|
||||
return LV_RESULT_INVALID;
|
||||
}
|
||||
|
||||
lv_draw_buf_t * adjusted = lv_image_decoder_post_process(dsc, decoded);
|
||||
if(adjusted == NULL) {
|
||||
lv_draw_buf_destroy_user(image_cache_draw_buf_handlers, decoded);
|
||||
return LV_RESULT_INVALID;
|
||||
}
|
||||
|
||||
/*The adjusted draw buffer is newly allocated.*/
|
||||
if(adjusted != decoded) {
|
||||
lv_draw_buf_destroy_user(image_cache_draw_buf_handlers, decoded);
|
||||
decoded = adjusted;
|
||||
}
|
||||
|
||||
dsc->decoded = decoded;
|
||||
|
||||
if(dsc->args.no_cache) return LV_RESULT_OK;
|
||||
|
||||
/*If the image cache is disabled, just return the decoded image*/
|
||||
if(!lv_image_cache_is_enabled()) return LV_RESULT_OK;
|
||||
|
||||
/*Add the decoded image to the cache*/
|
||||
lv_image_cache_data_t search_key;
|
||||
search_key.src_type = dsc->src_type;
|
||||
search_key.src = dsc->src;
|
||||
search_key.slot.size = decoded->data_size;
|
||||
|
||||
lv_cache_entry_t * entry = lv_image_decoder_add_to_cache(decoder, &search_key, decoded, NULL);
|
||||
|
||||
if(entry == NULL) {
|
||||
lv_draw_buf_destroy_user(image_cache_draw_buf_handlers, decoded);
|
||||
return LV_RESULT_INVALID;
|
||||
}
|
||||
dsc->cache_entry = entry;
|
||||
|
||||
return LV_RESULT_OK; /*The image is fully decoded. Return with its pointer*/
|
||||
if(decoded == NULL) {
|
||||
return LV_RESULT_INVALID;
|
||||
}
|
||||
|
||||
return LV_RESULT_INVALID; /*If not returned earlier then it failed*/
|
||||
lv_draw_buf_t * adjusted = lv_image_decoder_post_process(dsc, decoded);
|
||||
if(adjusted == NULL) {
|
||||
lv_draw_buf_destroy_user(image_cache_draw_buf_handlers, decoded);
|
||||
return LV_RESULT_INVALID;
|
||||
}
|
||||
|
||||
/*The adjusted draw buffer is newly allocated.*/
|
||||
if(adjusted != decoded) {
|
||||
lv_draw_buf_destroy_user(image_cache_draw_buf_handlers, decoded);
|
||||
decoded = adjusted;
|
||||
}
|
||||
|
||||
dsc->decoded = decoded;
|
||||
|
||||
if(dsc->args.no_cache) return LV_RESULT_OK;
|
||||
|
||||
/*If the image cache is disabled, just return the decoded image*/
|
||||
if(!lv_image_cache_is_enabled()) return LV_RESULT_OK;
|
||||
|
||||
/*Add the decoded image to the cache*/
|
||||
lv_image_cache_data_t search_key;
|
||||
search_key.src_type = dsc->src_type;
|
||||
search_key.src = dsc->src;
|
||||
search_key.slot.size = decoded->data_size;
|
||||
|
||||
lv_cache_entry_t * entry = lv_image_decoder_add_to_cache(decoder, &search_key, decoded, NULL);
|
||||
|
||||
if(entry == NULL) {
|
||||
lv_draw_buf_destroy_user(image_cache_draw_buf_handlers, decoded);
|
||||
return LV_RESULT_INVALID;
|
||||
}
|
||||
dsc->cache_entry = entry;
|
||||
|
||||
return LV_RESULT_OK; /*The image is fully decoded. Return with its pointer*/
|
||||
}
|
||||
|
||||
/**
|
||||
@ -236,27 +245,41 @@ failed:
|
||||
return data;
|
||||
}
|
||||
|
||||
static lv_draw_buf_t * decode_png_file(lv_image_decoder_dsc_t * dsc, const char * filename)
|
||||
static lv_draw_buf_t * decode_png(lv_image_decoder_dsc_t * dsc)
|
||||
{
|
||||
int ret;
|
||||
|
||||
uint8_t * png_data;
|
||||
uint32_t png_data_size;
|
||||
/*Prepare png_image*/
|
||||
png_image image;
|
||||
lv_memzero(&image, sizeof(image));
|
||||
image.version = PNG_IMAGE_VERSION;
|
||||
|
||||
uint32_t data_size;
|
||||
uint8_t * data = alloc_file(filename, &data_size);
|
||||
if(data == NULL) {
|
||||
LV_LOG_WARN("can't load file: %s", filename);
|
||||
return NULL;
|
||||
if(dsc->src_type == LV_IMAGE_SRC_FILE) {
|
||||
if(lv_strcmp(lv_fs_get_ext(dsc->src), "png") != 0) { /*Check the extension*/
|
||||
return NULL;
|
||||
}
|
||||
|
||||
png_data = alloc_file(dsc->src, &png_data_size);
|
||||
if(png_data == NULL) {
|
||||
LV_LOG_WARN("can't load file: %s", (const char *)dsc->src);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
else if(dsc->src_type == LV_IMAGE_SRC_VARIABLE) {
|
||||
const lv_image_dsc_t * img_dsc = dsc->src;
|
||||
png_data = (uint8_t *)img_dsc->data;
|
||||
png_data_size = img_dsc->data_size;
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
|
||||
/*Ready to read file*/
|
||||
ret = png_image_begin_read_from_memory(&image, data, data_size);
|
||||
ret = png_image_begin_read_from_memory(&image, png_data, png_data_size);
|
||||
if(!ret) {
|
||||
LV_LOG_ERROR("png file: %s read failed: %d", filename, ret);
|
||||
lv_free(data);
|
||||
LV_LOG_ERROR("png read failed: %d", ret);
|
||||
if(dsc->src_type == LV_IMAGE_SRC_FILE)
|
||||
lv_free(png_data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -274,8 +297,15 @@ static lv_draw_buf_t * decode_png_file(lv_image_decoder_dsc_t * dsc, const char
|
||||
lv_draw_buf_t * decoded;
|
||||
decoded = lv_draw_buf_create_user(image_cache_draw_buf_handlers, image.width, image.height, cf, LV_STRIDE_AUTO);
|
||||
if(decoded == NULL) {
|
||||
LV_LOG_ERROR("alloc PNG_IMAGE_SIZE(%" LV_PRIu32 ") failed: %s", (uint32_t)PNG_IMAGE_SIZE(image), filename);
|
||||
lv_free(data);
|
||||
|
||||
if(dsc->src_type == LV_IMAGE_SRC_FILE) {
|
||||
LV_LOG_ERROR("alloc PNG_IMAGE_SIZE(%" LV_PRIu32 ") failed: %s", (uint32_t)PNG_IMAGE_SIZE(image),
|
||||
(const char *)dsc->src);
|
||||
lv_free(png_data);
|
||||
}
|
||||
else if(dsc->src_type == LV_IMAGE_SRC_VARIABLE)
|
||||
LV_LOG_ERROR("alloc PNG_IMAGE_SIZE(%" LV_PRIu32 ")", (uint32_t)PNG_IMAGE_SIZE(image));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -285,7 +315,8 @@ static lv_draw_buf_t * decode_png_file(lv_image_decoder_dsc_t * dsc, const char
|
||||
/*Start decoding*/
|
||||
ret = png_image_finish_read(&image, NULL, map, decoded->header.stride, palette);
|
||||
png_image_free(&image);
|
||||
lv_free(data);
|
||||
if(dsc->src_type == LV_IMAGE_SRC_FILE)
|
||||
lv_free(png_data);
|
||||
if(!ret) {
|
||||
LV_LOG_ERROR("png decode failed: %s", image.message);
|
||||
lv_draw_buf_destroy_user(image_cache_draw_buf_handlers, decoded);
|
||||
|
@ -84,59 +84,43 @@ static lv_result_t decoder_info(lv_image_decoder_t * decoder, lv_image_decoder_d
|
||||
{
|
||||
LV_UNUSED(decoder); /*Unused*/
|
||||
|
||||
const void * src = dsc->src;
|
||||
lv_image_src_t src_type = dsc->src_type; /*Get the source type*/
|
||||
|
||||
/*If it's a PNG file...*/
|
||||
if(src_type == LV_IMAGE_SRC_FILE) {
|
||||
const char * fn = src;
|
||||
if(lv_strcmp(lv_fs_get_ext(fn), "png") == 0) { /*Check the extension*/
|
||||
if(src_type == LV_IMAGE_SRC_FILE || src_type == LV_IMAGE_SRC_VARIABLE) {
|
||||
uint32_t * size;
|
||||
static const uint8_t magic[] = {0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a};
|
||||
uint8_t buf[24];
|
||||
|
||||
/*If it's a PNG file...*/
|
||||
if(src_type == LV_IMAGE_SRC_FILE) {
|
||||
/* Read the width and height from the file. They have a constant location:
|
||||
* [16..23]: width
|
||||
* [24..27]: height
|
||||
*/
|
||||
uint32_t size[2];
|
||||
* [16..19]: width
|
||||
* [20..23]: height
|
||||
*/
|
||||
uint32_t rn;
|
||||
lv_fs_read(&dsc->file, buf, sizeof(buf), &rn);
|
||||
|
||||
lv_fs_seek(&dsc->file, 16, LV_FS_SEEK_SET);
|
||||
lv_fs_read(&dsc->file, &size, 8, &rn);
|
||||
if(rn != sizeof(buf)) return LV_RESULT_INVALID;
|
||||
|
||||
if(rn != 8) return LV_RESULT_INVALID;
|
||||
if(lv_memcmp(buf, magic, sizeof(magic)) != 0) return LV_RESULT_INVALID;
|
||||
|
||||
/*Save the data in the header*/
|
||||
header->cf = LV_COLOR_FORMAT_ARGB8888;
|
||||
/*The width and height are stored in Big endian format so convert them to little endian*/
|
||||
header->w = (int32_t)((size[0] & 0xff000000) >> 24) + ((size[0] & 0x00ff0000) >> 8);
|
||||
header->h = (int32_t)((size[1] & 0xff000000) >> 24) + ((size[1] & 0x00ff0000) >> 8);
|
||||
|
||||
return LV_RESULT_OK;
|
||||
size = (uint32_t *)&buf[16];
|
||||
}
|
||||
}
|
||||
/*If it's a PNG file in a C array...*/
|
||||
else if(src_type == LV_IMAGE_SRC_VARIABLE) {
|
||||
const lv_image_dsc_t * img_dsc = src;
|
||||
const uint32_t data_size = img_dsc->data_size;
|
||||
const uint32_t * size = ((uint32_t *)img_dsc->data) + 4;
|
||||
const uint8_t magic[] = {0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a};
|
||||
if(data_size < sizeof(magic)) return LV_RESULT_INVALID;
|
||||
if(lv_memcmp(magic, img_dsc->data, sizeof(magic))) return LV_RESULT_INVALID;
|
||||
/*If it's a PNG file in a C array...*/
|
||||
else {
|
||||
const lv_image_dsc_t * img_dsc = dsc->src;
|
||||
const uint32_t data_size = img_dsc->data_size;
|
||||
size = ((uint32_t *)img_dsc->data) + 4;
|
||||
|
||||
if(data_size < sizeof(magic)) return LV_RESULT_INVALID;
|
||||
if(lv_memcmp(img_dsc->data, magic, sizeof(magic)) != 0) return LV_RESULT_INVALID;
|
||||
}
|
||||
|
||||
/*Save the data in the header*/
|
||||
header->cf = LV_COLOR_FORMAT_ARGB8888;
|
||||
|
||||
if(img_dsc->header.w) {
|
||||
header->w = img_dsc->header.w; /*Save the image width*/
|
||||
}
|
||||
else {
|
||||
header->w = (int32_t)((size[0] & 0xff000000) >> 24) + ((size[0] & 0x00ff0000) >> 8);
|
||||
}
|
||||
|
||||
if(img_dsc->header.h) {
|
||||
header->h = img_dsc->header.h; /*Save the color height*/
|
||||
}
|
||||
else {
|
||||
header->h = (int32_t)((size[1] & 0xff000000) >> 24) + ((size[1] & 0x00ff0000) >> 8);
|
||||
}
|
||||
/*The width and height are stored in Big endian format so convert them to little endian*/
|
||||
header->w = (int32_t)((size[0] & 0xff000000) >> 24) + ((size[0] & 0x00ff0000) >> 8);
|
||||
header->h = (int32_t)((size[1] & 0xff000000) >> 24) + ((size[1] & 0x00ff0000) >> 8);
|
||||
|
||||
return LV_RESULT_OK;
|
||||
}
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 13 KiB |
Binary file not shown.
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 13 KiB |
@ -19,10 +19,35 @@ static void create_images(void)
|
||||
lv_obj_clean(lv_screen_active());
|
||||
|
||||
lv_obj_t * img;
|
||||
lv_obj_t * label;
|
||||
|
||||
/* PNG array */
|
||||
LV_IMAGE_DECLARE(test_img_lvgl_logo_png);
|
||||
img = lv_image_create(lv_screen_active());
|
||||
lv_image_set_src(img, &test_img_lvgl_logo_png);
|
||||
lv_obj_align(img, LV_ALIGN_CENTER, -100, -20);
|
||||
|
||||
label = lv_label_create(lv_screen_active());
|
||||
lv_label_set_text(label, "Array");
|
||||
lv_obj_align(label, LV_ALIGN_CENTER, -100, 20);
|
||||
|
||||
/* 32 bit PNG file */
|
||||
img = lv_image_create(lv_screen_active());
|
||||
lv_image_set_src(img, "A:src/test_assets/test_img_lvgl_logo.png");
|
||||
lv_obj_center(img);
|
||||
lv_obj_align(img, LV_ALIGN_CENTER, 100, -100);
|
||||
|
||||
label = lv_label_create(lv_screen_active());
|
||||
lv_label_set_text(label, "File (32 bit)");
|
||||
lv_obj_align(label, LV_ALIGN_CENTER, 100, -60);
|
||||
|
||||
/* 8 bit palette PNG file */
|
||||
img = lv_image_create(lv_screen_active());
|
||||
lv_image_set_src(img, "A:src/test_assets/test_img_lvgl_logo_8bit_palette.png");
|
||||
lv_obj_align(img, LV_ALIGN_CENTER, 100, 60);
|
||||
|
||||
label = lv_label_create(lv_screen_active());
|
||||
lv_label_set_text(label, "File (8 bit palette)");
|
||||
lv_obj_align(label, LV_ALIGN_CENTER, 100, 100);
|
||||
}
|
||||
|
||||
void test_libpng_1(void)
|
||||
|
Loading…
x
Reference in New Issue
Block a user