juegos

Juegos de terminal de Pancho: Catan (TUI, GUI, web, servidor, PicoCalc), ajedrez, calculadora y minijuegos
git clone https://git.lu3dhn.xyz/juegos.git
Log | Files | Refs

ansi2png.py (2549B)


      1 #!/usr/bin/env python3
      2 """Convierte una captura de tmux (capture-pane -e -p) a PNG, para revisar la TUI.
      3 Uso: tmux capture-pane -e -p -t SES | python3 tools/ansi2png.py salida.png [cols rows]"""
      4 import re, sys
      5 from PIL import Image, ImageDraw, ImageFont
      6 
      7 def xterm(n):
      8     base = [(0,0,0),(205,0,0),(0,205,0),(205,205,0),(0,0,238),(205,0,205),(0,205,205),(229,229,229),
      9             (127,127,127),(255,0,0),(0,255,0),(255,255,0),(92,92,255),(255,0,255),(0,255,255),(255,255,255)]
     10     if n < 16: return base[n]
     11     if n < 232:
     12         n -= 16; lv = [0,95,135,175,215,255]
     13         return (lv[n//36], lv[(n//6)%6], lv[n%6])
     14     v = 8 + (n-232)*10; return (v,v,v)
     15 
     16 out = sys.argv[1]
     17 cols = int(sys.argv[2]) if len(sys.argv) > 2 else 160
     18 rows = int(sys.argv[3]) if len(sys.argv) > 3 else 50
     19 text = sys.stdin.read().split("\n")[:rows]
     20 font = ImageFont.truetype("/usr/share/fonts/TTF/DejaVuSansMono.ttf", 14)
     21 bold = ImageFont.truetype("/usr/share/fonts/TTF/DejaVuSansMono-Bold.ttf", 14)
     22 cw, ch = 8, 17
     23 DFG, DBG = (220,220,220), (18,18,24)
     24 img = Image.new("RGB", (cols*cw, rows*ch), DBG)
     25 d = ImageDraw.Draw(img)
     26 for y, line in enumerate(text):
     27     fg, bg, b, rev = DFG, DBG, False, False
     28     x = 0
     29     for tok in re.split(r"(\x1b\[[0-9;]*m)", line):
     30         if tok.startswith("\x1b["):
     31             ps = [int(p) if p else 0 for p in tok[2:-1].split(";")]
     32             i = 0
     33             while i < len(ps):
     34                 p = ps[i]
     35                 if p == 0: fg, bg, b, rev = DFG, DBG, False, False
     36                 elif p == 1: b = True
     37                 elif p == 7: rev = True
     38                 elif p == 22: b = False
     39                 elif p == 27: rev = False
     40                 elif p == 39: fg = DFG
     41                 elif p == 49: bg = DBG
     42                 elif p == 38 and i+2 < len(ps) and ps[i+1] == 5: fg = xterm(ps[i+2]); i += 2
     43                 elif p == 48 and i+2 < len(ps) and ps[i+1] == 5: bg = xterm(ps[i+2]); i += 2
     44                 elif 30 <= p <= 37: fg = xterm(p-30)
     45                 elif 40 <= p <= 47: bg = xterm(p-40)
     46                 elif 90 <= p <= 97: fg = xterm(p-90+8)
     47                 elif 100 <= p <= 107: bg = xterm(p-100+8)
     48                 i += 1
     49             continue
     50         for c in tok:
     51             f, g = (bg, fg) if rev else (fg, bg)
     52             d.rectangle([x*cw, y*ch, x*cw+cw-1, y*ch+ch-1], fill=g)
     53             if c == "▀":
     54                 d.rectangle([x*cw, y*ch, x*cw+cw-1, y*ch+ch//2-1], fill=f)
     55             elif c != " ":
     56                 d.text((x*cw, y*ch), c, font=bold if b else font, fill=f)
     57             x += 1
     58 img.save(out)