Encode snapshots as PNGs when saving to disk

custom
jacqueline 9 months ago
parent 7012e64a14
commit 2ab459598c
  1. 2
      lib/lvgl/lv_conf.h
  2. 48
      src/tangara/ui/screenshot.cpp
  3. 17
      src/tangara/ui/screenshot.hpp
  4. 18
      src/tangara/ui/ui_fsm.cpp

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

@ -0,0 +1,48 @@
/*
* Copyright 2024 jacqueline <me@jacqueline.id.au>
*
* SPDX-License-Identifier: GPL-3.0-only
*/
#include "screenshot.hpp"
#include <sys/_stdint.h>
#include <string>
#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

@ -0,0 +1,17 @@
/*
* Copyright 2024 jacqueline <me@jacqueline.id.au>
*
* SPDX-License-Identifier: GPL-3.0-only
*/
#pragma once
#include <string>
#include "lvgl.h"
namespace ui {
auto SaveScreenshot(lv_obj_t* obj, const std::string& path) -> void;
}

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

Loading…
Cancel
Save