chromatic-python 0.9.0__tar.gz → 0.9.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.
- chromatic_python-0.9.1/.github/workflows/build.yml +33 -0
- {chromatic_python-0.9.0 → chromatic_python-0.9.1}/PKG-INFO +72 -71
- chromatic_python-0.9.1/README.md +153 -0
- {chromatic_python-0.9.0 → chromatic_python-0.9.1}/chromatic/__init__.pyi +3 -2
- {chromatic_python-0.9.0 → chromatic_python-0.9.1}/chromatic/_version.py +3 -3
- {chromatic_python-0.9.0 → chromatic_python-0.9.1}/chromatic/color/core.py +5 -10
- {chromatic_python-0.9.0 → chromatic_python-0.9.1}/chromatic/color/core.pyi +2 -2
- {chromatic_python-0.9.0 → chromatic_python-0.9.1}/chromatic/data/userfont.pyi +3 -11
- {chromatic_python-0.9.0 → chromatic_python-0.9.1}/chromatic_python.egg-info/PKG-INFO +72 -71
- {chromatic_python-0.9.0 → chromatic_python-0.9.1}/chromatic_python.egg-info/SOURCES.txt +5 -1
- {chromatic_python-0.9.0 → chromatic_python-0.9.1}/chromatic_python.egg-info/scm_file_list.json +5 -1
- chromatic_python-0.9.1/chromatic_python.egg-info/scm_version.json +8 -0
- chromatic_python-0.9.1/docs/index.md +153 -0
- {chromatic_python-0.9.0 → chromatic_python-0.9.1}/pyproject.toml +4 -0
- chromatic_python-0.9.1/tests/test_color_chain.py +244 -0
- chromatic_python-0.9.1/tests/test_colorconv.py +370 -0
- chromatic_python-0.9.1/tests/test_colorstr.py +241 -0
- chromatic_python-0.9.1/tests/test_image.py +143 -0
- chromatic_python-0.9.0/README.md +0 -152
- chromatic_python-0.9.0/chromatic_python.egg-info/scm_version.json +0 -8
- chromatic_python-0.9.0/docs/index.md +0 -152
- chromatic_python-0.9.0/tests/test_color_str.py +0 -338
- {chromatic_python-0.9.0 → chromatic_python-0.9.1}/.gitattributes +0 -0
- {chromatic_python-0.9.0 → chromatic_python-0.9.1}/.github/dependabot.yml +0 -0
- {chromatic_python-0.9.0 → chromatic_python-0.9.1}/.github/workflows/docs.yml +0 -0
- {chromatic_python-0.9.0 → chromatic_python-0.9.1}/.github/workflows/release.yml +0 -0
- {chromatic_python-0.9.0 → chromatic_python-0.9.1}/.gitignore +0 -0
- {chromatic_python-0.9.0 → chromatic_python-0.9.1}/LICENSE +0 -0
- {chromatic_python-0.9.0 → chromatic_python-0.9.1}/banner.png +0 -0
- {chromatic_python-0.9.0 → chromatic_python-0.9.1}/chromatic/__init__.py +0 -0
- {chromatic_python-0.9.0 → chromatic_python-0.9.1}/chromatic/__main__.py +0 -0
- {chromatic_python-0.9.0 → chromatic_python-0.9.1}/chromatic/_typing.py +0 -0
- {chromatic_python-0.9.0 → chromatic_python-0.9.1}/chromatic/color/__init__.py +0 -0
- {chromatic_python-0.9.0 → chromatic_python-0.9.1}/chromatic/color/__init__.pyi +0 -0
- {chromatic_python-0.9.0 → chromatic_python-0.9.1}/chromatic/color/colorconv.py +0 -0
- {chromatic_python-0.9.0 → chromatic_python-0.9.1}/chromatic/color/colorconv.pyi +0 -0
- {chromatic_python-0.9.0 → chromatic_python-0.9.1}/chromatic/color/palette.py +0 -0
- {chromatic_python-0.9.0 → chromatic_python-0.9.1}/chromatic/color/palette.pyi +0 -0
- {chromatic_python-0.9.0 → chromatic_python-0.9.1}/chromatic/data/__init__.py +0 -0
- {chromatic_python-0.9.0 → chromatic_python-0.9.1}/chromatic/data/fonts/userfont.schema.json +0 -0
- {chromatic_python-0.9.0 → chromatic_python-0.9.1}/chromatic/data/fonts/vga437.ttf +0 -0
- {chromatic_python-0.9.0 → chromatic_python-0.9.1}/chromatic/data/userfont.py +0 -0
- {chromatic_python-0.9.0 → chromatic_python-0.9.1}/chromatic/image/__init__.py +0 -0
- {chromatic_python-0.9.0 → chromatic_python-0.9.1}/chromatic/image/__init__.pyi +0 -0
- {chromatic_python-0.9.0 → chromatic_python-0.9.1}/chromatic/image/_array.py +0 -0
- {chromatic_python-0.9.0 → chromatic_python-0.9.1}/chromatic/image/_curses.py +0 -0
- {chromatic_python-0.9.0 → chromatic_python-0.9.1}/chromatic/image/_glyph.py +0 -0
- {chromatic_python-0.9.0 → chromatic_python-0.9.1}/chromatic_python.egg-info/dependency_links.txt +0 -0
- {chromatic_python-0.9.0 → chromatic_python-0.9.1}/chromatic_python.egg-info/entry_points.txt +0 -0
- {chromatic_python-0.9.0 → chromatic_python-0.9.1}/chromatic_python.egg-info/requires.txt +0 -0
- {chromatic_python-0.9.0 → chromatic_python-0.9.1}/chromatic_python.egg-info/top_level.txt +0 -0
- {chromatic_python-0.9.0 → chromatic_python-0.9.1}/docs/api/chromatic.md +0 -0
- {chromatic_python-0.9.0 → chromatic_python-0.9.1}/docs/api/color.md +0 -0
- {chromatic_python-0.9.0 → chromatic_python-0.9.1}/docs/api/data.md +0 -0
- {chromatic_python-0.9.0 → chromatic_python-0.9.1}/docs/api/image.md +0 -0
- {chromatic_python-0.9.0 → chromatic_python-0.9.1}/docs/cli/index.md +0 -0
- {chromatic_python-0.9.0 → chromatic_python-0.9.1}/mkdocs.yml +0 -0
- {chromatic_python-0.9.0 → chromatic_python-0.9.1}/mkdocs_hooks.py +0 -0
- {chromatic_python-0.9.0 → chromatic_python-0.9.1}/setup.cfg +0 -0
- {chromatic_python-0.9.0 → chromatic_python-0.9.1}/tests/__init__.py +0 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
name: build
|
|
2
|
+
|
|
3
|
+
on: [workflow_dispatch, push, pull_request]
|
|
4
|
+
|
|
5
|
+
jobs:
|
|
6
|
+
test:
|
|
7
|
+
runs-on: ubuntu-latest
|
|
8
|
+
strategy:
|
|
9
|
+
matrix:
|
|
10
|
+
python-version: ['3.12', '3.13', '3.14']
|
|
11
|
+
steps:
|
|
12
|
+
- uses: actions/checkout@v7
|
|
13
|
+
- uses: astral-sh/setup-uv@v7
|
|
14
|
+
with:
|
|
15
|
+
python-version: ${{ matrix.python-version }}
|
|
16
|
+
- name: Install OpenCV runtime libraries
|
|
17
|
+
run: sudo apt-get update && sudo apt-get install -y libgl1
|
|
18
|
+
- run: uv run --group tests pytest
|
|
19
|
+
|
|
20
|
+
bench:
|
|
21
|
+
runs-on: ubuntu-latest
|
|
22
|
+
permissions:
|
|
23
|
+
contents: read
|
|
24
|
+
id-token: write
|
|
25
|
+
steps:
|
|
26
|
+
- uses: actions/checkout@v7
|
|
27
|
+
- uses: astral-sh/setup-uv@v7
|
|
28
|
+
- name: Install OpenCV runtime libraries
|
|
29
|
+
run: sudo apt-get update && sudo apt-get install -y libgl1
|
|
30
|
+
- uses: CodSpeedHQ/action@v5
|
|
31
|
+
with:
|
|
32
|
+
mode: simulation
|
|
33
|
+
run: uv run --group tests pytest --codspeed
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: chromatic-python
|
|
3
|
-
Version: 0.9.
|
|
3
|
+
Version: 0.9.1
|
|
4
4
|
Summary: ANSI art image processing and colored terminal text
|
|
5
5
|
Author: crypt0lith
|
|
6
6
|
License-Expression: MIT
|
|
@@ -31,6 +31,7 @@ Dynamic: license-file
|
|
|
31
31
|

