Chinese Dragon TUI
August 10, 2026 · View on GitHub
A self-contained, true-color terminal artwork: a complete Chinese dragon rendered from square-pixel RLE data.

Run
Requirements: Node.js 18+ and a terminal with 24-bit color support.
git clone https://github.com/x0c/chinese-dragon-tui.git
cd chinese-dragon-tui
./dragon-tui
The app enters the alternate terminal screen, scales the artwork to the current terminal while keeping the whole dragon visible, and compensates for terminal character geometry with a 1.25× horizontal correction. Press q or Esc to exit.
Useful commands:
./dragon-tui --status
./dragon-tui --json
./dragon-tui --render
Data format
dragon-grid.json uses `tui-square-grid-rle/v1$:
- 256 \times 170 \text{logical} \text{square} \text{cells}
- 64-\text{color} \text{true}-\text{color} \text{palette}
- \text{row}-\text{based} \text{run}-\text{length} \text{encoding}, \text{where} \text{each} \text{run} \text{is} $[paletteIndex, length]`
- background palette index:
0(#FFFFFF)
The renderer packs two adjacent logical rows into one ▀ character, using the foreground color for the upper cell and background color for the lower cell. This makes the full source render in 256 terminal columns × 85 rows before responsive scaling.
From pixel art to terminal grid data
The project includes both the input artwork (source-dragon.png) and the converter (make_tui_dragon_grid.py), so the data is reproducible instead of being a hand-written approximation.
python3 -m pip install Pillow
python3 make_tui_dragon_grid.py source-dragon.png \
--output dragon-grid.json \
--preview dragon-grid-preview.png
The converter performs these steps:
- Nearest-neighbor sampling — it downsamples the 1536 × 1024 pixel artwork to a 256 × 170 logical grid. Nearest-neighbor sampling is intentional: averaging would blur the hard edges of pixel art.
- Separate the white backdrop — any nearly white cell (
R,G, andBall at least244) becomes palette index0, fixed as#FFFFFF. This prevents the empty background from consuming palette slots. - Preserve the dragon palette — all foreground cells are median-cut quantized into 63 colors, then combined with the white background to form a 64-color true-color palette. Keeping the palette budget for the foreground retains the small color transitions in the head, scales, and claws.
- Encode every row with RLE — adjacent cells using the same palette index become
[index, count]runs. The JSON therefore remains compact while decoding back to exactly 256 cells per row. - Render square logical cells in a terminal —
dragon-tui.mjsdecodes the RLE and combines two neighboring logical rows into the Unicode▀character. Its foreground color draws the upper cell and its background color draws the lower cell. A 1.25× horizontal correction compensates for how terminal glyphs look on screen.
The generated dragon-grid-preview.png is a nearest-neighbor enlargement decoded from the JSON itself. It is the visual check that the generated data, rather than the source image alone, still contains the complete dragon.