Public Access
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
58 lines
2.0 KiB
C++
58 lines
2.0 KiB
C++
#pragma once
|
|
|
|
#include <memory>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include "image_file.h"
|
|
#include "key_event.h"
|
|
#include "key_help.h"
|
|
#include "services/storage_service.h"
|
|
#include "ui/canvas.h"
|
|
|
|
namespace roro {
|
|
|
|
// A picture from the card, for the Storage App's viewer (issue #45, F1 Q233-Q242): PNG, JPEG, BMP
|
|
// and the first picture of a GIF (only JPEG needs a decoder that isn't ours). It is decoded once, straight into the screen's own buffer, and
|
|
// left there (App::retainsContent): there is no copy of it in memory. It is decoded again only
|
|
// when something else was drawn over it, or when it is zoomed or moved.
|
|
//
|
|
// The decoding runs on the storage task while the main loop goes on: a photograph takes seconds,
|
|
// and the picture appears as it comes. Anything that needs the screen back stops it first.
|
|
class ImagePane {
|
|
public:
|
|
explicit ImagePane(StorageService& storage) : storage_(storage) {}
|
|
|
|
std::string open(const std::string& path, uint32_t size); // "" or why it can't be shown
|
|
void close();
|
|
bool onKey(const KeyEvent& e); // true: the key was the picture's
|
|
void help(std::vector<KeyHelp>& out) const;
|
|
bool update(uint32_t nowMs); // true: draw again
|
|
void draw(Canvas& c);
|
|
void lost(); // the screen no longer holds it
|
|
void say(const std::string& text);
|
|
|
|
struct Job; // one decoding: shared with the storage task, which may outlive the view of it
|
|
|
|
private:
|
|
enum class Phase { Wanted, Decoding, Shown };
|
|
|
|
std::string describe() const;
|
|
void start(Canvas& c);
|
|
void cancel(); // returns once the storage task has let go of the screen
|
|
void hideNote(Canvas* c);
|
|
|
|
StorageService& storage_;
|
|
std::string path_, problem_, note_;
|
|
uint32_t size_ = 0, noteMs_ = 0, shotAt_ = 0, pushedMs_ = 0;
|
|
files::ImageInfo info_;
|
|
files::ImageFrame frame_;
|
|
Phase phase_ = Phase::Wanted;
|
|
std::shared_ptr<Job> job_;
|
|
Canvas* canvas_ = nullptr;
|
|
bool told_ = false, noteDrawn_ = false;
|
|
std::vector<uint8_t> under_; // what the note was written over
|
|
};
|
|
|
|
} // namespace roro
|