Totally a pile of garbage with a bunch of debug prints because I'm going to have to rewrite the renderer resizing to allow for any size image, not just the map. But this does display an image using averaged squares.
This commit is contained in:
parent
3bb3b654e7
commit
19b8bf1850
7 changed files with 262 additions and 98 deletions
|
@ -1,3 +1,5 @@
|
|||
#include <chrono> // for operator""s, chrono_literals
|
||||
#include <thread> // for sleep_for
|
||||
#include <fmt/core.h>
|
||||
#include <filesystem>
|
||||
#include "panel.hpp"
|
||||
|
@ -5,11 +7,67 @@
|
|||
#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 namespace std;
|
||||
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]);
|
||||
|
@ -20,14 +78,89 @@ int main(int argc, char *argv[]) {
|
|||
sf::Image image;
|
||||
image.loadFromFile(image_file);
|
||||
|
||||
// create a grid panel to hold the cells
|
||||
Panel panel(40,40, 0, 0, true);
|
||||
// divide the image into cells
|
||||
auto size = image.getSize();
|
||||
|
||||
// for each cell:
|
||||
// get the color
|
||||
// calculate value
|
||||
// find character that's closest
|
||||
// write to panel/canvas with ftxui
|
||||
// display in sfml window with renderer
|
||||
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;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue