lvgl use native lv_png instead of library

This commit is contained in:
Stephan Hadinger 2022-01-12 22:17:55 +01:00
parent 955d807cec
commit 636ac69a4b
9 changed files with 58 additions and 171 deletions

View File

@ -1,50 +0,0 @@
# PNG decoder for LVGL
Allow the use of PNG images in LVGL. This implementation uses [lodepng](https://github.com/lvandeve/lodepng) library.
## Get started
- Download or clone this repository
- [Download from GitHub](https://github.com/littlevgl/lv_lib_lodepng/archive/master.zip)
- Clone: `git clone https://github.com/littlevgl/lv_lib_png.git`
- Include the library: `#include "lv_lib_png/lv_png.h"`
- Initalize the decocer with `lv_png_init()`
- Test with the following code:
```c
LV_IMG_DECLARE(png_decoder_test);
lv_obj_t * img = lv_img_create(lv_scr_act(), NULL);
lv_img_set_src(img, &png_decoder_test);
```
## Use PNG images from file
By deafult `lodepng` uses C file IO API (e.g. `fopen`) and images can be opened like this:
```c
lv_img_set_src(img, "./lv_lib_lodepng/png_decoder_test.png");
```
If you want to make `lodepng` to use LVGL's file system API add `#define LV_PNG_USE_LV_FILESYSTEM 1` to the end of your`lv_conf.h`.
In this case you need to [register a driver](https://docs.lvgl.io/latest/en/html/overview/file-system.html) fo LVGL. The following functions are required:
- `open_cb()`
- `read_cb()`
- `close_cb()`
- `size_cb()`
After that fiels can be opened like this:
```c
lv_img_set_src(img, "P:lv_lib_lodepng/png_decoder_test.png");
```
Note that the path of the file might be different.
## Use PNG images from flash
To store a PNG image in flash it needs to be converted to C array with [Online Image converter](https://lvgl.io/tools/imageconverter). Choose `Raw with alpha` Color format and `C array` Output format. Copy the result C array to your project and use it like this:
```c
LV_IMG_DECLARE(my_test_img);
lv_obj_t * img = lv_img_create(lv_scr_act(), NULL);
lv_img_set_src(img, &my_test_img);
```
## Learn more
To learn more about the PNG decoder itself read [this blog post](https://blog.littlevgl.com/2018-10-05/png_converter)
To learn more about the Image decoder interface of LittlevGL read the realevant part of the [documentation](https://docs.littlevgl.com/en/html/overview/image.html#image-decoder).

View File

@ -1,21 +0,0 @@
{
"name":"lv_lib_png",
"description":"Allow the use of PNG images in LVGL. This implementation uses lodepng library.",
"keywords":"lvgl, png",
"license": "MIT License",
"repository": {
"type": "git",
"url": "https://github.com/lvgl/lv_lib_png"
},
"frameworks": "arduino",
"platforms": "espressif32",
"build": {
"flags": [ "-DLV_PNG_USE_LV_FILESYSTEM=1",
"-DLODEPNG_NO_COMPILE_ALLOCATORS",
"-DLODEPNG_NO_COMPILE_ERROR_TEXT",
"-DLODEPNG_NO_COMPILE_ANCILLARY_CHUNKS",
"-DLV_LVGL_H_INCLUDE_SIMPLE",
"-I$PROJECT_DIR/include",
"-includetasmota_options.h" ]
}
}

View File

@ -16,7 +16,7 @@ extern "C" {
// TODO Tasmota
// #include "bmp/lv_bmp.h"
// #include "fsdrv/lv_fsdrv.h"
// #include "png/lv_png.h"
#include "png/lv_png.h"
// #include "gif/lv_gif.h"
// #include "qrcode/lv_qrcode.h"
// #include "sjpg/lv_sjpg.h"

View File

@ -29,10 +29,10 @@ Rename this file to lodepng.cpp to use it for C++, or to lodepng.c to use it for
*/
#include "lodepng.h"
#if LV_USE_PNG
#ifdef LODEPNG_COMPILE_DISK
#include <limits.h> /* LONG_MAX */
#include <stdio.h> /* file handling */
#endif /* LODEPNG_COMPILE_DISK */
#ifdef LODEPNG_COMPILE_ALLOCATORS
@ -75,7 +75,7 @@ static void* lodepng_malloc(size_t size) {
#ifdef LODEPNG_MAX_ALLOC
if(size > LODEPNG_MAX_ALLOC) return 0;
#endif
return malloc(size);
return lv_mem_alloc(size);
}
/* NOTE: when realloc returns NULL, it leaves the original memory untouched */
@ -83,11 +83,11 @@ static void* lodepng_realloc(void* ptr, size_t new_size) {
#ifdef LODEPNG_MAX_ALLOC
if(new_size > LODEPNG_MAX_ALLOC) return 0;
#endif
return realloc(ptr, new_size);
return lv_mem_realloc(ptr, new_size);
}
static void lodepng_free(void* ptr) {
free(ptr);
lv_mem_free(ptr);
}
#else /*LODEPNG_COMPILE_ALLOCATORS*/
/* TODO: support giving additional void* payload to the custom allocators */
@ -343,12 +343,11 @@ static void lodepng_set32bitInt(unsigned char* buffer, unsigned value) {
/* returns negative value on error. This should be pure C compatible, so no fstat. */
static long lodepng_filesize(const char* filename) {
#if LV_PNG_USE_LV_FILESYSTEM
lv_fs_file_t f;
lv_fs_res_t res = lv_fs_open(&f, filename, LV_FS_MODE_RD);
if(res != LV_FS_RES_OK) return -1;
uint32_t size = 0;
if(lv_fs_seek(&f, 0, SEEK_END) != 0) {
if(lv_fs_seek(&f, 0, LV_FS_SEEK_END) != 0) {
lv_fs_close(&f);
return -1;
}
@ -356,29 +355,10 @@ static long lodepng_filesize(const char* filename) {
lv_fs_tell(&f, &size);
lv_fs_close(&f);
return size;
#else
FILE* file;
long size;
file = fopen(filename, "rb");
if(!file) return -1;
if(fseek(file, 0, SEEK_END) != 0) {
fclose(file);
return -1;
}
size = ftell(file);
/* It may give LONG_MAX as directory size, this is invalid for us. */
if(size == LONG_MAX) size = -1;
fclose(file);
return size;
#endif
}
/* load file into buffer that already has the correct allocated size. Returns error code.*/
static unsigned lodepng_buffer_file(unsigned char* out, size_t size, const char* filename) {
#if LV_PNG_USE_LV_FILESYSTEM
lv_fs_file_t f;
lv_fs_res_t res = lv_fs_open(&f, filename, LV_FS_MODE_RD);
if(res != LV_FS_RES_OK) return 78;
@ -389,18 +369,6 @@ static unsigned lodepng_buffer_file(unsigned char* out, size_t size, const char*
if (br != size) return 78;
lv_fs_close(&f);
return 0;
#else
FILE* file;
size_t readsize;
file = fopen(filename, "rb");
if(!file) return 78;
readsize = fread(out, 1, size, file);
fclose(file);
if(readsize != size) return 78;
return 0;
#endif
}
unsigned lodepng_load_file(unsigned char** out, size_t* outsize, const char* filename) {
@ -416,11 +384,13 @@ unsigned lodepng_load_file(unsigned char** out, size_t* outsize, const char* fil
/*write given buffer to the file, overwriting the file, it doesn't append to it.*/
unsigned lodepng_save_file(const unsigned char* buffer, size_t buffersize, const char* filename) {
FILE* file;
file = fopen(filename, "wb" );
if(!file) return 79;
fwrite(buffer, 1, buffersize, file);
fclose(file);
lv_fs_file_t f;
lv_fs_res_t res = lv_fs_open(&f, filename, LV_FS_MODE_WR);
if(res != LV_FS_RES_OK) return 79;
uint32_t bw;
res = lv_fs_write(&f, buffer, buffersize, &bw);
lv_fs_close(&f);
return 0;
}
@ -611,6 +581,7 @@ static unsigned readBits(LodePNGBitReader* reader, size_t nbits) {
return result;
}
#if 0 /*Disable because tests fail due to unused declaration*/
/* Public for testing only. steps and result must have numsteps values. */
static unsigned lode_png_test_bitreader(const unsigned char* data, size_t size,
size_t numsteps, const size_t* steps, unsigned* result) {
@ -630,6 +601,8 @@ static unsigned lode_png_test_bitreader(const unsigned char* data, size_t size,
}
return 1;
}
#endif
#endif /*LODEPNG_COMPILE_DECODER*/
static unsigned reverseBits(unsigned bits, unsigned num) {
@ -2337,7 +2310,7 @@ static unsigned zlib_compress(unsigned char** out, size_t* outsize, const unsign
static unsigned zlib_decompress(unsigned char** out, size_t* outsize, size_t expected_size,
const unsigned char* in, size_t insize, const LodePNGDecompressSettings* settings) {
if(!settings->custom_zlib) return 87; /*no custom zlib function provided */
(void)expected_size;
LV_UNUSED(expected_size);
return settings->custom_zlib(out, outsize, in, insize, settings);
}
#endif /*LODEPNG_COMPILE_DECODER*/
@ -2579,6 +2552,8 @@ unsigned char* lodepng_chunk_find(unsigned char* chunk, unsigned char* end, cons
if(lodepng_chunk_type_equals(chunk, type)) return chunk;
chunk = lodepng_chunk_next(chunk, end);
}
return 0; /*Shouldn't reach this*/
}
const unsigned char* lodepng_chunk_find_const(const unsigned char* chunk, const unsigned char* end, const char type[5]) {
@ -2587,6 +2562,8 @@ const unsigned char* lodepng_chunk_find_const(const unsigned char* chunk, const
if(lodepng_chunk_type_equals(chunk, type)) return chunk;
chunk = lodepng_chunk_next_const(chunk, end);
}
return 0; /*Shouldn't reach this*/
}
unsigned lodepng_chunk_append(unsigned char** out, size_t* outsize, const unsigned char* chunk) {
@ -6490,3 +6467,5 @@ unsigned encode(const std::string& filename,
#endif /* LODEPNG_COMPILE_PNG */
} /* namespace lodepng */
#endif /*LODEPNG_COMPILE_CPP*/
#endif /*LV_USE_PNG*/

View File

@ -28,18 +28,8 @@ freely, subject to the following restrictions:
#include <string.h> /*for size_t*/
#ifndef LV_PNG_USE_LV_FILESYSTEM
#define LV_PNG_USE_LV_FILESYSTEM 0
#endif
#if LV_PNG_USE_LV_FILESYSTEM
#if defined(LV_LVGL_H_INCLUDE_SIMPLE)
#include "lvgl.h"
#else
#include "lvgl/lvgl.h"
#endif
#endif /* LV_PNG_USE_LV_FILESYSTEM */
#include "../../../lvgl.h"
#if LV_USE_PNG
extern const char* LODEPNG_VERSION_STRING;
/*
@ -1095,6 +1085,8 @@ TODO:
[X] provide alternatives for C library functions not present on some platforms (memcpy, ...)
*/
#endif /*LV_USE_PNG*/
#endif /*LODEPNG_H inclusion guard*/
/*

View File

@ -6,19 +6,12 @@
/*********************
* INCLUDES
*********************/
#if defined(LV_LVGL_H_INCLUDE_SIMPLE)
#include "lvgl.h"
#else
#include "lvgl/lvgl.h"
#endif
#include "../../../lvgl.h"
#if LV_USE_PNG
#include "lv_png.h"
#include "lodepng.h"
#include <stdlib.h>
#if LV_MEM_CUSTOM != 0
#include LV_MEM_CUSTOM_INCLUDE
#endif
#include <stdio.h>
/*********************
* DEFINES
@ -84,7 +77,6 @@ static lv_res_t decoder_info(struct _lv_img_decoder_t * decoder, const void * sr
* [24..27]: height
*/
uint32_t size[2];
#if LV_PNG_USE_LV_FILESYSTEM
lv_fs_file_t f;
lv_fs_res_t res = lv_fs_open(&f, fn, LV_FS_MODE_RD);
if(res != LV_FS_RES_OK) return LV_RES_INV;
@ -93,15 +85,6 @@ static lv_res_t decoder_info(struct _lv_img_decoder_t * decoder, const void * sr
lv_fs_read(&f, &size, 8, &rn);
if(rn != 8) return LV_RES_INV;
lv_fs_close(&f);
#else
FILE* file;
file = fopen(fn, "rb" );
if(!file) return LV_RES_INV;
fseek(file, 16, SEEK_SET);
size_t rn = fread(size, 1 , 8, file);
fclose(file);
if(rn != 8) return LV_RES_INV;
#endif
/*Save the data in the header*/
header->always_zero = 0;
header->cf = LV_IMG_CF_RAW_ALPHA;
@ -152,11 +135,7 @@ static lv_res_t decoder_open(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t *
error = lodepng_load_file(&png_data, &png_data_size, fn); /*Load the file*/
if(error) {
#ifdef LODEPNG_COMPILE_ERROR_TEXT
LV_LOG_ERROR("lv_png error %u: %s\n", error, lodepng_error_text(error));
#else
LV_LOG_ERROR("lv_png error %u\n", error);
#endif
LV_LOG_WARN("error %u: %s\n", error, lodepng_error_text(error));
return LV_RES_INV;
}
@ -166,13 +145,9 @@ static lv_res_t decoder_open(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t *
/*Decode the loaded image in ARGB8888 */
error = lodepng_decode32(&img_data, &png_width, &png_height, png_data, png_data_size);
LV_MEM_CUSTOM_FREE(png_data); /*Free the loaded file*/
lv_mem_free(png_data); /*Free the loaded file*/
if(error) {
#ifdef LODEPNG_COMPILE_ERROR_TEXT
LV_LOG_ERROR("lv_png error %u: %s\n", error, lodepng_error_text(error));
#else
LV_LOG_ERROR("lv_png error %u\n", error);
#endif
LV_LOG_WARN("error %u: %s\n", error, lodepng_error_text(error));
return LV_RES_INV;
}
@ -210,8 +185,11 @@ static lv_res_t decoder_open(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t *
*/
static void decoder_close(lv_img_decoder_t *decoder, lv_img_decoder_dsc_t *dsc)
{
(void) decoder; /*Unused*/
if(dsc->img_data) LV_MEM_CUSTOM_FREE((uint8_t *)dsc->img_data);
LV_UNUSED(decoder); /*Unused*/
if (dsc->img_data) {
lv_mem_free((uint8_t *)dsc->img_data);
dsc->img_data = NULL;
}
}
/**
@ -243,15 +221,25 @@ static void convert_color_depth(uint8_t * img, uint32_t px_cnt)
}
#elif LV_COLOR_DEPTH == 8
lv_color32_t * img_argb = (lv_color32_t*)img;
lv_color_t c;
uint32_t i;
for(i = 0; i < px_cnt; i++) {
c = lv_color_make(img_argb[i].red, img_argb[i].green, img_argb[i].blue);
img[i*2 + 1] = img_argb[i].alpha;
img[i*2 + 0] = c.full
}
lv_color_t c;
uint32_t i;
for(i = 0; i < px_cnt; i++) {
c = lv_color_make(img_argb[i].ch.red, img_argb[i].ch.green, img_argb[i].ch.blue);
img[i*2 + 1] = img_argb[i].ch.alpha;
img[i*2 + 0] = c.full;
}
#elif LV_COLOR_DEPTH == 1
lv_color32_t * img_argb = (lv_color32_t*)img;
uint8_t b;
uint32_t i;
for(i = 0; i < px_cnt; i++) {
b = img_argb[i].ch.red | img_argb[i].ch.green | img_argb[i].ch.blue;
img[i*2 + 1] = img_argb[i].ch.alpha;
img[i*2 + 0] = b > 128 ? 1 : 0;
}
#endif
}
#endif /*LV_USE_PNG*/

View File

@ -13,6 +13,8 @@ extern "C" {
/*********************
* INCLUDES
*********************/
#include "../../../lv_conf_internal.h"
#if LV_USE_PNG
/*********************
* DEFINES
@ -35,6 +37,7 @@ void lv_png_init(void);
* MACROS
**********************/
#endif /*LV_USE_PNG*/
#ifdef __cplusplus
} /* extern "C" */

View File

@ -555,7 +555,7 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h"*/
#define LV_USE_FS_FATFS '\0' /*Uses f_open, f_read, etc*/
/*PNG decoder library*/
#define LV_USE_PNG 0
#define LV_USE_PNG 1
/*BMP decoder library*/
#define LV_USE_BMP 0

View File

@ -32,10 +32,6 @@
#include "Adafruit_LvGL_Glue.h"
#ifdef USE_LVGL_PNG_DECODER
#include "lv_png.h"
#endif // USE_LVGL_PNG_DECODER
#ifdef USE_LVGL_FREETYPE
#include "lv_freetype.h"
#endif // USE_LVGL_FREETYPE