This commit is contained in:
Thomas Peterson 2026-02-01 21:48:36 +01:00
parent 1e6f65807e
commit ae8bb5a01f
6 changed files with 53 additions and 23 deletions

View File

@ -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 = {

View File

@ -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)

View File

@ -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);

View File

@ -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

View File

@ -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();