diff --git a/lib/lvgl/lv_conf.h b/lib/lvgl/lv_conf.h index 026e2ee2..6bff1096 100644 --- a/lib/lvgl/lv_conf.h +++ b/lib/lvgl/lv_conf.h @@ -47,7 +47,7 @@ #if LV_USE_STDLIB_MALLOC == LV_STDLIB_BUILTIN /*Size of the memory available for `lv_malloc()` in bytes (>= 2kB)*/ - #define LV_MEM_SIZE (1024U * 1024U) /*[bytes]*/ + #define LV_MEM_SIZE (1536U * 1024U) /*[bytes]*/ /*Size of the memory expand for `lv_malloc()` in bytes*/ #define LV_MEM_POOL_EXPAND_SIZE 0 diff --git a/src/tangara/ui/screenshot.cpp b/src/tangara/ui/screenshot.cpp new file mode 100644 index 00000000..e4f9cc3f --- /dev/null +++ b/src/tangara/ui/screenshot.cpp @@ -0,0 +1,48 @@ +/* + * Copyright 2024 jacqueline + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#include "screenshot.hpp" +#include + +#include + +#define LODEPNG_NO_COMPILE_CPP +#include "libs/lodepng/lodepng.h" + +#include "esp_log.h" +#include "lvgl.h" + +namespace ui { + +[[maybe_unused]] static constexpr char kTag[] = "screenshot"; + +auto SaveScreenshot(lv_obj_t* obj, const std::string& path) -> void { + lv_draw_buf_t* buf = lv_snapshot_take(obj, LV_COLOR_FORMAT_RGB888); + if (!buf) { + return; + } + + // LVGL appears to output BGR data instead. Not quite sure why, but swapping + // each pair is quite easy. + for (size_t i = 0; i < buf->data_size; i += 3) { + uint8_t temp = buf->data[i]; + buf->data[i] = buf->data[i + 2]; + buf->data[i + 2] = temp; + } + + // The LVGL lodepng fork uses LVGL's file API, so an extra '/' is needed. + std::string fullpath = "//sdcard/" + path; + + auto res = lodepng_encode_file(fullpath.c_str(), buf->data, buf->header.w, + buf->header.h, LCT_RGB, 8); + + lv_draw_buf_destroy(buf); + if (res != 0) { + ESP_LOGE(kTag, "lodepng error: '%s'", lodepng_error_text(res)); + } +} + +} // namespace ui diff --git a/src/tangara/ui/screenshot.hpp b/src/tangara/ui/screenshot.hpp new file mode 100644 index 00000000..d19be0f0 --- /dev/null +++ b/src/tangara/ui/screenshot.hpp @@ -0,0 +1,17 @@ +/* + * Copyright 2024 jacqueline + * + * SPDX-License-Identifier: GPL-3.0-only + */ + +#pragma once + +#include + +#include "lvgl.h" + +namespace ui { + +auto SaveScreenshot(lv_obj_t* obj, const std::string& path) -> void; + +} diff --git a/src/tangara/ui/ui_fsm.cpp b/src/tangara/ui/ui_fsm.cpp index 4f93fe61..cd39dc9c 100644 --- a/src/tangara/ui/ui_fsm.cpp +++ b/src/tangara/ui/ui_fsm.cpp @@ -65,6 +65,7 @@ #include "ui/screen.hpp" #include "ui/screen_lua.hpp" #include "ui/screen_splash.hpp" +#include "ui/screenshot.hpp" #include "ui/ui_events.hpp" namespace ui { @@ -371,22 +372,7 @@ void UiState::react(const Screenshot& ev) { if (!sCurrentScreen) { return; } - ESP_LOGI(kTag, "taking snapshot"); - lv_draw_buf_t* buf = - lv_snapshot_take(sCurrentScreen->root(), LV_COLOR_FORMAT_RGB888); - if (!buf) { - ESP_LOGW(kTag, "snapshot failed"); - return; - } - ESP_LOGI(kTag, "writing to file"); - std::string fullpath = "//sdcard/" + ev.filename; - auto res = lv_draw_buf_save_to_file(buf, fullpath.c_str()); - lv_draw_buf_destroy(buf); - if (res == LV_RESULT_OK) { - ESP_LOGI(kTag, "write okay!"); - } else { - ESP_LOGE(kTag, "write failed!"); - } + SaveScreenshot(sCurrentScreen->root(), ev.filename); } void UiState::react(const system_fsm::KeyLockChanged& ev) {