Skip to content

Commit

Permalink
experimental: improve image as logo in terminal
Browse files Browse the repository at this point in the history
  • Loading branch information
Toni500github committed Sep 16, 2024
1 parent 12f41ef commit 1247f53
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 20 deletions.
1 change: 1 addition & 0 deletions include/util.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ byte_units_t auto_devide_bytes(const size_t num);
bool is_file_image(const unsigned char* bytes);
void ctrl_d_handler(const std::istream& cin);
std::string expandVar(std::string ret);
bool taur_exec(const std::vector<std::string> cmd_str, const bool noerror_print = true);
std::string which(const std::string& command);
bool read_binary_file(std::ifstream& f, std::string& ret);
void replace_str(std::string& str, const std::string_view from, const std::string_view to);
Expand Down
2 changes: 1 addition & 1 deletion src/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ void Config::loadConfigFile(const std::string_view filename, colors_t& colors)
this->offset = this->getValue<std::uint16_t>("config.offset", 5);
this->logo_padding_left = this->getValue<std::uint16_t>("config.logo-padding-left", 0);
this->layout_padding_top = this->getValue<std::uint16_t>("config.layout-padding-top", 0);
this->logo_padding_top = this->getValue<std::uint16_t>("config.logo-padding-top", 0);
this->font = this->getValue<std::string>("gui.font", "Liberation Mono Normal 12");
this->gui_bg_image = this->getValue<std::string>("gui.bg-image", "disable");
this->logo_padding_top = this->getValue<std::uint16_t>("config.logo-padding-top", 0);

this->builtin_title_sep = this->getValue<std::string>("config.title-sep", "-");

Expand Down
83 changes: 64 additions & 19 deletions src/display.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#include "display.hpp"

#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
#include <termios.h>

#include <algorithm>
#include <array>
Expand All @@ -16,6 +16,7 @@
#include "fmt/core.h"
#include "parse.hpp"
#include "query.hpp"
#include "stb_image.h"
#include "util.hpp"

std::string Display::detect_distro(const Config& config)
Expand Down Expand Up @@ -43,9 +44,10 @@ std::string Display::detect_distro(const Config& config)
}
}

static std::vector<std::string> render_with_image(const Config& config, const colors_t& colors)
static std::vector<std::string> render_with_image(const Config& config, const colors_t& colors,
const std::string_view path)
{
std::string path{ Display::detect_distro(config) };
std::string distro_path{ Display::detect_distro(config) };
systemInfo_t systemInfo{};
std::vector<std::string> layout{ config.layout };

Expand All @@ -58,19 +60,19 @@ static std::vector<std::string> render_with_image(const Config& config, const co
stbi_image_free(img);
else
die("Unable to load image '{}'", config.source_path);

if (!config.ascii_logo_type.empty())
{
const size_t& pos = path.rfind('.');

if (pos != std::string::npos)
path.insert(pos, "_" + config.ascii_logo_type);
distro_path.insert(pos, "_" + config.ascii_logo_type);
else
path += "_" + config.ascii_logo_type;
distro_path += "_" + config.ascii_logo_type;
}

// this is just for parse() to auto add the distro colors
std::ifstream file(path, std::ios::binary);
std::ifstream file(distro_path, std::ios::binary);
std::string line, _;

while (std::getline(file, line))
Expand All @@ -85,14 +87,59 @@ static std::vector<std::string> render_with_image(const Config& config, const co
layout.end());

for (size_t i = 0; i < layout.size(); i++)
{
for (size_t _ = 0; _ < config.offset; _++) // I use _ because we don't need it
for (size_t _ = 0; _ < config.offset + 40; _++) // I use _ because we don't need it
layout.at(i).insert(0, " ");
}

return layout;
}

bool get_pos(std::uint32_t& y, std::uint32_t& x)
{
char buf[30] = { 0 };
int ret, i, pow;
char ch;

y = 0;
x = 0;

struct termios term, restore;

tcgetattr(0, &term);
tcgetattr(0, &restore);
term.c_lflag &= ~(ICANON | ECHO);
tcsetattr(0, TCSANOW, &term);

write(1, "\033[6n", 4);

for (i = 0, ch = 0; ch != 'R'; i++)
{
ret = read(0, &ch, 1);
if (!ret)
{
tcsetattr(0, TCSANOW, &restore);
fprintf(stderr, "getpos: error reading response!\n");
return false;
}
buf[i] = ch;
debug("buf[{}]: \t{} \t{}", i, ch, ch);
}

if (i < 2)
{
tcsetattr(0, TCSANOW, &restore);
return false;
}

for (i -= 2, pow = 1; buf[i] != ';'; i--, pow *= 10)
x = x + (buf[i] - '0') * pow;

for (i--, pow = 1; buf[i] != '['; i--, pow *= 10)
y = y + (buf[i] - '0') * pow;

tcsetattr(0, TCSANOW, &restore);
return true;
}

std::vector<std::string> Display::render(const Config& config, const colors_t& colors, const bool already_analyzed_file,
const std::string_view path)
{
Expand Down Expand Up @@ -120,8 +167,6 @@ std::vector<std::string> Display::render(const Config& config, const colors_t& c
std::string line;
std::vector<size_t> pureAsciiArtLens;
int maxLineLength = -1;
std::string image_backend_cmd;


// first check if the file is an image
// without even using the same library that "file" uses
Expand All @@ -133,12 +178,13 @@ std::vector<std::string> Display::render(const Config& config, const colors_t& c
fileToAnalyze.read(reinterpret_cast<char*>(&buffer.at(0)), buffer.size());
if (is_file_image(buffer.data()))
{
std::uint32_t x = 0, y = 0;
get_pos(x, y);
fmt::print("\033[{};{}H", x, y);
if (config.m_image_backend == "kitty")
{
image_backend_cmd = fmt::format("kitty +kitten icat --align left {}", path);
}
shell_exec(image_backend_cmd);
return render_with_image(config, colors);
taur_exec({ "kitty", "+kitten", "icat", "--align", "left", path.data() });

return render_with_image(config, colors, path);
}
/* die("The source file '{}' is a binary file.\n"
"Please currently use the GUI mode for rendering the image/gif (use -h for more details)",
Expand Down Expand Up @@ -251,7 +297,6 @@ std::vector<std::string> Display::render(const Config& config, const colors_t& c
}

return layout;

}

void Display::display(const std::vector<std::string>& renderResult)
Expand Down
43 changes: 43 additions & 0 deletions src/util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,49 @@ bool read_exec(std::vector<const char*> cmd, std::string& output, bool useStdErr
return false;
}

/** Executes commands with execvp() and keep the program running without existing
* @param cmd_str The command to execute
* @param exitOnFailure Whether to call exit(1) on command failure.
* @return true if the command successed, else false
*/
bool taur_exec(const std::vector<std::string> cmd_str, const bool noerror_print)
{
std::vector<const char*> cmd;
for (const std::string_view str : cmd_str)
cmd.push_back(str.data());

int pid = fork();

if (pid < 0)
{
die("fork() failed: {}", strerror(errno));
}

if (pid == 0)
{
debug("running {}", cmd);
cmd.push_back(nullptr);
execvp(cmd[0], const_cast<char* const*>(cmd.data()));

// execvp() returns instead of exiting when failed
die("An error has occurred: {}: {}", cmd[0], strerror(errno));
}
else if (pid > 0)
{ // we wait for the command to finish then start executing the rest
int status;
waitpid(pid, &status, 0); // Wait for the child to finish

if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
return true;
else
{
if (!noerror_print)
error("Failed to execute the command: {}", fmt::join(cmd, " "));
}
}

return false;
}
std::string str_tolower(std::string str)
{
for (char& x : str)
Expand Down

0 comments on commit 1247f53

Please sign in to comment.