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.

main
Zed A. Shaw 2 days ago
parent 3bb3b654e7
commit 19b8bf1850
  1. 2
      Makefile
  2. 175
      ansi_parser.cpp
  3. 15
      ansi_parser.rl
  4. 2
      gui.cpp
  5. 13
      render.cpp
  6. 2
      render.hpp
  7. 151
      scratchpad/img2ansi.cpp

@ -27,4 +27,4 @@ clean:
meson compile --clean -C builddir meson compile --clean -C builddir
debug: debug:
gdb --nx -x .gdbinit builddir/roguish.exe gdb --nx -x .gdbinit builddir/img2ansi.exe

@ -10,96 +10,98 @@
using namespace fmt; using namespace fmt;
#line 110 "ansi_parser.rl" #line 115 "ansi_parser.rl"
#line 13 "ansi_parser.cpp" #line 13 "ansi_parser.cpp"
static const char _foo_actions[] = { static const char _ansi_parser_actions[] = {
0, 1, 0, 1, 3, 1, 4, 1, 0, 1, 0, 1, 3, 1, 4, 1,
5, 1, 6, 1, 7, 1, 8, 1, 5, 1, 6, 1, 7, 1, 8, 1,
9, 1, 10, 1, 14, 1, 15, 2, 9, 1, 10, 1, 11, 1, 15, 1,
1, 11, 2, 1, 12, 2, 15, 5, 16, 2, 1, 12, 2, 1, 13, 2,
3, 1, 13, 2 16, 5, 3, 1, 14, 2
}; };
static const char _foo_key_offsets[] = { static const char _ansi_parser_key_offsets[] = {
0, 0, 1, 2, 10, 11, 13, 16, 0, 0, 1, 2, 10, 11, 13, 16,
19, 20, 23, 24, 25, 26, 28, 31, 19, 20, 24, 25, 26, 27, 28, 30,
33, 36, 38, 41, 42, 45, 46, 47, 33, 35, 38, 40, 43, 44, 47, 48,
48, 49, 50 49, 50, 51, 52
}; };
static const int _foo_trans_keys[] = { static const int _ansi_parser_trans_keys[] = {
27, 91, 49, 50, 51, 52, 55, 57, 27, 91, 49, 50, 51, 52, 55, 57,
48, 54, 109, 48, 109, 34, 48, 55, 48, 54, 109, 48, 109, 34, 48, 55,
50, 55, 109, 109, 56, 57, 109, 59, 50, 55, 109, 109, 49, 56, 57, 109,
50, 59, 48, 57, 59, 48, 57, 48, 109, 59, 50, 59, 48, 57, 59, 48,
57, 59, 48, 57, 48, 57, 109, 48, 57, 48, 57, 59, 48, 57, 48, 57,
57, 109, 56, 57, 109, 59, 50, 109, 109, 48, 57, 109, 56, 57, 109, 59,
109, 27, 27, 0 50, 109, 109, 27, 27, 0
}; };
static const char _foo_single_lengths[] = { static const char _ansi_parser_single_lengths[] = {
0, 1, 1, 6, 1, 2, 3, 3, 0, 1, 1, 6, 1, 2, 3, 3,
1, 3, 1, 1, 1, 0, 1, 0, 1, 4, 1, 1, 1, 1, 0, 1,
1, 0, 1, 1, 3, 1, 1, 1, 0, 1, 0, 1, 1, 3, 1, 1,
1, 1, 1 1, 1, 1, 1
}; };
static const char _foo_range_lengths[] = { static const char _ansi_parser_range_lengths[] = {
0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1,
1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0,
0, 0, 0 0, 0, 0, 0
}; };
static const char _foo_index_offsets[] = { static const char _ansi_parser_index_offsets[] = {
0, 0, 2, 4, 12, 14, 17, 21, 0, 0, 2, 4, 12, 14, 17, 21,
25, 27, 31, 33, 35, 37, 39, 42, 25, 27, 32, 34, 36, 38, 40, 42,
44, 47, 49, 52, 54, 58, 60, 62, 45, 47, 50, 52, 55, 57, 61, 63,
64, 66, 68 65, 67, 69, 71
}; };
static const char _foo_trans_targs[] = { static const char _ansi_parser_trans_targs[] = {
2, 1, 3, 0, 5, 7, 9, 20, 2, 1, 3, 0, 5, 7, 9, 21,
24, 6, 4, 0, 26, 0, 6, 26, 25, 6, 4, 0, 27, 0, 6, 27,
0, 4, 4, 4, 0, 4, 8, 26, 0, 4, 4, 4, 0, 4, 8, 27,
0, 26, 0, 10, 19, 26, 0, 11, 0, 27, 0, 10, 11, 20, 27, 0,
0, 12, 0, 13, 0, 14, 0, 15, 27, 0, 12, 0, 13, 0, 14, 0,
14, 0, 16, 0, 17, 16, 0, 18, 15, 0, 16, 15, 0, 17, 0, 18,
0, 26, 18, 0, 26, 0, 21, 23, 17, 0, 19, 0, 27, 19, 0, 27,
26, 0, 22, 0, 12, 0, 26, 0, 0, 22, 24, 27, 0, 23, 0, 13,
26, 0, 2, 1, 2, 1, 0 0, 27, 0, 27, 0, 2, 1, 2,
1, 0
}; };
static const char _foo_trans_actions[] = { static const char _ansi_parser_trans_actions[] = {
0, 7, 0, 0, 19, 19, 19, 19, 0, 7, 0, 0, 21, 21, 21, 21,
19, 19, 19, 0, 0, 0, 0, 0, 21, 21, 21, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 17,
0, 15, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, 0,
0, 3, 0, 0, 0, 1, 0, 23, 19, 0, 0, 0, 3, 0, 0, 0,
0, 0, 1, 0, 26, 0, 0, 1, 1, 0, 25, 0, 0, 1, 0, 28,
0, 32, 0, 0, 9, 0, 0, 0, 0, 0, 1, 0, 34, 0, 0, 9,
0, 0, 0, 0, 5, 0, 11, 0, 0, 0, 0, 0, 0, 0, 0, 5,
13, 0, 0, 7, 21, 29, 0 0, 11, 0, 13, 0, 0, 7, 23,
31, 0
}; };
static const char _foo_eof_actions[] = { static const char _ansi_parser_eof_actions[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 21 0, 0, 0, 23
}; };
static const int foo_start = 25; static const int ansi_parser_start = 26;
static const int foo_first_final = 25; static const int ansi_parser_first_final = 26;
static const int foo_error = 0; static const int ansi_parser_error = 0;
static const int foo_en_main = 25; static const int ansi_parser_en_main = 26;
#line 113 "ansi_parser.rl" #line 118 "ansi_parser.rl"
#include <ftxui/screen/terminal.hpp> #include <ftxui/screen/terminal.hpp>
@ -125,14 +127,14 @@ bool ANSIParser::parse(std::wstring_view codes, ColorCB color_cb, WriteCB write_
sf::Color &target = color; sf::Color &target = color;
#line 120 "ansi_parser.cpp" #line 122 "ansi_parser.cpp"
{ {
cs = foo_start; cs = ansi_parser_start;
} }
#line 138 "ansi_parser.rl" #line 143 "ansi_parser.rl"
#line 123 "ansi_parser.cpp" #line 125 "ansi_parser.cpp"
{ {
int _klen; int _klen;
unsigned int _trans; unsigned int _trans;
@ -145,10 +147,10 @@ bool ANSIParser::parse(std::wstring_view codes, ColorCB color_cb, WriteCB write_
if ( cs == 0 ) if ( cs == 0 )
goto _out; goto _out;
_resume: _resume:
_keys = _foo_trans_keys + _foo_key_offsets[cs]; _keys = _ansi_parser_trans_keys + _ansi_parser_key_offsets[cs];
_trans = _foo_index_offsets[cs]; _trans = _ansi_parser_index_offsets[cs];
_klen = _foo_single_lengths[cs]; _klen = _ansi_parser_single_lengths[cs];
if ( _klen > 0 ) { if ( _klen > 0 ) {
const int *_lower = _keys; const int *_lower = _keys;
const int *_mid; const int *_mid;
@ -171,7 +173,7 @@ _resume:
_trans += _klen; _trans += _klen;
} }
_klen = _foo_range_lengths[cs]; _klen = _ansi_parser_range_lengths[cs];
if ( _klen > 0 ) { if ( _klen > 0 ) {
const int *_lower = _keys; const int *_lower = _keys;
const int *_mid; const int *_mid;
@ -194,12 +196,12 @@ _resume:
} }
_match: _match:
cs = _foo_trans_targs[_trans]; cs = _ansi_parser_trans_targs[_trans];
if ( _foo_trans_actions[_trans] == 0 ) if ( _ansi_parser_trans_actions[_trans] == 0 )
goto _again; goto _again;
_acts = _foo_actions + _foo_trans_actions[_trans]; _acts = _ansi_parser_actions + _ansi_parser_trans_actions[_trans];
_nacts = (unsigned int) *_acts++; _nacts = (unsigned int) *_acts++;
while ( _nacts-- > 0 ) while ( _nacts-- > 0 )
{ {
@ -291,26 +293,33 @@ _match:
} }
break; break;
case 11: case 11:
#line 71 "ansi_parser.rl" #line 70 "ansi_parser.rl"
{ target.r = value; } {
color = sf::Color::Red;
color_cb(color, bgcolor);
}
break; break;
case 12: case 12:
#line 72 "ansi_parser.rl" #line 75 "ansi_parser.rl"
{ target.g = value; } { target.r = value; }
break; break;
case 13: case 13:
#line 73 "ansi_parser.rl" #line 76 "ansi_parser.rl"
{ target.b = value; } { target.g = value; }
break; break;
case 14: case 14:
#line 74 "ansi_parser.rl" #line 77 "ansi_parser.rl"
{ value = 0; } { target.b = value; }
break; break;
case 15: case 15:
#line 75 "ansi_parser.rl" #line 78 "ansi_parser.rl"
{ value = 0; }
break;
case 16:
#line 79 "ansi_parser.rl"
{} {}
break; break;
#line 284 "ansi_parser.cpp" #line 292 "ansi_parser.cpp"
} }
} }
@ -322,15 +331,15 @@ _again:
_test_eof: {} _test_eof: {}
if ( p == eof ) if ( p == eof )
{ {
const char *__acts = _foo_actions + _foo_eof_actions[cs]; const char *__acts = _ansi_parser_actions + _ansi_parser_eof_actions[cs];
unsigned int __nacts = (unsigned int) *__acts++; unsigned int __nacts = (unsigned int) *__acts++;
while ( __nacts-- > 0 ) { while ( __nacts-- > 0 ) {
switch ( *__acts++ ) { switch ( *__acts++ ) {
case 15: case 16:
#line 75 "ansi_parser.rl" #line 79 "ansi_parser.rl"
{} {}
break; break;
#line 302 "ansi_parser.cpp" #line 310 "ansi_parser.cpp"
} }
} }
} }
@ -338,16 +347,20 @@ _again:
_out: {} _out: {}
} }
#line 139 "ansi_parser.rl" #line 144 "ansi_parser.rl"
bool good = p - pe == 0; bool good = pe - p == 0;
if(!good) { if(!good) {
println("FAIL AT {}", p - pe); println("FAIL AT {}", pe - p);
p -= 10; p -= 10;
// dear cthuhlu, save me from the pain that is wstring // dear cthuhlu, save me from the pain that is wstring
for(int i = 0; i < 100; i++) { for(int i = 0; i < 100; i++) {
print("{}", char(p[i])); try {
print("{}", p[i] == 0x1B ? '^' : char(p[i]));
} catch(...) {
print("?=", int(p[i]));
}
} }
} }

@ -67,6 +67,10 @@ using namespace fmt;
color = sf::Color(100,100,100); color = sf::Color(100,100,100);
color_cb(color, bgcolor); color_cb(color, bgcolor);
} }
action red_text {
color = sf::Color::Red;
color_cb(color, bgcolor);
}
action red { target.r = value; } action red { target.r = value; }
action blue { target.g = value; } action blue { target.g = value; }
@ -96,6 +100,7 @@ using namespace fmt;
"5" | "5" |
"6" | "6" |
"7" %invert | "7" %invert |
"31" %red_text |
"22" | "22" |
"27" %reset_invert | "27" %reset_invert |
"9" ["0"-"7"] | "9" ["0"-"7"] |
@ -137,14 +142,18 @@ bool ANSIParser::parse(std::wstring_view codes, ColorCB color_cb, WriteCB write_
%% write init; %% write init;
%% write exec; %% write exec;
bool good = p - pe == 0; bool good = pe - p == 0;
if(!good) { if(!good) {
println("FAIL AT {}", p - pe); println("FAIL AT {}", pe - p);
p -= 10; p -= 10;
// dear cthuhlu, save me from the pain that is wstring // dear cthuhlu, save me from the pain that is wstring
for(int i = 0; i < 100; i++) { for(int i = 0; i < 100; i++) {
print("{}", char(p[i])); try {
print("{}", p[i] == 0x1B ? '^' : char(p[i]));
} catch(...) {
print("?=", int(p[i]));
}
} }
} }

@ -49,7 +49,7 @@ GUI::GUI(DinkyECS::World &world, Map& game_map) :
} }
void GUI::resize_map(int new_size) { void GUI::resize_map(int new_size) {
if($renderer.resize_map(new_size, $view_port)) { if($renderer.resize_grid(new_size, $view_port)) {
// set canvas to best size // set canvas to best size
$canvas = Canvas($view_port.x * 2, $view_port.y * 4); $canvas = Canvas($view_port.x * 2, $view_port.y * 4);
$map_view.resize($view_port.x, $view_port.y); $map_view.resize($view_port.x, $view_port.y);

@ -57,13 +57,21 @@ inline bool base_glyph_check(sf::Font &font, sf::Glyph &base_glyph, Point &view_
font_size = new_size; font_size = new_size;
return true; return true;
} else { } else {
println("VIEW TOO BIG, view={},{} MAP={},{}", view_x, view_y,
GAME_MAP_X, GAME_MAP_Y);
return false; return false;
} }
} }
bool SFMLRender::resize_map(int new_size, Point &view_port) { bool SFMLRender::resize_grid(int new_size, Point &view_port) {
if($map_font_size == new_size || new_size < MIN_FONT_SIZE || new_size > MAX_FONT_SIZE) return false; if($map_font_size == new_size || new_size < MIN_FONT_SIZE || new_size > MAX_FONT_SIZE) {
println("invalid map font size {}, =={}, min={}, max={}",
new_size, $map_font_size, MIN_FONT_SIZE, MAX_FONT_SIZE);
return false;
} else {
println("NEW SIZE SELECTED {}", new_size);
}
if(base_glyph_check($font, $base_glyph, view_port, $map_font_size, new_size)) { if(base_glyph_check($font, $base_glyph, view_port, $map_font_size, new_size)) {
$sprites.clear(); // need to reset the sprites for the new size $sprites.clear(); // need to reset the sprites for the new size
@ -72,6 +80,7 @@ bool SFMLRender::resize_map(int new_size, Point &view_port) {
$bg_bounds = $bg_sprite.getLocalBounds(); $bg_bounds = $bg_sprite.getLocalBounds();
return true; return true;
} else { } else {
println("BASE GLYPH FAILED!");
// something else here // something else here
return false; return false;
} }

@ -47,7 +47,7 @@ struct SFMLRender {
SFMLRender(SFMLRender &other) = delete; SFMLRender(SFMLRender &other) = delete;
sf::Sprite &get_text_sprite(wchar_t tile); sf::Sprite &get_text_sprite(wchar_t tile);
bool resize_map(int new_size, Point &view_port); bool resize_grid(int new_size, Point &view_port);
void render_grid(const std::wstring &text, float x, float y); void render_grid(const std::wstring &text, float x, float y);
void render_text(const std::wstring &text, sf::Color bgcolor, float x, float y); void render_text(const std::wstring &text, sf::Color bgcolor, float x, float y);

@ -1,3 +1,5 @@
#include <chrono> // for operator""s, chrono_literals
#include <thread> // for sleep_for
#include <fmt/core.h> #include <fmt/core.h>
#include <filesystem> #include <filesystem>
#include "panel.hpp" #include "panel.hpp"
@ -5,11 +7,67 @@
#include "render.hpp" #include "render.hpp"
#include "dbc.hpp" #include "dbc.hpp"
#include <SFML/Graphics/Image.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 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[]) { 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>"); dbc::check(argc == 2, "USAGE: img2ansi <image_file>");
string image_file(argv[1]); string image_file(argv[1]);
@ -20,14 +78,89 @@ int main(int argc, char *argv[]) {
sf::Image image; sf::Image image;
image.loadFromFile(image_file); image.loadFromFile(image_file);
// create a grid panel to hold the cells
Panel panel(40,40, 0, 0, true);
// divide the image into cells // 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);
}
// for each cell: return 0;
// get the color
// calculate value
// find character that's closest
// write to panel/canvas with ftxui
// display in sfml window with renderer
} }

Loading…
Cancel
Save