|
|
|
#include <chrono> // for operator""s, chrono_literals
|
|
|
|
#include <thread> // for sleep_for
|
|
|
|
#include <fmt/core.h>
|
|
|
|
#include <filesystem>
|
|
|
|
#include "panel.hpp"
|
|
|
|
#include "color.hpp"
|
|
|
|
#include "render.hpp"
|
|
|
|
#include "dbc.hpp"
|
|
|
|
#include <SFML/Graphics/Image.hpp>
|
|
|
|
#include <ftxui/screen/color.hpp>
|
|
|
|
#include <ftxui/screen/terminal.hpp>
|
|
|
|
#include <iostream>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <io.h>
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
using namespace std::chrono_literals;
|
|
|
|
using namespace fmt;
|
|
|
|
using std::string, std::cout, std::vector;
|
|
|
|
|
|
|
|
struct HSVColor {
|
|
|
|
unsigned long h = 0;
|
|
|
|
unsigned long s = 0;
|
|
|
|
unsigned long v = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct RGBColor {
|
|
|
|
unsigned long r = 0;
|
|
|
|
unsigned long g = 0;
|
|
|
|
unsigned long b = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
// taken from https://github.com/python/cpython/blob/3.9/Lib/colorsys.py#L140
|
|
|
|
HSVColor rgb_to_hsv(sf::Color rgb) {
|
|
|
|
float r = rgb.r / 255.0f;
|
|
|
|
float g = rgb.g / 255.0f;
|
|
|
|
float b = rgb.b / 255.0f;
|
|
|
|
|
|
|
|
float maxc = std::max({rgb.r, rgb.g, rgb.b});
|
|
|
|
float minc = std::min({rgb.r, rgb.g, rgb.b});
|
|
|
|
float v = maxc;
|
|
|
|
|
|
|
|
// if minc == maxc:
|
|
|
|
if(minc == maxc) {
|
|
|
|
// no hue no sat, so gray with value
|
|
|
|
return {0, 0, uint8_t(v * 255.0)};
|
|
|
|
}
|
|
|
|
|
|
|
|
float s = (maxc - minc) / maxc;
|
|
|
|
float rc = (maxc - r) / (maxc - minc);
|
|
|
|
float gc = (maxc - g) / (maxc - minc);
|
|
|
|
float bc = (maxc - b) / (maxc - minc);
|
|
|
|
float h = 0.0f;
|
|
|
|
|
|
|
|
if(r == maxc) {
|
|
|
|
h = bc-gc;
|
|
|
|
} else if(g == maxc) {
|
|
|
|
h = 2.0 + rc - bc;
|
|
|
|
} else {
|
|
|
|
h = 4.0 + gc - rc;
|
|
|
|
h = std::fmod((h/6.0), 1.0);
|
|
|
|
}
|
|
|
|
|
|
|
|
return {uint8_t(h * 255.0f), uint8_t(s * 255.0f), uint8_t(v * 255.0f)};
|
|
|
|
}
|
|
|
|
|
|
|
|
int main(int argc, char *argv[]) {
|
|
|
|
ftxui::Terminal::SetColorSupport(ftxui::Terminal::Color::TrueColor);
|
|
|
|
|
|
|
|
_setmode(_fileno(stdout), _O_U16TEXT);
|
|
|
|
dbc::check(argc == 2, "USAGE: img2ansi <image_file>");
|
|
|
|
|
|
|
|
string image_file(argv[1]);
|
|
|
|
|
|
|
|
println("LOADING IMAGE: {}", image_file);
|
|
|
|
|
|
|
|
// load the image from argv
|
|
|
|
sf::Image image;
|
|
|
|
image.loadFromFile(image_file);
|
|
|
|
|
|
|
|
// divide the image into cells
|
|
|
|
auto size = image.getSize();
|
|
|
|
|
|
|
|
const int cell = 10;
|
|
|
|
|
|
|
|
// create a grid panel to hold the cells
|
|
|
|
Panel panel(0, 0, GAME_MAP_POS, 0, true);
|
|
|
|
Point view_port{0,0};
|
|
|
|
|
|
|
|
println("IMAGE SIZE {},{}", size.x, size.y);
|
|
|
|
RGBColor avg{0,0,0};
|
|
|
|
|
|
|
|
typedef vector<RGBColor> ColorRow;
|
|
|
|
vector<ColorRow> colors(size.x / cell, ColorRow(size.y / cell));
|
|
|
|
|
|
|
|
// LOL, so bad but just the start
|
|
|
|
for(unsigned int i = 0; i < size.x / cell; i++) {
|
|
|
|
for(unsigned int j = 0; j < size.y / cell; j++) {
|
|
|
|
|
|
|
|
// sum the cell
|
|
|
|
for(unsigned int x = 0; x < cell ; x++) {
|
|
|
|
for(unsigned int y = 0; y < cell ; y++) {
|
|
|
|
auto pixel = image.getPixel((i*cell) + x, (j * cell) + y);
|
|
|
|
|
|
|
|
avg.r += pixel.r;
|
|
|
|
avg.g += pixel.g;
|
|
|
|
avg.b += pixel.b;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// average it for the cell size
|
|
|
|
RGBColor color = {avg.r / (cell * cell),
|
|
|
|
avg.g / (cell * cell), avg.b / (cell * cell)};
|
|
|
|
|
|
|
|
// add it
|
|
|
|
colors[i][j] = color;
|
|
|
|
|
|
|
|
// reset
|
|
|
|
avg = {0,0,0};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Canvas drawing;
|
|
|
|
|
|
|
|
|
|
|
|
SFMLRender renderer;
|
|
|
|
// NEED TO RESIZE FOR IT TO SHOW
|
|
|
|
// this shows that I need more refinement on the renderer
|
|
|
|
// for example, this won't let me do arbitrary resize and
|
|
|
|
// is still locked to the map, but I need arbitrary for the
|
|
|
|
// scenes
|
|
|
|
if(renderer.resize_grid(50, view_port)) {
|
|
|
|
println("RESIZED: {},{}", view_port.x, view_port.y);
|
|
|
|
// set canvas to best size
|
|
|
|
drawing = Canvas(view_port.x * 2, view_port.y * 4);
|
|
|
|
panel.resize(view_port.x, view_port.y);
|
|
|
|
}
|
|
|
|
|
|
|
|
panel.set_renderer(Renderer([&]{
|
|
|
|
for(size_t x = 0; x < colors.size(); x++) {
|
|
|
|
for(size_t y = 0; y < colors[0].size(); y++) {
|
|
|
|
auto color = colors[x][y];
|
|
|
|
ftxui::Color block = ftxui::Color::RGB(color.r, color.g, color.b);
|
|
|
|
drawing.DrawText(x * 2, y * 4, "█", block);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ftxui::canvas(drawing);
|
|
|
|
}));
|
|
|
|
|
|
|
|
sf::Event event;
|
|
|
|
|
|
|
|
while(renderer.is_open()) {
|
|
|
|
renderer.draw(panel);
|
|
|
|
renderer.display();
|
|
|
|
|
|
|
|
while(renderer.poll_event(event)) {
|
|
|
|
if(event.type == sf::Event::Closed) {
|
|
|
|
renderer.close();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
std::this_thread::sleep_for(10ms);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|