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:
Zed A. Shaw 2024-11-21 02:49:58 -05:00
parent 3bb3b654e7
commit 19b8bf1850
7 changed files with 262 additions and 98 deletions

View file

@ -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;
}