tuimg 0.1.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
tuimg-0.1.1/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Alexey Borsky
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
tuimg-0.1.1/PKG-INFO ADDED
@@ -0,0 +1,158 @@
1
+ Metadata-Version: 2.4
2
+ Name: tuimg
3
+ Version: 0.1.1
4
+ Summary: Render images in the terminal via a VQ-VAE codebook turned into a glyph font
5
+ Home-page: https://github.com/volotat/tuimg
6
+ Author: Alexey Borsky
7
+ License: MIT
8
+ Project-URL: Author, https://github.com/volotat
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Environment :: Console
12
+ Classifier: Topic :: Multimedia :: Graphics
13
+ Requires-Python: >=3.10
14
+ Description-Content-Type: text/markdown
15
+ License-File: LICENSE
16
+ Requires-Dist: numpy>=1.23
17
+ Requires-Dist: Pillow>=9.0
18
+ Provides-Extra: build
19
+ Requires-Dist: torch>=2.0; extra == "build"
20
+ Requires-Dist: scikit-learn>=1.1; extra == "build"
21
+ Requires-Dist: scipy>=1.7; extra == "build"
22
+ Requires-Dist: fonttools>=4.30; extra == "build"
23
+ Requires-Dist: huggingface_hub>=0.20; extra == "build"
24
+ Dynamic: license-file
25
+
26
+ # TUI-Image
27
+
28
+ Show an image **in your terminal as colored text**, using a pretrained image
29
+ tokenizer's codebook as a custom 4096-glyph font.
30
+
31
+ *Left: original. Right: rendered in the terminal (using TokImg Mono font).*
32
+
33
+ ![photo](previews/photo_compare.png)
34
+ ![ui](previews/ui_compare.png)
35
+ ![bear](previews/bear_compare.png)
36
+ ---
37
+
38
+ ## The idea
39
+
40
+ 1. A pretrained **VQ-VAE** (LlamaGen, MIT licensed) has 16384 little 16×16 image
41
+ patches. We keep the **4096 most shape-diverse** as a custom font (**TokImg Mono**).
42
+ 2. Each glyph is just a binary *shape*; its two colors come from the image — so a
43
+ shape and its color-swapped mirror are the same, and duplicates are dropped.
44
+ 3. To draw an image: split it into a grid of **terminal cells** — each cell is a
45
+ tall rectangle (~1:2) and for each cell pick the glyph whose
46
+ **shape** fits best, drawn (stretched to fill the cell) in that cell's **two
47
+ main colors**.
48
+ 4. The grid of colored glyphs approximates the image.
49
+
50
+ The VQ-VAE is used **only once, to build the font**. Rendering is pure NumPy on
51
+ CPU — `tuimg` never imports torch and needs no GPU/VRAM.
52
+
53
+ A handful of **Unicode block/box characters** (`█ ▀ ▌ ▖ ▒ ─ ╱` …) are mixed into
54
+ the alphabet too: the terminal draws those *procedurally*, so they render
55
+ **seam-free** and need no font. They win a cell whenever they fit about as well
56
+ as the best glyph, trading a seam away at ~no fidelity cost.
57
+
58
+ ---
59
+
60
+ ## Install
61
+
62
+ The font is **prebuilt and bundled**, so no GPU is needed to use it. Install it
63
+ as a `tuimg` command that's always on your PATH:
64
+
65
+ ```bash
66
+ git clone https://github.com/volotat/tuimg
67
+ cd tuimg
68
+ pip install . # or: pip install --user .
69
+ tuimg --install-font # copies the bundled font to ~/.fonts (+ refreshes cache)
70
+ tuimg path/to/image.jpg
71
+ ```
72
+
73
+ Or run from the cloned repo without installing:
74
+
75
+ ```bash
76
+ pip install numpy Pillow # only runtime deps
77
+ cp tuimg/assets/tokimg.ttf ~/.fonts/ && fc-cache -f # install the font
78
+ python -m tuimg samples/photo.jpg
79
+ ```
80
+
81
+ Rebuilding the font from the model is optional and the **only** step that needs a
82
+ GPU (~3 min): `pip install ".[build]"` then `make assets`.
83
+
84
+ > **Why you don't need to select the font:** our glyphs live in **plane-16 PUA**
85
+ > (U+100000+), a Unicode range no normal font defines. Your terminal can't find
86
+ > them in your current font, so it automatically *falls back* to TokImg just for
87
+ > those characters — your own font keeps drawing all your normal text. Installing
88
+ > the font is enough.
89
+ >
90
+ > *If the tiles don't appear* (a few terminals don't fall back for these
91
+ > codepoints): either set your terminal font to **"TokImg Mono"** (it includes
92
+ > normal ASCII, so your shell still looks normal — `fc-match "TokImg Mono"` should
93
+ > print `tokimg.ttf`), or skip the font entirely with `--mode block` / `--save *.png`.
94
+ > Tip: install to `~/.fonts`, which fontconfig scans even when `XDG_DATA_HOME` is
95
+ > redirected by a snap/flatpak sandbox.
96
+
97
+ ## Use
98
+
99
+ ```bash
100
+ python -m tuimg samples/photo.jpg # color (default)
101
+ python -m tuimg samples/photo.jpg --save pic.png # save the stitched picture
102
+ python -m tuimg samples/photo.jpg --no-color --save pic.txt # plain text, opens anywhere
103
+ python -m tuimg samples/ui.png --mode block # colored blocks, NO font needed
104
+ python -m tuimg --demo # render all sample images
105
+ ```
106
+
107
+ `--save FILE` saves the **perfectly-stitched picture** when FILE ends in
108
+ `.png`/`.jpg` (no font needed), otherwise the rendered text. `--no-color` drops
109
+ all ANSI color codes and renders a
110
+ **1-bit brightness halftone** of plain glyph characters — clean to open in any
111
+ editor (it suits a light/white background by default; add `--invert` for a dark
112
+ terminal, and `--mono-threshold T` to shift the brightness pivot — raise it for
113
+ more ink in a bright image, lower it for a dark one). `--blocks` matches using
114
+ **only** the Unicode block/box characters
115
+ (no codebook font) — a baseline to see how much the font actually adds. Other
116
+ flags: `--width N`, `--cell-aspect R` (if the image looks stretched;
117
+ auto-detected when possible), `--debug`. Run `python -m tuimg -h` for all.
118
+
119
+ ## Terminal rendering limitations (and why they can't be "fixed" here)
120
+
121
+ What you actually see in the terminal is **not** pixel-perfect, and this is a
122
+ limit of the medium, not a bug in this project:
123
+
124
+ ![how it really looks in the terminal](previews/flower_terminal.png)
125
+
126
+ A terminal lays out **discrete text glyphs**, one per cell — it was never built to
127
+ tile glyphs into a seamless image. Two consequences are unavoidable from inside
128
+ the application:
129
+
130
+ - **Hairline seams between cells.** A cell's size in device pixels is almost
131
+ always *fractional*, so the terminal snaps each cell to an integer pixel
132
+ boundary and rasterises every glyph independently. Edges that should meet
133
+ don't share pixels, leaving ~1-px seams. We mitigate this with glyph "ink
134
+ bleed" (overfilling right/bottom) and by preferring seam-free block characters,
135
+ but it can't be eliminated — the rounding happens in the terminal, below us.
136
+ - **No antialiasing control.** Whether glyph edges are soft or hard is the
137
+ terminal/font-renderer's decision.
138
+
139
+ Why can't we get the flawless alignment that box-drawing (`─ │ █ ▀`) has? Because
140
+ terminals special-case *those* ranges and draw them **procedurally**, filling the
141
+ exact cell rectangle and bypassing the font. Arbitrary custom shapes — the whole
142
+ premise of a glyph alphabet — go through normal font rasterisation, where the
143
+ snapping is inherent. You can have a rich shaped alphabet **or** box-drawing-grade
144
+ alignment, not both. For a pixel-perfect result, export the picture with
145
+ `--save out.png` (rasterised seam-free) or use `--mode block`.
146
+
147
+ Within those constraints, this project is about as good as terminal image
148
+ printing gets with a predefined character set: instead of a fixed handful of
149
+ ASCII/box glyphs, it builds a 4096-glyph alphabet straight from a learned image
150
+ tokenizer, selects it to match real-image statistics, mixes in the seam-free
151
+ block characters, and fits each cell's two colors to the block — squeezing the
152
+ most detail the two-colors-per-cell ceiling allows.
153
+
154
+ ## License
155
+
156
+ [MIT](LICENSE). The vendored model code (`tuimg/vendor/llamagen_vq.py`) and the
157
+ downloaded weights are from [LlamaGen](https://github.com/FoundationVision/LlamaGen),
158
+ also MIT.
tuimg-0.1.1/README.md ADDED
@@ -0,0 +1,133 @@
1
+ # TUI-Image
2
+
3
+ Show an image **in your terminal as colored text**, using a pretrained image
4
+ tokenizer's codebook as a custom 4096-glyph font.
5
+
6
+ *Left: original. Right: rendered in the terminal (using TokImg Mono font).*
7
+
8
+ ![photo](previews/photo_compare.png)
9
+ ![ui](previews/ui_compare.png)
10
+ ![bear](previews/bear_compare.png)
11
+ ---
12
+
13
+ ## The idea
14
+
15
+ 1. A pretrained **VQ-VAE** (LlamaGen, MIT licensed) has 16384 little 16×16 image
16
+ patches. We keep the **4096 most shape-diverse** as a custom font (**TokImg Mono**).
17
+ 2. Each glyph is just a binary *shape*; its two colors come from the image — so a
18
+ shape and its color-swapped mirror are the same, and duplicates are dropped.
19
+ 3. To draw an image: split it into a grid of **terminal cells** — each cell is a
20
+ tall rectangle (~1:2) and for each cell pick the glyph whose
21
+ **shape** fits best, drawn (stretched to fill the cell) in that cell's **two
22
+ main colors**.
23
+ 4. The grid of colored glyphs approximates the image.
24
+
25
+ The VQ-VAE is used **only once, to build the font**. Rendering is pure NumPy on
26
+ CPU — `tuimg` never imports torch and needs no GPU/VRAM.
27
+
28
+ A handful of **Unicode block/box characters** (`█ ▀ ▌ ▖ ▒ ─ ╱` …) are mixed into
29
+ the alphabet too: the terminal draws those *procedurally*, so they render
30
+ **seam-free** and need no font. They win a cell whenever they fit about as well
31
+ as the best glyph, trading a seam away at ~no fidelity cost.
32
+
33
+ ---
34
+
35
+ ## Install
36
+
37
+ The font is **prebuilt and bundled**, so no GPU is needed to use it. Install it
38
+ as a `tuimg` command that's always on your PATH:
39
+
40
+ ```bash
41
+ git clone https://github.com/volotat/tuimg
42
+ cd tuimg
43
+ pip install . # or: pip install --user .
44
+ tuimg --install-font # copies the bundled font to ~/.fonts (+ refreshes cache)
45
+ tuimg path/to/image.jpg
46
+ ```
47
+
48
+ Or run from the cloned repo without installing:
49
+
50
+ ```bash
51
+ pip install numpy Pillow # only runtime deps
52
+ cp tuimg/assets/tokimg.ttf ~/.fonts/ && fc-cache -f # install the font
53
+ python -m tuimg samples/photo.jpg
54
+ ```
55
+
56
+ Rebuilding the font from the model is optional and the **only** step that needs a
57
+ GPU (~3 min): `pip install ".[build]"` then `make assets`.
58
+
59
+ > **Why you don't need to select the font:** our glyphs live in **plane-16 PUA**
60
+ > (U+100000+), a Unicode range no normal font defines. Your terminal can't find
61
+ > them in your current font, so it automatically *falls back* to TokImg just for
62
+ > those characters — your own font keeps drawing all your normal text. Installing
63
+ > the font is enough.
64
+ >
65
+ > *If the tiles don't appear* (a few terminals don't fall back for these
66
+ > codepoints): either set your terminal font to **"TokImg Mono"** (it includes
67
+ > normal ASCII, so your shell still looks normal — `fc-match "TokImg Mono"` should
68
+ > print `tokimg.ttf`), or skip the font entirely with `--mode block` / `--save *.png`.
69
+ > Tip: install to `~/.fonts`, which fontconfig scans even when `XDG_DATA_HOME` is
70
+ > redirected by a snap/flatpak sandbox.
71
+
72
+ ## Use
73
+
74
+ ```bash
75
+ python -m tuimg samples/photo.jpg # color (default)
76
+ python -m tuimg samples/photo.jpg --save pic.png # save the stitched picture
77
+ python -m tuimg samples/photo.jpg --no-color --save pic.txt # plain text, opens anywhere
78
+ python -m tuimg samples/ui.png --mode block # colored blocks, NO font needed
79
+ python -m tuimg --demo # render all sample images
80
+ ```
81
+
82
+ `--save FILE` saves the **perfectly-stitched picture** when FILE ends in
83
+ `.png`/`.jpg` (no font needed), otherwise the rendered text. `--no-color` drops
84
+ all ANSI color codes and renders a
85
+ **1-bit brightness halftone** of plain glyph characters — clean to open in any
86
+ editor (it suits a light/white background by default; add `--invert` for a dark
87
+ terminal, and `--mono-threshold T` to shift the brightness pivot — raise it for
88
+ more ink in a bright image, lower it for a dark one). `--blocks` matches using
89
+ **only** the Unicode block/box characters
90
+ (no codebook font) — a baseline to see how much the font actually adds. Other
91
+ flags: `--width N`, `--cell-aspect R` (if the image looks stretched;
92
+ auto-detected when possible), `--debug`. Run `python -m tuimg -h` for all.
93
+
94
+ ## Terminal rendering limitations (and why they can't be "fixed" here)
95
+
96
+ What you actually see in the terminal is **not** pixel-perfect, and this is a
97
+ limit of the medium, not a bug in this project:
98
+
99
+ ![how it really looks in the terminal](previews/flower_terminal.png)
100
+
101
+ A terminal lays out **discrete text glyphs**, one per cell — it was never built to
102
+ tile glyphs into a seamless image. Two consequences are unavoidable from inside
103
+ the application:
104
+
105
+ - **Hairline seams between cells.** A cell's size in device pixels is almost
106
+ always *fractional*, so the terminal snaps each cell to an integer pixel
107
+ boundary and rasterises every glyph independently. Edges that should meet
108
+ don't share pixels, leaving ~1-px seams. We mitigate this with glyph "ink
109
+ bleed" (overfilling right/bottom) and by preferring seam-free block characters,
110
+ but it can't be eliminated — the rounding happens in the terminal, below us.
111
+ - **No antialiasing control.** Whether glyph edges are soft or hard is the
112
+ terminal/font-renderer's decision.
113
+
114
+ Why can't we get the flawless alignment that box-drawing (`─ │ █ ▀`) has? Because
115
+ terminals special-case *those* ranges and draw them **procedurally**, filling the
116
+ exact cell rectangle and bypassing the font. Arbitrary custom shapes — the whole
117
+ premise of a glyph alphabet — go through normal font rasterisation, where the
118
+ snapping is inherent. You can have a rich shaped alphabet **or** box-drawing-grade
119
+ alignment, not both. For a pixel-perfect result, export the picture with
120
+ `--save out.png` (rasterised seam-free) or use `--mode block`.
121
+
122
+ Within those constraints, this project is about as good as terminal image
123
+ printing gets with a predefined character set: instead of a fixed handful of
124
+ ASCII/box glyphs, it builds a 4096-glyph alphabet straight from a learned image
125
+ tokenizer, selects it to match real-image statistics, mixes in the seam-free
126
+ block characters, and fits each cell's two colors to the block — squeezing the
127
+ most detail the two-colors-per-cell ceiling allows.
128
+
129
+ ## License
130
+
131
+ [MIT](LICENSE). The vendored model code (`tuimg/vendor/llamagen_vq.py`) and the
132
+ downloaded weights are from [LlamaGen](https://github.com/FoundationVision/LlamaGen),
133
+ also MIT.
@@ -0,0 +1,6 @@
1
+ # Metadata lives in setup.cfg (read by every setuptools, old or new) so the
2
+ # package builds correctly even under older pip/setuptools that don't understand
3
+ # PEP 621 [project] tables -- avoiding the "UNKNOWN-0.0.0" build.
4
+ [build-system]
5
+ requires = ["setuptools>=40.8.0", "wheel"]
6
+ build-backend = "setuptools.build_meta"
tuimg-0.1.1/setup.cfg ADDED
@@ -0,0 +1,51 @@
1
+ [metadata]
2
+ name = tuimg
3
+ version = 0.1.1
4
+ description = Render images in the terminal via a VQ-VAE codebook turned into a glyph font
5
+ long_description = file: README.md
6
+ long_description_content_type = text/markdown
7
+ author = Alexey Borsky
8
+ license = MIT
9
+ license_files = LICENSE
10
+ url = https://github.com/volotat/tuimg
11
+ project_urls =
12
+ Author = https://github.com/volotat
13
+ classifiers =
14
+ License :: OSI Approved :: MIT License
15
+ Programming Language :: Python :: 3
16
+ Environment :: Console
17
+ Topic :: Multimedia :: Graphics
18
+
19
+ [options]
20
+ python_requires = >=3.10
21
+ packages = find:
22
+ include_package_data = True
23
+ install_requires =
24
+ numpy>=1.23
25
+ Pillow>=9.0
26
+
27
+ [options.packages.find]
28
+ include = tuimg*
29
+
30
+ [options.extras_require]
31
+ build =
32
+ torch>=2.0
33
+ scikit-learn>=1.1
34
+ scipy>=1.7
35
+ fonttools>=4.30
36
+ huggingface_hub>=0.20
37
+
38
+ [options.entry_points]
39
+ console_scripts =
40
+ tuimg = tuimg.cli:main
41
+
42
+ [options.package_data]
43
+ tuimg =
44
+ assets/tokimg.ttf
45
+ assets/mapping.json
46
+ assets/glyph_masks.npy
47
+
48
+ [egg_info]
49
+ tag_build =
50
+ tag_date = 0
51
+
File without changes
@@ -0,0 +1,4 @@
1
+ """Allow `python -m tuimg <image>` as a shortcut for the CLI."""
2
+ from .cli import main
3
+
4
+ raise SystemExit(main())
Binary file