Haio
0.2.X
Homebrew Asset IO/CDN
Toggle main menu visibility
Loading...
Searching...
No Matches
encode.cpp
Go to the documentation of this file.
1
#include <
haio_codec.hpp
>
2
#include <haio_codecs.hpp>
3
#include <
haio_convert.hpp
>
4
5
#include <string>
6
7
namespace
{
8
9
/** a cell is two spaces because a terminal cell is about twice as tall as it is wide */
10
constexpr
std::string_view cell =
" "
;
11
12
void
appendNumber(std::string& out,
int
value) {
13
out += std::to_string(value);
14
}
15
16
}
17
18
namespace
Haio::Codecs
{
19
20
/**
21
* one terminal cell per pixel, coloured by its background.
22
*
23
* the picture ends up half the height of the utf8 one for the same number of rows,
24
* and it works on anything that can colour a background, including terminals with no
25
* font to draw a half block with.
26
*
27
* @todo a terminal that cannot do 24 bit colour renders this as noise. detecting that
28
* means reading COLORTERM, and falling back means quantising to the 256 colour cube.
29
*/
30
template
<>
31
Result<Blob>
Encode<Format::ANSI, Color::RGB888>
(Image<Color::RGB888> img) {
32
const
Size size{img.width, img.height};
33
HAIO_TRY
(expected,
sizeOf
(
Color::RGB888
, size));
34
if
(img.data.size() != expected)
HAIO_FAIL
(InvalidInput,
"invalid rgb888 image for ansi encode"
);
35
36
std::string out;
37
// every cell carries an escape sequence of its own, so the text is far larger
38
// than the picture: reserving up from the start saves growing it a hundred times
39
out.reserve(
static_cast<
size_t
>
(img.width) *
static_cast<
size_t
>
(img.height) * 20);
40
41
for
(
int
y = 0; y < img.height; y++) {
42
// a terminal keeps the colour it was last told, and a run of one colour is
43
// the common case in the pictures anybody renders here
44
uint32_t last = 0;
45
bool
anySoFar =
false
;
46
47
for
(
int
x = 0; x < img.width; x++) {
48
const
auto
at = (
static_cast<
size_t
>
(y) *
static_cast<
size_t
>
(img.width) +
static_cast<
size_t
>
(x)) * 3;
49
const
uint32_t colour = (
static_cast<
uint32_t
>
(img.data[at + 0]) << 16)
50
| (
static_cast<
uint32_t
>
(img.data[at + 1]) << 8)
51
| img.data[at + 2];
52
53
if
(!anySoFar || colour != last) {
54
out +=
"\x1b[48;2;"
;
55
appendNumber(out, img.data[at + 0]);
56
out +=
';'
;
57
appendNumber(out, img.data[at + 1]);
58
out +=
';'
;
59
appendNumber(out, img.data[at + 2]);
60
out +=
'm'
;
61
last = colour;
62
anySoFar =
true
;
63
}
64
out += cell;
65
}
66
// reset at the end of every row, so a terminal that wraps does not paint the
67
// rest of the line in whatever colour the last pixel was
68
out +=
"\x1b[0m\n"
;
69
}
70
71
return
Blob{
Format::ANSI
,
Color::RGB888
,
"text/x-ansi"
, {}, std::vector<uint8_t>(out.begin(), out.end())};
72
}
73
74
}
haio_codec.hpp
HAIO_TRY
#define HAIO_TRY(name, expr)
Definition
haio_codec.hpp:246
HAIO_FAIL
#define HAIO_FAIL(why, message)
Definition
haio_codec.hpp:258
haio_convert.hpp
Haio::Codecs
Definition
haio_codec.hpp:136
Haio::Codecs::Encode< Format::ANSI, Color::RGB888 >
Result< Blob > Encode< Format::ANSI, Color::RGB888 >(Image< Color::RGB888 > img)
Definition
encode.cpp:31
Haio::Color::RGB888
@ RGB888
Definition
haio_formats.hpp:108
Haio::Result
std::expected< T, Error > Result
Definition
haio_codec.hpp:32
Haio::sizeOf
Result< size_t > sizeOf(Color color, Size size)
Definition
sizes.cpp:6
Haio::Format::ANSI
@ ANSI
Definition
haio_formats.hpp:68
library
backend
codecs
container
ansi
encode.cpp
Generated by
1.18.0