|
19 | 19 |
|
20 | 20 | #include <terminal/Capabilities.h>
|
21 | 21 | #include <terminal/Parser.h>
|
| 22 | +#include <terminal/Image.h> |
22 | 23 |
|
| 24 | +#include <crispy/base64.h> |
23 | 25 | #include <crispy/debuglog.h>
|
| 26 | +#include <crispy/stdfs.h> |
24 | 27 | #include <crispy/utils.h>
|
25 | 28 |
|
26 | 29 | #include <fstream>
|
27 | 30 | #include <memory>
|
28 | 31 |
|
| 32 | +#define GOOD_IMAGE_PROTOCOL // TODO use cmake here instead |
| 33 | + |
29 | 34 | using std::bind;
|
30 | 35 | using std::cout;
|
| 36 | +using std::ifstream; |
31 | 37 | using std::make_unique;
|
32 | 38 | using std::ofstream;
|
33 | 39 | using std::string;
|
34 | 40 | using std::string_view;
|
35 | 41 | using std::unique_ptr;
|
| 42 | +using std::vector; |
36 | 43 |
|
37 | 44 | using namespace std::string_literals;
|
| 45 | +using namespace std::string_view_literals; |
38 | 46 |
|
39 | 47 | namespace CLI = crispy::cli;
|
40 | 48 |
|
41 | 49 | namespace contour {
|
42 | 50 |
|
| 51 | +#if defined(GOOD_IMAGE_PROTOCOL) // {{{ |
| 52 | +terminal::ImageAlignment parseImageAlignment(string_view _text) |
| 53 | +{ |
| 54 | + (void) _text; |
| 55 | + return terminal::ImageAlignment::TopStart; // TODO |
| 56 | +} |
| 57 | + |
| 58 | +terminal::ImageResize parseImageResize(string_view _text) |
| 59 | +{ |
| 60 | + (void) _text; |
| 61 | + return terminal::ImageResize::NoResize; // TODO |
| 62 | +} |
| 63 | + |
| 64 | +terminal::Coordinate parsePosition(string_view _text) |
| 65 | +{ |
| 66 | + (void) _text; |
| 67 | + return {}; // TODO |
| 68 | +} |
| 69 | + |
| 70 | +// TODO: chunkedFileReader(path) to return iterator over spans of data chunks. |
| 71 | +std::vector<uint8_t> readFile(FileSystem::path const& _path) |
| 72 | +{ |
| 73 | + auto ifs = ifstream(_path.string()); |
| 74 | + if (!ifs.good()) |
| 75 | + return {}; |
| 76 | + |
| 77 | + auto const size = FileSystem::file_size(_path); |
| 78 | + auto text = vector<uint8_t>(); |
| 79 | + text.resize(size); |
| 80 | + ifs.read((char*) &text[0], size); |
| 81 | + return text; |
| 82 | +} |
| 83 | + |
| 84 | +void displayImage(terminal::ImageResize _resizePolicy, |
| 85 | + terminal::ImageAlignment _alignmentPolicy, |
| 86 | + crispy::Size _screenSize, |
| 87 | + string_view _fileName) |
| 88 | +{ |
| 89 | + auto constexpr ST = "\033\\"sv; |
| 90 | + |
| 91 | + cout << fmt::format("{}f={},c={},l={},a={},z={};", |
| 92 | + "\033Ps"sv, // GIONESHOT |
| 93 | + '0', // image format: 0 = auto detect |
| 94 | + _screenSize.width, |
| 95 | + _screenSize.height, |
| 96 | + int(_alignmentPolicy), |
| 97 | + int(_resizePolicy) |
| 98 | + ); |
| 99 | + |
| 100 | +#if 1 |
| 101 | + auto const data = readFile(_fileName);// TODO: incremental buffered read |
| 102 | + auto encoderState = crispy::base64::EncoderState{}; |
| 103 | + |
| 104 | + vector<char> buf; |
| 105 | + auto const writer = [&](string_view _data) { for (auto ch: _data) buf.push_back(ch); }; |
| 106 | + auto const flush = [&]() { cout.write(buf.data(), buf.size()); buf.clear(); }; |
| 107 | + |
| 108 | + for (uint8_t const byte: data) |
| 109 | + { |
| 110 | + crispy::base64::encode(byte, encoderState, writer); |
| 111 | + if (buf.size() >= 4096) |
| 112 | + flush(); |
| 113 | + } |
| 114 | + flush(); |
| 115 | +#endif |
| 116 | + |
| 117 | + cout << ST; |
| 118 | +} |
| 119 | +#endif // }}} |
| 120 | + |
43 | 121 | ContourApp::ContourApp() :
|
44 | 122 | App("contour", "Contour Terminal Emulator", CONTOUR_VERSION_STRING)
|
45 | 123 | {
|
@@ -135,6 +213,28 @@ int ContourApp::profileAction()
|
135 | 213 | return EXIT_SUCCESS;
|
136 | 214 | }
|
137 | 215 |
|
| 216 | +#if defined(GOOD_IMAGE_PROTOCOL) |
| 217 | +crispy::Size parseSize(string_view _text) |
| 218 | +{ |
| 219 | + (void) _text; |
| 220 | + return crispy::Size{};//TODO |
| 221 | +} |
| 222 | + |
| 223 | +int ContourApp::imageAction() |
| 224 | +{ |
| 225 | + auto const resizePolicy = parseImageResize(parameters().get<string>("contour.image.resize")); |
| 226 | + auto const alignmentPolicy = parseImageAlignment(parameters().get<string>("contour.image.align")); |
| 227 | + auto const size = parseSize(parameters().get<string>("contour.image.size")); |
| 228 | + auto const fileName = parameters().verbatim.front(); |
| 229 | + // TODO: how do we wanna handle more than one verbatim arg (image)? |
| 230 | + // => report error and EXIT_FAILURE as only one verbatim arg is allowed. |
| 231 | + // FIXME: What if parameter `size` is given as `_size` instead, it should cause an |
| 232 | + // invalid-argument error above already! |
| 233 | + displayImage(resizePolicy, alignmentPolicy, size, fileName); |
| 234 | + return EXIT_SUCCESS; |
| 235 | +} |
| 236 | +#endif |
| 237 | + |
138 | 238 | crispy::cli::Command ContourApp::parameterDefinition() const
|
139 | 239 | {
|
140 | 240 | return CLI::Command{
|
@@ -199,6 +299,37 @@ crispy::cli::Command ContourApp::parameterDefinition() const
|
199 | 299 | }
|
200 | 300 | }
|
201 | 301 | },
|
| 302 | +#if defined(GOOD_IMAGE_PROTOCOL) |
| 303 | + CLI::Command{ |
| 304 | + "image", |
| 305 | + "Sends an image to the terminal emulator for display.", |
| 306 | + CLI::OptionList{ |
| 307 | + CLI::Option{"resize", CLI::Value{"fit"s}, |
| 308 | + "Sets the image resize policy.\n" |
| 309 | + "Policies available are:\n" |
| 310 | + " - no (no resize),\n" |
| 311 | + " - fit (resize to fit),\n" |
| 312 | + " - fill (resize to fill),\n" |
| 313 | + " - stretch (stretch to fill)." |
| 314 | + }, |
| 315 | + CLI::Option{"align", CLI::Value{"center"s}, |
| 316 | + "Sets the image alignment policy.\n" |
| 317 | + "Possible policies are: TopLeft, TopCenter, TopRight, MiddleLeft, MiddleCenter, MiddleRight, BottomLeft, BottomCenter, BottomRight." |
| 318 | + }, |
| 319 | + CLI::Option{"size", CLI::Value{""s}, |
| 320 | + "Sets the amount of columns and rows to place the image onto. " |
| 321 | + "The top-left of the this area is the current cursor position, " |
| 322 | + "and it will be scrolled automatically if not enough rows are present." |
| 323 | + } |
| 324 | + }, |
| 325 | + CLI::CommandList{}, |
| 326 | + CLI::CommandSelect::Explicit, |
| 327 | + CLI::Verbatim{ |
| 328 | + "IMAGE_FILE", |
| 329 | + "Path to image to be displayed. Image formats supported are at least PNG, JPG." |
| 330 | + } |
| 331 | + }, |
| 332 | +#endif |
202 | 333 | CLI::Command{
|
203 | 334 | "capture",
|
204 | 335 | "Captures the screen buffer of the currently running terminal.",
|
|
0 commit comments