2024-01-19 12:05:14 +01:00
|
|
|
#include <memory>
|
|
|
|
#include <libscterm.hpp>
|
|
|
|
#include <netpbm/pam.h>
|
|
|
|
#include "pixels.hpp"
|
|
|
|
|
2024-01-27 16:25:23 +01:00
|
|
|
// truecolor to palette color (216-color)
|
|
|
|
static inline int t2p(int val) {
|
|
|
|
return .5 + 5 * val / 255.0;
|
|
|
|
}
|
|
|
|
|
2024-01-27 16:58:52 +01:00
|
|
|
static void write(std::ostream& os, FILE* in) {
|
2024-01-27 16:25:23 +01:00
|
|
|
char* tc = getenv("TRUECOLOR");
|
|
|
|
std::string truecolor {tc ? tc : ""};
|
|
|
|
bool has_truecolor = truecolor.size() > 0;
|
2024-01-19 12:05:14 +01:00
|
|
|
struct pam info;
|
2024-01-27 16:58:52 +01:00
|
|
|
pnm_readpaminit(in, &info, PAM_STRUCT_SIZE(tuple_type));
|
2024-01-19 12:05:14 +01:00
|
|
|
std::unique_ptr<tuple, void(*)(void*)> row1 {pnm_allocpamrow(&info), pm_freerow};
|
|
|
|
std::unique_ptr<tuple, void(*)(void*)> row2 {pnm_allocpamrow(&info), pm_freerow};
|
|
|
|
for (int y = 0; y < info.height; y += 2) {
|
|
|
|
pnm_readpamrow(&info, row1.get());
|
|
|
|
pnm_readpamrow(&info, row2.get());
|
|
|
|
for (int x = 0; x < info.width; ++x) {
|
|
|
|
if (info.depth == 3) { // assume RGB, 1 byte per sample
|
|
|
|
tuple* t1 {row1.get()};
|
2024-01-27 16:25:23 +01:00
|
|
|
if (has_truecolor) {
|
|
|
|
os << sc::io::truecolorb(t1[x][0], t1[x][1], t1[x][2]);
|
|
|
|
} else {
|
|
|
|
os << sc::io::rgbb(t2p(t1[x][0]), t2p(t1[x][1]), t2p(t1[x][2]));
|
|
|
|
}
|
2024-01-19 12:05:14 +01:00
|
|
|
tuple* t2 {row2.get()};
|
2024-01-27 16:25:23 +01:00
|
|
|
if (has_truecolor) {
|
|
|
|
os << sc::io::truecolorf(t2[x][0], t2[x][1], t2[x][2]);
|
|
|
|
} else {
|
|
|
|
os << sc::io::rgbf(t2p(t2[x][0]), t2p(t2[x][1]), t2p(t2[x][2]));
|
|
|
|
}
|
2024-01-19 12:05:14 +01:00
|
|
|
os << u8"\u2584"; // unicode lower half block
|
|
|
|
}
|
|
|
|
}
|
|
|
|
os << sc::io::reset << '\n';
|
|
|
|
}
|
|
|
|
}
|
2024-01-27 16:58:52 +01:00
|
|
|
|
|
|
|
void write_image(std::ostream& os) {
|
|
|
|
write(os, stdin);
|
|
|
|
}
|
|
|
|
|
|
|
|
void write_image(std::ostream& os, const std::string& path) {
|
|
|
|
std::unique_ptr<FILE, void(*)(FILE*)> infile {pm_openr(path.c_str()), pm_close};
|
|
|
|
write(os, infile.get());
|
|
|
|
}
|