Storage: view pictures, PNG, JPEG, BMP and GIF (#45)
CI / build (pull_request) Successful in 1m56s
Site / build (pull_request) Successful in 10s

Enter on a picture shows it: shrunk to fit the screen, or at its own size
with Enter again and the arrows to move. Dithered to the screen's 256
colours; a colour the screen has exactly is left alone, so screenshots are
shown as they are.

The picture is decoded once, straight into the screen's buffer, and kept
there (App::retainsContent): no copy in memory. Decoding runs on the
storage task, so the keys keep working and a 12 megapixel photograph
appears as it comes instead of tripping the watchdog.

PNG, BMP and GIF are read by decoders of our own, host-tested against files
made by Pillow; the PNG one needs 32 KB where the display library's needed
44 KB in one block, which the device often doesn't have. JPEG uses the
library's TJpgDec.

Also corrects two sentences that still gave 16 KB as the editing limit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EhqxQ49eCju4CzKYNjZzwT
This commit is contained in:
2026-10-07 21:04:39 +02:00
co-authored by Claude Opus 5.5
parent ae25cf0be2
commit 2c18762614
22 changed files with 2074 additions and 9 deletions
+16 -2
View File
@@ -13,10 +13,23 @@ bool Screen::begin() {
}
void Screen::render(AppManager& apps, const StatusInfo& status, const Toast* toast) {
canvas_.fillSprite(theme::kBackground);
const auto& area = theme::kContent;
App& app = apps.foreground();
// An App that keeps what it drew: only the Status Bar is cleared, unless the App has changed
// or a Toast or the help panel, drawn over it, has just gone.
bool overlay = apps.help().isOpen() || toast, retains = app.retainsContent();
if (overlayWas_ && !overlay) lost_ = true;
if (retains && &app == lastApp_ && !lost_) {
canvas_.fillRect(0, 0, theme::kWidth, area.y, theme::kBackground);
} else {
canvas_.fillSprite(theme::kBackground);
if (retains) app.contentLost();
}
lastApp_ = &app;
lost_ = false;
overlayWas_ = overlay && retains;
canvas_.setClipRect(area.x, area.y, area.w, area.h);
apps.foreground().draw(canvas_);
app.draw(canvas_);
if (apps.help().isOpen()) widgets::help(canvas_, apps.help()); // over the App, under the Status Bar
canvas_.clearClipRect();
widgets::statusBar(canvas_, status);
@@ -25,6 +38,7 @@ void Screen::render(AppManager& apps, const StatusInfo& status, const Toast* toa
}
void Screen::renderUpdate(const std::string& title, const std::string& detail, int percent) {
lost_ = true;
canvas_.fillSprite(theme::kBackground);
canvas_.setTextDatum(top_center);
canvas_.setFont(&fonts::bold);