|
|
32
32
|
[](https://pepy.tech/projects/chromatic-python)
|
|
33
33
|
[](https://mypy-lang.org/)
|
|
34
|
+
[](https://app.codspeed.io/crypt0lith/chromatic?utm_source=badge)
|
|
34
35
|
|
|
35
36
|
Chromatic is a library for ANSI art image processing and colored terminal text.
|
|
36
37
|
|
|
@@ -45,127 +46,127 @@ It offers a collection of algorithms and types for a variety of use cases:
|
|
|
45
46
|
|
|
46
47
|
### Usage
|
|
47
48
|
|
|
48
|
-
#### `
|
|
49
|
+
#### `ColorStr`
|
|
50
|
+
|
|
51
|
+
```python
|
|
52
|
+
from chromatic import ColorStr
|
|
53
|
+
|
|
54
|
+
cs = ColorStr("hello world", fg=0xFF0000, ansi_type="8b")
|
|
55
|
+
|
|
56
|
+
assert cs.base_str == "hello world"
|
|
57
|
+
assert len(cs) == len("hello world")
|
|
58
|
+
|
|
59
|
+
head, tail = cs.split()
|
|
60
|
+
|
|
61
|
+
assert head.fg == tail.fg == cs.fg
|
|
62
|
+
assert all(c.fg == cs.fg for c in cs)
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
`ColorStr` is a `str` subclass that carries SGR state as metadata.
|
|
66
|
+
Its `str` methods delegate to the base string and return `ColorStr` instances that retain the SGR state.
|
|
67
|
+
|
|
68
|
+
```python
|
|
69
|
+
assert str(cs) == "\x1b[38;5;196mhello world\x1b[0m"
|
|
70
|
+
assert cs.ansi == b"\x1b[38;5;196m"
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
The SGR sequence materializes when the `ColorStr` is converted back to a Python `str`.
|
|
49
74
|
|
|
50
|
-
|
|
75
|
+
#### `color_chain`
|
|
51
76
|
|
|
52
77
|
```python
|
|
53
|
-
from chromatic import color_chain
|
|
78
|
+
from chromatic import color_chain
|
|
54
79
|
|
|
55
80
|
cc = color_chain(
|
|
56
81
|
[ColorStr("hello", fg=0xFF0000), ColorStr(" world", fg=0x00FF00)], ansi_type="8b"
|
|
57
82
|
)
|
|
58
83
|
|
|
59
|
-
|
|
84
|
+
sgr, s = cc[0]
|
|
85
|
+
|
|
86
|
+
assert sgr.fg == (0xFF, 0, 0)
|
|
87
|
+
assert s == "hello"
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
A `color_chain` is a sequence of colored-text fragments that round-trips with a structured NumPy array.
|
|
91
|
+
Each fragment is an `(sgr, text)` pair of the SGR state and the run of text it applies to.
|
|
92
|
+
|
|
93
|
+
```python
|
|
60
94
|
cc2 = color_chain("\x1b[38;5;196mhello\x1b[38;5;46m world")
|
|
61
95
|
|
|
62
96
|
assert cc == cc2
|
|
97
|
+
```
|
|
63
98
|
|
|
64
|
-
|
|
65
|
-
|
|
99
|
+
The constructor also parses a raw SGR string.
|
|
100
|
+
It infers the color depth from the sequence, so `cc2` needs no `ansi_type`.
|
|
66
101
|
|
|
67
|
-
|
|
102
|
+
```python
|
|
68
103
|
arr = cc.term_array()
|
|
69
104
|
|
|
105
|
+
assert arr.dtype == [("char", "<U1"), ("sgr", "<u8"), ("rgb", "u1", (2, 4))]
|
|
70
106
|
assert str(color_chain.fromarray(arr)) == str(cc)
|
|
71
107
|
```
|
|
72
108
|
|
|
73
|
-
|
|
109
|
+
`term_array` exposes the structured `ndarray` behind the chain, and `fromarray` reverses it.
|
|
110
|
+
`fromarray` accepts any `ndarray` of that dtype, so an array built by other means converts to a printable `color_chain`.
|
|
74
111
|
|
|
75
|
-
`img2ansi`
|
|
112
|
+
#### `img2ansi`
|
|
76
113
|
|
|
77
114
|
```python
|
|
78
115
|
from chromatic import img2ansi
|
|
79
|
-
from chromatic.data import userfonts
|
|
80
|
-
|
|
81
|
-
font = userfonts["vga437"]
|
|
82
|
-
|
|
83
|
-
# the image, as ANSI art
|
|
84
|
-
cc = img2ansi("input.png", font, factor=200)
|
|
85
|
-
print(cc)
|
|
86
116
|
|
|
87
|
-
|
|
88
|
-
arr = img2ansi("input.png", font, factor=200, outarray=True)
|
|
117
|
+
cc = img2ansi("input.png")
|
|
89
118
|
```
|
|
90
119
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
`ansi2img` renders a `color_chain` (or array) back to an image:
|
|
120
|
+
`img2ansi` reads an image and returns a `color_chain`.
|
|
94
121
|
|
|
95
122
|
```python
|
|
96
|
-
|
|
97
|
-
from chromatic.data import userfonts
|
|
98
|
-
|
|
99
|
-
font = userfonts["vga437"]
|
|
100
|
-
|
|
101
|
-
cc = img2ansi("input.png", font, factor=200)
|
|
123
|
+
arr = img2ansi("input.png", outarray=True)
|
|
102
124
|
|
|
103
|
-
|
|
104
|
-
img = ansi2img(cc, font, font_size=16)
|
|
105
|
-
img.show()
|
|
125
|
+
assert color_chain.fromarray(arr) == cc
|
|
106
126
|
```
|
|
107
127
|
|
|
108
|
-
|
|
128
|
+
`outarray=True` returns the underlying `ndarray` instead.
|
|
109
129
|
|
|
110
|
-
`
|
|
130
|
+
#### `ansi2img`
|
|
111
131
|
|
|
112
132
|
```python
|
|
113
|
-
from chromatic import
|
|
114
|
-
from chromatic.data import userfonts
|
|
133
|
+
from chromatic import ansi2img
|
|
115
134
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
img = ansify("input.png", font, font_size=16, factor=200)
|
|
135
|
+
img = ansi2img(cc)
|
|
119
136
|
img.show()
|
|
120
|
-
|
|
121
|
-
# the ndarray it rendered from
|
|
122
|
-
arr = img.info["ansi_array"]
|
|
123
137
|
```
|
|
124
138
|
|
|
125
|
-
|
|
139
|
+
`ansi2img` renders a `color_chain` back to an image.
|
|
140
|
+
It also accepts a dtype-matching array.
|
|
126
141
|
|
|
127
|
-
|
|
142
|
+
#### `ansify`
|
|
128
143
|
|
|
129
144
|
```python
|
|
130
|
-
import
|
|
131
|
-
import time
|
|
132
|
-
|
|
133
|
-
from chromatic import img2ansi
|
|
134
|
-
from chromatic.data import userfonts
|
|
135
|
-
|
|
136
|
-
font = userfonts["vga437"]
|
|
137
|
-
|
|
138
|
-
# list[color_chain], one per frame
|
|
139
|
-
frames = img2ansi("input.gif", font, factor=200)
|
|
145
|
+
from chromatic import ansify
|
|
140
146
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
sys.stdout.write(f"\x1b[H{cc}")
|
|
144
|
-
time.sleep(0.1)
|
|
147
|
+
img = ansify("input.png")
|
|
148
|
+
arr = img.info["ansi_array"]
|
|
145
149
|
```
|
|
146
150
|
|
|
147
|
-
`ansify`
|
|
148
|
-
|
|
149
|
-
#### `ColorStr`
|
|
151
|
+
`ansify` runs both directions in one call, returning the rendered image with the array it rendered from on `Image.info`.
|
|
150
152
|
|
|
151
|
-
|
|
153
|
+
#### Animated images
|
|
152
154
|
|
|
153
155
|
```python
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
cs = ColorStr("hello world", fg=0xFF0000, ansi_type="8b")
|
|
156
|
+
frames = img2ansi("input.gif")
|
|
157
157
|
|
|
158
|
-
assert isinstance(
|
|
158
|
+
assert isinstance(frames, list)
|
|
159
|
+
assert all(isinstance(f, color_chain) for f in frames)
|
|
160
|
+
```
|
|
159
161
|
|
|
160
|
-
|
|
161
|
-
assert cs.base_str == "hello world"
|
|
162
|
-
assert len(cs) == len("hello world")
|
|
162
|
+
An animated image renders to a `list[color_chain]`, one per frame.
|
|
163
163
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
assert cs.ansi == b"\x1b[38;5;196m"
|
|
164
|
+
```shell
|
|
165
|
+
chromatic image ansify input.gif --stdout
|
|
167
166
|
```
|
|
168
167
|
|
|
168
|
+
The [CLI](https://crypt0lith.github.io/chromatic/cli/image/#chromatic-image-ansify) renders and plays one straight to the terminal.
|
|
169
|
+
|
|
169
170
|
### Installation
|
|
170
171
|
|
|
171
172
|
Install the package using `pip`:
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+

|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/chromatic-python/)
|
|
4
|
+

|
|
5
|
+
[](https://pepy.tech/projects/chromatic-python)
|
|
6
|
+
[](https://mypy-lang.org/)
|
|
7
|
+
[](https://app.codspeed.io/crypt0lith/chromatic?utm_source=badge)
|
|
8
|
+
|
|
9
|
+
Chromatic is a library for ANSI art image processing and colored terminal text.
|
|
10
|
+
|
|
11
|
+
It offers a collection of algorithms and types for a variety of use cases:
|
|
12
|
+
|
|
13
|
+
- Image-to-ASCII / Image-to-ANSI conversions.
|
|
14
|
+
- ANSI art rendering, with support for user-defined fonts.
|
|
15
|
+
- A `ColorStr` type for low-level control over ANSI SGR strings.
|
|
16
|
+
- [colorama](https://github.com/tartley/colorama/)-style wrappers (`Fore`, `Back`, `Style`).
|
|
17
|
+
- Conversion between 16-color, 256-color, and true-color (RGB) ANSI colorspace via the `colorbytes` type.
|
|
18
|
+
- Et Cetera 😲
|
|
19
|
+
|
|
20
|
+
### Usage
|
|
21
|
+
|
|
22
|
+
#### `ColorStr`
|
|
23
|
+
|
|
24
|
+
```python
|
|
25
|
+
from chromatic import ColorStr
|
|
26
|
+
|
|
27
|
+
cs = ColorStr("hello world", fg=0xFF0000, ansi_type="8b")
|
|
28
|
+
|
|
29
|
+
assert cs.base_str == "hello world"
|
|
30
|
+
assert len(cs) == len("hello world")
|
|
31
|
+
|
|
32
|
+
head, tail = cs.split()
|
|
33
|
+
|
|
34
|
+
assert head.fg == tail.fg == cs.fg
|
|
35
|
+
assert all(c.fg == cs.fg for c in cs)
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
`ColorStr` is a `str` subclass that carries SGR state as metadata.
|
|
39
|
+
Its `str` methods delegate to the base string and return `ColorStr` instances that retain the SGR state.
|
|
40
|
+
|
|
41
|
+
```python
|
|
42
|
+
assert str(cs) == "\x1b[38;5;196mhello world\x1b[0m"
|
|
43
|
+
assert cs.ansi == b"\x1b[38;5;196m"
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
The SGR sequence materializes when the `ColorStr` is converted back to a Python `str`.
|
|
47
|
+
|
|
48
|
+
#### `color_chain`
|
|
49
|
+
|
|
50
|
+
```python
|
|
51
|
+
from chromatic import color_chain
|
|
52
|
+
|
|
53
|
+
cc = color_chain(
|
|
54
|
+
[ColorStr("hello", fg=0xFF0000), ColorStr(" world", fg=0x00FF00)], ansi_type="8b"
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
sgr, s = cc[0]
|
|
58
|
+
|
|
59
|
+
assert sgr.fg == (0xFF, 0, 0)
|
|
60
|
+
assert s == "hello"
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
A `color_chain` is a sequence of colored-text fragments that round-trips with a structured NumPy array.
|
|
64
|
+
Each fragment is an `(sgr, text)` pair of the SGR state and the run of text it applies to.
|
|
65
|
+
|
|
66
|
+
```python
|
|
67
|
+
cc2 = color_chain("\x1b[38;5;196mhello\x1b[38;5;46m world")
|
|
68
|
+
|
|
69
|
+
assert cc == cc2
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
The constructor also parses a raw SGR string.
|
|
73
|
+
It infers the color depth from the sequence, so `cc2` needs no `ansi_type`.
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
arr = cc.term_array()
|
|
77
|
+
|
|
78
|
+
assert arr.dtype == [("char", "<U1"), ("sgr", "<u8"), ("rgb", "u1", (2, 4))]
|
|
79
|
+
assert str(color_chain.fromarray(arr)) == str(cc)
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
`term_array` exposes the structured `ndarray` behind the chain, and `fromarray` reverses it.
|
|
83
|
+
`fromarray` accepts any `ndarray` of that dtype, so an array built by other means converts to a printable `color_chain`.
|
|
84
|
+
|
|
85
|
+
#### `img2ansi`
|
|
86
|
+
|
|
87
|
+
```python
|
|
88
|
+
from chromatic import img2ansi
|
|
89
|
+
|
|
90
|
+
cc = img2ansi("input.png")
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
`img2ansi` reads an image and returns a `color_chain`.
|
|
94
|
+
|
|
95
|
+
```python
|
|
96
|
+
arr = img2ansi("input.png", outarray=True)
|
|
97
|
+
|
|
98
|
+
assert color_chain.fromarray(arr) == cc
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
`outarray=True` returns the underlying `ndarray` instead.
|
|
102
|
+
|
|
103
|
+
#### `ansi2img`
|
|
104
|
+
|
|
105
|
+
```python
|
|
106
|
+
from chromatic import ansi2img
|
|
107
|
+
|
|
108
|
+
img = ansi2img(cc)
|
|
109
|
+
img.show()
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
`ansi2img` renders a `color_chain` back to an image.
|
|
113
|
+
It also accepts a dtype-matching array.
|
|
114
|
+
|
|
115
|
+
#### `ansify`
|
|
116
|
+
|
|
117
|
+
```python
|
|
118
|
+
from chromatic import ansify
|
|
119
|
+
|
|
120
|
+
img = ansify("input.png")
|
|
121
|
+
arr = img.info["ansi_array"]
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
`ansify` runs both directions in one call, returning the rendered image with the array it rendered from on `Image.info`.
|
|
125
|
+
|
|
126
|
+
#### Animated images
|
|
127
|
+
|
|
128
|
+
```python
|
|
129
|
+
frames = img2ansi("input.gif")
|
|
130
|
+
|
|
131
|
+
assert isinstance(frames, list)
|
|
132
|
+
assert all(isinstance(f, color_chain) for f in frames)
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
An animated image renders to a `list[color_chain]`, one per frame.
|
|
136
|
+
|
|
137
|
+
```shell
|
|
138
|
+
chromatic image ansify input.gif --stdout
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
The [CLI](https://crypt0lith.github.io/chromatic/cli/image/#chromatic-image-ansify) renders and plays one straight to the terminal.
|
|
142
|
+
|
|
143
|
+
### Installation
|
|
144
|
+
|
|
145
|
+
Install the package using `pip`:
|
|
146
|
+
|
|
147
|
+
```shell
|
|
148
|
+
pip install chromatic-python
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Credits
|
|
152
|
+
|
|
153
|
+
Banner artwork: [main rules by Crasher (2002)](https://16colo.rs/pack/galza-14/CRS-MAIN.ANS)
|
|
@@ -3,6 +3,7 @@ __all__ = [
|
|
|
3
3
|
"Color",
|
|
4
4
|
"ColorNamespace",
|
|
5
5
|
"ColorStr",
|
|
6
|
+
"DEFAULT_FONT",
|
|
6
7
|
"Fore",
|
|
7
8
|
"SgrFlag",
|
|
8
9
|
"SgrParameter",
|
|
@@ -38,10 +39,10 @@ __all__ = [
|
|
|
38
39
|
"reshape_ansi",
|
|
39
40
|
"rgb2hexstr",
|
|
40
41
|
"rgb2int",
|
|
42
|
+
"set_default_ansi",
|
|
41
43
|
"sort_glyphs",
|
|
42
44
|
"ttf_extract_codepoints",
|
|
43
45
|
"userfonts",
|
|
44
|
-
"set_default_ansi",
|
|
45
46
|
]
|
|
46
47
|
from . import color, data, image
|
|
47
48
|
from ._version import version as __version__
|
|
@@ -66,7 +67,7 @@ from .color import (
|
|
|
66
67
|
rgb2int,
|
|
67
68
|
set_default_ansi,
|
|
68
69
|
)
|
|
69
|
-
from .data import UserFont, register_userfont, userfonts
|
|
70
|
+
from .data import DEFAULT_FONT, UserFont, register_userfont, userfonts
|
|
70
71
|
from .image import (
|
|
71
72
|
ansi2img,
|
|
72
73
|
ansi_quantize,
|
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '0.9.
|
|
22
|
-
__version_tuple__ = version_tuple = (0, 9,
|
|
21
|
+
__version__ = version = '0.9.1'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 9, 1)
|
|
23
23
|
|
|
24
|
-
__commit_id__ = commit_id = '
|
|
24
|
+
__commit_id__ = commit_id = 'g281bef66b'
|
|
@@ -3,6 +3,7 @@ __all__ = [
|
|
|
3
3
|
"Color",
|
|
4
4
|
"ColorChainDType",
|
|
5
5
|
"ColorStr",
|
|
6
|
+
"DEFAULT_ANSI",
|
|
6
7
|
"SGR_RESET",
|
|
7
8
|
"SgrFlag",
|
|
8
9
|
"SgrParameter",
|
|
@@ -16,6 +17,7 @@ __all__ = [
|
|
|
16
17
|
"is_vt_enabled",
|
|
17
18
|
"randcolor",
|
|
18
19
|
"rgb2ansi_escape",
|
|
20
|
+
"set_default_ansi",
|
|
19
21
|
]
|
|
20
22
|
|
|
21
23
|
import collections.abc as abc
|
|
@@ -1349,17 +1351,10 @@ class ColorStr(str, _IntFloatMixin):
|
|
|
1349
1351
|
return self._weak_var_update(sgr=sgr)
|
|
1350
1352
|
|
|
1351
1353
|
def strip_style(self):
|
|
1352
|
-
|
|
1353
|
-
diff = False
|
|
1354
|
-
for x in self._sgr:
|
|
1355
|
-
if x.is_color():
|
|
1356
|
-
only_colors.append(x)
|
|
1357
|
-
elif not diff:
|
|
1358
|
-
diff = True
|
|
1359
|
-
if not diff:
|
|
1354
|
+
if all(x.is_color() for x in self._sgr):
|
|
1360
1355
|
return self
|
|
1361
|
-
sgr =
|
|
1362
|
-
sgr
|
|
1356
|
+
sgr = SgrSequence()
|
|
1357
|
+
sgr.set_colors(self._sgr.rgb_dict, self.ansi_type)
|
|
1363
1358
|
return self._weak_var_update(sgr=sgr)
|
|
1364
1359
|
|
|
1365
1360
|
def add_reset(self):
|
|
@@ -3,6 +3,7 @@ __all__ = [
|
|
|
3
3
|
"Color",
|
|
4
4
|
"ColorChainDType",
|
|
5
5
|
"ColorStr",
|
|
6
|
+
"DEFAULT_ANSI",
|
|
6
7
|
"SGR_RESET",
|
|
7
8
|
"SgrFlag",
|
|
8
9
|
"SgrParameter",
|
|
@@ -16,6 +17,7 @@ __all__ = [
|
|
|
16
17
|
"is_vt_enabled",
|
|
17
18
|
"randcolor",
|
|
18
19
|
"rgb2ansi_escape",
|
|
20
|
+
"set_default_ansi",
|
|
19
21
|
]
|
|
20
22
|
|
|
21
23
|
import collections.abc as abc
|
|
@@ -169,8 +171,6 @@ class SgrFlag(enum.IntFlag):
|
|
|
169
171
|
@property
|
|
170
172
|
def parameters(self) -> list[SgrParameter]: ...
|
|
171
173
|
|
|
172
|
-
_P2F: tp.Final[dict[int, int]]
|
|
173
|
-
_F2P: tp.Final[dict[int, int]]
|
|
174
174
|
_ANSI16C_I2KV: tp.Final[dict[int, tuple[ColorDictKeys, Int3Tuple]]]
|
|
175
175
|
_ANSI16C_KV2I: tp.Final[dict[tuple[ColorDictKeys, Int3Tuple], int]]
|
|
176
176
|
_ANSI256_B2KEY: tp.Final[dict[L[b"38", b"48"], ColorDictKeys]]
|
|
@@ -29,17 +29,9 @@ class UserFont:
|
|
|
29
29
|
def __fspath__(self) -> str: ...
|
|
30
30
|
def to_truetype(self) -> FreeTypeFont: ...
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
all_keys: frozenset[str]
|
|
36
|
-
annotations: MappingProxyType[str, type[tp.Any]]
|
|
37
|
-
|
|
38
|
-
@classmethod
|
|
39
|
-
def from_typeddict(cls, typ: type[tp.TypedDict], /) -> tp.Self: ...
|
|
40
|
-
def match(self, obj: dict, /) -> bool: ...
|
|
41
|
-
|
|
42
|
-
def _userfont_dict_struct() -> _TypedDictStruct: ...
|
|
32
|
+
def _userfont_dict_struct() -> (
|
|
33
|
+
tuple[frozenset[str], frozenset[str], frozenset[str], MappingProxyType[str, tp.Any]]
|
|
34
|
+
): ...
|
|
43
35
|
|
|
44
36
|
userfonts: tp.Final[MappingProxyType[str, UserFont]]
|
|
45
37
|
|