diff --git a/.cache/clangd/index/StaticFileHandlers.cpp.7B27CFEA2E9C1EF7.idx b/.cache/clangd/index/StaticFileHandlers.cpp.7B27CFEA2E9C1EF7.idx index 82e55c4..22f0819 100644 Binary files a/.cache/clangd/index/StaticFileHandlers.cpp.7B27CFEA2E9C1EF7.idx and b/.cache/clangd/index/StaticFileHandlers.cpp.7B27CFEA2E9C1EF7.idx differ diff --git a/main/SdCard.cpp b/main/SdCard.cpp index 05e0f27..5876681 100644 --- a/main/SdCard.cpp +++ b/main/SdCard.cpp @@ -37,7 +37,7 @@ bool SdCard::init() { // Configure SDMMC host sdmmc_host_t host = SDMMC_HOST_DEFAULT(); - host.max_freq_khz = SDMMC_FREQ_DEFAULT; // 20 MHz + host.max_freq_khz = SDMMC_FREQ_HIGHSPEED; // 40 MHz (faster image loading) // Initialize SD card power control via internal LDO sd_pwr_ctrl_ldo_config_t ldo_config = { diff --git a/main/WidgetManager.cpp b/main/WidgetManager.cpp index cb7ce5a..c01a23a 100644 --- a/main/WidgetManager.cpp +++ b/main/WidgetManager.cpp @@ -792,24 +792,43 @@ void WidgetManager::createAllWidgets(const ScreenConfig& screen, lv_obj_t* paren lv_obj_t* bgImg = lv_image_create(parent); lv_image_set_src(bgImg, fullPath); - // Position at top-left - lv_obj_set_pos(bgImg, 0, 0); + // Get image dimensions + lv_image_header_t header; + lv_result_t res = lv_image_decoder_get_info(fullPath, &header); - // Apply scaling mode - switch (screen.bgImageMode) { - case BgImageMode::STRETCH: - lv_obj_set_size(bgImg, lv_pct(100), lv_pct(100)); - lv_image_set_inner_align(bgImg, LV_IMAGE_ALIGN_STRETCH); - break; - case BgImageMode::CENTER: - lv_obj_center(bgImg); - break; - case BgImageMode::TILE: - lv_image_set_inner_align(bgImg, LV_IMAGE_ALIGN_TILE); - lv_obj_set_size(bgImg, lv_pct(100), lv_pct(100)); - break; - default: - break; + if (res == LV_RESULT_OK && header.w > 0 && header.h > 0) { + ESP_LOGI(TAG, "Image size: %dx%d", header.w, header.h); + + // Get display/canvas size + int32_t dispW = lv_obj_get_width(parent); + int32_t dispH = lv_obj_get_height(parent); + if (dispW <= 0) dispW = LV_HOR_RES; + if (dispH <= 0) dispH = LV_VER_RES; + + switch (screen.bgImageMode) { + case BgImageMode::STRETCH: { + // Calculate scale to fill display (in 1/256 units for LVGL) + int32_t scaleX = (dispW * 256) / header.w; + int32_t scaleY = (dispH * 256) / header.h; + lv_image_set_scale_x(bgImg, scaleX); + lv_image_set_scale_y(bgImg, scaleY); + lv_obj_set_pos(bgImg, 0, 0); + ESP_LOGI(TAG, "Stretch scale: %ldx%ld", scaleX, scaleY); + break; + } + case BgImageMode::CENTER: + lv_obj_center(bgImg); + break; + case BgImageMode::TILE: + lv_image_set_inner_align(bgImg, LV_IMAGE_ALIGN_TILE); + lv_obj_set_size(bgImg, lv_pct(100), lv_pct(100)); + break; + default: + break; + } + } else { + ESP_LOGW(TAG, "Could not get image info, using default position"); + lv_obj_set_pos(bgImg, 0, 0); } // Send to background (behind all widgets) diff --git a/main/main.cpp b/main/main.cpp index 3c1aee6..9a00599 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -3,6 +3,7 @@ #include "freertos/task.h" #include "esp_log.h" #include "esp_lv_adapter.h" +#include "esp_lv_decoder.h" #include "lvgl.h" #include "Display.hpp" #include "Touch.hpp" @@ -84,7 +85,17 @@ public: if (!SdCard::instance().init()) { ESP_LOGW(TAG, "SD card not available, using defaults"); } - + + // Initialize hardware JPEG/PNG decoder for LVGL (uses ESP32-P4 hardware acceleration) + ESP_LOGI(TAG, "INIT IMAGE DECODER"); + esp_lv_decoder_handle_t decoder_handle = NULL; + esp_err_t dec_err = esp_lv_decoder_init(&decoder_handle); + if (dec_err != ESP_OK) { + ESP_LOGW(TAG, "Failed to init image decoder: %s", esp_err_to_name(dec_err)); + } else { + ESP_LOGI(TAG, "Hardware image decoder initialized"); + } + ESP_LOGI(TAG, "START KNX"); BaseType_t knx_ok = xTaskCreatePinnedToCore( knx_task, "knx", 4096, &Gui::knxWorker, 5, nullptr, 1); diff --git a/sdkconfig b/sdkconfig index bfb155c..b664f67 100644 --- a/sdkconfig +++ b/sdkconfig @@ -2979,8 +2979,8 @@ CONFIG_LV_ASSERT_HANDLER_INCLUDE="assert.h" # Others # # CONFIG_LV_ENABLE_GLOBAL_CUSTOM is not set -CONFIG_LV_CACHE_DEF_SIZE=0 -CONFIG_LV_IMAGE_HEADER_CACHE_DEF_CNT=0 +CONFIG_LV_CACHE_DEF_SIZE=4194304 +CONFIG_LV_IMAGE_HEADER_CACHE_DEF_CNT=8 CONFIG_LV_GRADIENT_MAX_STOPS=2 CONFIG_LV_COLOR_MIX_ROUND_OFS=128 # CONFIG_LV_OBJ_STYLE_CACHE is not set @@ -3184,7 +3184,7 @@ CONFIG_LV_FS_POSIX_CACHE_SIZE=0 # CONFIG_LV_USE_LODEPNG is not set # CONFIG_LV_USE_LIBPNG is not set # CONFIG_LV_USE_BMP is not set -CONFIG_LV_USE_TJPGD=y +# CONFIG_LV_USE_TJPGD is not set # CONFIG_LV_USE_LIBJPEG_TURBO is not set # CONFIG_LV_USE_GIF is not set # CONFIG_LV_BIN_DECODER_RAM_LOAD is not set diff --git a/web-interface/src/components/FileManager.vue b/web-interface/src/components/FileManager.vue index f3ae236..e50b4b9 100644 --- a/web-interface/src/components/FileManager.vue +++ b/web-interface/src/components/FileManager.vue @@ -219,7 +219,7 @@ const imageExtensions = ['png', 'jpg', 'jpeg', 'gif', 'bmp', 'webp', 'svg']; // Image optimization settings for ESP32 const MAX_IMAGE_WIDTH = 1280; // Display width const MAX_IMAGE_HEIGHT = 800; // Display height -const JPEG_QUALITY = 0.75; // 75% quality +const JPEG_QUALITY = 0.80; // 80% quality - good balance function isImageFile(name) { const ext = name.split('.').pop().toLowerCase();