diff --git a/include/hasp_conf.h b/include/hasp_conf.h index 1d30b61f..df4eabb3 100644 --- a/include/hasp_conf.h +++ b/include/hasp_conf.h @@ -125,6 +125,18 @@ #define HASP_USE_PNGDECODE 0 #endif +#ifndef HASP_USE_BMPDECODE +#define HASP_USE_BMPDECODE 0 +#endif + +#ifndef HASP_USE_GIFDECODE +#define HASP_USE_GIFDECODE 0 +#endif + +#ifndef HASP_USE_JPGDECODE +#define HASP_USE_JPGDECODE 0 +#endif + #ifndef HASP_NUM_GPIO_CONFIG #define HASP_NUM_GPIO_CONFIG 8 #endif diff --git a/platformio.ini b/platformio.ini index 447c86be..32685e4e 100644 --- a/platformio.ini +++ b/platformio.ini @@ -135,6 +135,9 @@ build_flags = -D HASP_USE_CONFIG=1 ; Native application, not library -D LV_LOG_TRACE_TIMER=1 -D HASP_USE_PNGDECODE=1 + -D HASP_USE_BMPDECODE=0 + -D HASP_USE_JPGDECODE=0 + -D HASP_USE_GIFDECODE=0 ; -- LittleFS build options ------------------------ ;-D CONFIG_LITTLEFS_FOR_IDF_3_2 ; obsolete in IDF 3.3 @@ -153,6 +156,9 @@ lib_deps = ESP Async WebServer LittleFS_esp32 git+https://github.com/lvgl/lv_lib_png.git#release/v7 + #git+https://github.com/lvgl/lv_lib_bmp.git#release/v7 + #git+https://github.com/lvgl/lv_lib_gif.git#release/v7 + git+https://github.com/fvanroie/lv_lib_split_jpg.git ps_ram = -DBOARD_HAS_PSRAM diff --git a/src/hasp/hasp_attribute.cpp b/src/hasp/hasp_attribute.cpp index bab0f9cd..a8e00f07 100644 --- a/src/hasp/hasp_attribute.cpp +++ b/src/hasp/hasp_attribute.cpp @@ -8,6 +8,22 @@ #include "hasplib.h" #include "hasp_attribute_helper.h" +/*** Image Improvement ***/ +#if defined(ARDUINO_ARCH_ESP8266) +#include +#endif + +#if defined(ARDUINO_ARCH_ESP32) +#include +#endif + +#if HASP_USE_PNGDECODE > 0 +#include "lv_png.h" +#include "lodepng.h" +#include "hasp_png.h" +#endif +/*** Image Improvement ***/ + LV_FONT_DECLARE(unscii_8_icon); extern const char** btnmatrix_default_map; // memory pointer to lvgl default btnmatrix map @@ -978,8 +994,90 @@ static hasp_attribute_type_t special_attribute_src(lv_obj_t* obj, const char* pa if(!obj_check_type(obj, LV_HASP_IMAGE)) return HASP_ATTR_TYPE_NOT_FOUND; if(update) { - lv_img_cache_invalidate_src(lv_img_get_src(obj)); - lv_img_set_src(obj, payload); + const void* src = lv_img_get_src(obj); + lv_img_src_t src_type = lv_img_src_get_type(src); + lv_img_cache_invalidate_src(src); + + if(src_type == LV_IMG_SRC_VARIABLE) { + lv_img_dsc_t* img_dsc = (lv_img_dsc_t*)src; + lodepng_free((uint8_t*)img_dsc->data); + lv_mem_free(img_dsc); + } + + if(payload != strstr_P(payload, PSTR("http://"))) { + lv_img_set_src(obj, payload); + } else { + HTTPClient http; + http.begin(payload); + int httpCode = http.GET(); + if(httpCode == HTTP_CODE_OK) { + int total = http.getSize(); + int len = total; + int read = 0; + lv_img_dsc_t* img_dsc = (lv_img_dsc_t*)lv_mem_alloc(sizeof(lv_img_dsc_t)); + uint8_t* img_buf = (uint8_t*)(len > 0 ? lodepng_malloc(len) : NULL); + + LOG_VERBOSE(TAG_ATTR, "HTTP OK: buffer created of %d bytes", len); + + if(img_dsc && img_buf && len > sizeof(lv_img_header_t)) { // total size must be larger then header size + memset(img_buf, 0, len); + + Stream* stream = http.getStreamPtr(); + while(http.connected() && (len > 0 || len == -1)) { + size_t size = stream->available(); + int c = 0; + + if(size) { + if(read == 0 && size >= sizeof(lv_img_header_t)) { // read 4-byte header first + c = stream->readBytes((uint8_t*)img_dsc, sizeof(lv_img_header_t)); + LOG_VERBOSE(TAG_ATTR, D_BULLET "HEADER READ: %d bytes w=%d h=%d", c, + img_dsc->header.w, img_dsc->header.h); + } else if(read != 0) { // header has been read + c = stream->readBytes(img_buf + read - sizeof(lv_img_header_t), size); + LOG_VERBOSE(TAG_ATTR, D_BULLET "HTTP READ: %d bytes", c); + } + + if(len > 0) { + len -= c; + read += c; + } + } + delay(1); + } + LOG_VERBOSE(TAG_ATTR, D_BULLET "HTTP TOTAL READ: %d bytes, %d expected", read, + img_dsc->header.w * img_dsc->header.h * 2 + 4); + + img_dsc->data_size = total - 4; + img_dsc->data = img_buf; + lv_img_set_src(obj, img_dsc); + + // /*Decode the PNG image*/ + // unsigned char* png_decoded; /*Will be pointer to the decoded image*/ + // uint32_t png_width; /*Will be the width of the decoded image*/ + // uint32_t png_height; /*Will be the width of the decoded image*/ + + // /*Decode the loaded image in ARGB8888 */ + // uint32_t error = lodepng_decode32(&png_decoded, &png_width, &png_height, img_buf, (size_t)total); + + // if(error) { + // LOG_ERROR(TAG_ATTR, "error %u: %s\n", error, lodepng_error_text(error)); + // } else { + // img_dsc->header.always_zero = 0; /*It must be zero*/ + // img_dsc->header.cf = LV_IMG_CF_TRUE_COLOR_ALPHA; /*Set the color format*/ + // img_dsc->header.w = png_width; + // img_dsc->header.h = png_height; + // img_dsc->data_size = png_width * png_height * 3; + // img_dsc->data = png_decoded; + // lv_img_set_src(obj, img_dsc); + // } + + } else { + LOG_WARNING(TAG_ATTR, "image buffer creation failed %d", len); + } + } else { + LOG_WARNING(TAG_ATTR, "HTTP result %d", httpCode); + } + } } else { switch(lv_img_src_get_type(obj)) { case LV_IMG_SRC_FILE: diff --git a/src/hasp_gui.cpp b/src/hasp_gui.cpp index 6ad3b97d..559aa345 100644 --- a/src/hasp_gui.cpp +++ b/src/hasp_gui.cpp @@ -31,6 +31,18 @@ #include "lv_png.h" #endif +#if HASP_USE_BMPDECODE > 0 +#include "lv_bmp.h" +#endif + +#if HASP_USE_GIFDECODE > 0 +#include "lv_gif.h" +#endif + +#if HASP_USE_JPGDECODE > 0 +#include "lv_sjpg.h" +#endif + #define BACKLIGHT_CHANNEL 0 // pwm channel 0-15 #if HASP_USE_SPIFFS > 0 || HASP_USE_LITTLEFS > 0 @@ -272,6 +284,21 @@ void guiSetup() lv_png_init(); #endif + /* Initialize BMP decoder */ +#if HASP_USE_BMPDECODE > 0 + lv_bmp_init(); +#endif + + /* Initialize GIF decoder */ +#if HASP_USE_GIFDECODE > 0 + // lv_gif_init(); +#endif + + /* Initialize JPG decoder */ +#if HASP_USE_JPGDECODE > 0 + lv_split_jpeg_init(); +#endif + #if defined(ARDUINO_ARCH_ESP32) if(psramFound()) { lv_img_cache_set_size(LV_IMG_CACHE_DEF_SIZE_PSRAM); diff --git a/user_setups/linux_sdl/linux_sdl_64bits.ini b/user_setups/linux_sdl/linux_sdl_64bits.ini index 9584f7a6..926ac341 100644 --- a/user_setups/linux_sdl/linux_sdl_64bits.ini +++ b/user_setups/linux_sdl/linux_sdl_64bits.ini @@ -29,6 +29,9 @@ build_flags = -D HASP_USE_CONFIG=0 ; Standalone application, as library -D HASP_USE_DEBUG=1 -D HASP_USE_PNGDECODE=1 + -D HASP_USE_BMPDECODE=1 + -D HASP_USE_GIFDECODE=1 + -D HASP_USE_JPGDECODE=1 -D HASP_USE_MQTT=1 -D MQTT_MAX_PACKET_SIZE=2048 -D HASP_ATTRIBUTE_FAST_MEM= @@ -62,6 +65,9 @@ lib_deps = bblanchon/ArduinoJson@^6.17.2 ; Json(l) parser https://github.com/fvanroie/lv_drivers git+https://github.com/lvgl/lv_lib_png.git#release/v7 + git+https://github.com/lvgl/lv_lib_bmp.git#release/v7 + git+https://github.com/lvgl/gif.git#release/v7 + git+https://github.com/fvanroie/lv_lib_split_jpg.git lib_ignore = paho diff --git a/user_setups/win32/windows_sdl_64bits.ini b/user_setups/win32/windows_sdl_64bits.ini index edfe3417..69974f04 100644 --- a/user_setups/win32/windows_sdl_64bits.ini +++ b/user_setups/win32/windows_sdl_64bits.ini @@ -29,6 +29,9 @@ build_flags = -D HASP_USE_CONFIG=0 ; Standalone application, as library -D HASP_USE_DEBUG=1 -D HASP_USE_PNGDECODE=1 + -D HASP_USE_BMPDECODE=0 + -D HASP_USE_GIFDECODE=0 + -D HASP_USE_JPGDECODE=1 -D HASP_USE_MQTT=1 -D MQTT_MAX_PACKET_SIZE=2048 -D HASP_ATTRIBUTE_FAST_MEM= @@ -84,6 +87,9 @@ lib_deps = bblanchon/ArduinoJson@^6.17.2 ; Json(l) parser https://github.com/fvanroie/lv_drivers git+https://github.com/lvgl/lv_lib_png.git#release/v7 + #git+https://github.com/lvgl/lv_lib_bmp.git#release/v7 + #git+https://github.com/lvgl/gif.git#release/v7 + git+https://github.com/fvanroie/lv_lib_split_jpg.git lib_ignore = paho