chromatic-python 0.8.1__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.
Files changed (70) hide show
  1. chromatic_python-0.9.1/.github/workflows/build.yml +33 -0
  2. chromatic_python-0.9.1/LICENSE +21 -0
  3. chromatic_python-0.9.1/PKG-INFO +180 -0
  4. chromatic_python-0.9.1/README.md +153 -0
  5. {chromatic_python-0.8.1 → chromatic_python-0.9.1}/chromatic/__init__.pyi +3 -2
  6. {chromatic_python-0.8.1 → chromatic_python-0.9.1}/chromatic/__main__.py +189 -71
  7. {chromatic_python-0.8.1 → chromatic_python-0.9.1}/chromatic/_typing.py +27 -11
  8. {chromatic_python-0.8.1 → chromatic_python-0.9.1}/chromatic/_version.py +3 -3
  9. {chromatic_python-0.8.1 → chromatic_python-0.9.1}/chromatic/color/colorconv.py +3 -3
  10. {chromatic_python-0.8.1 → chromatic_python-0.9.1}/chromatic/color/colorconv.pyi +3 -3
  11. {chromatic_python-0.8.1 → chromatic_python-0.9.1}/chromatic/color/core.py +16 -24
  12. {chromatic_python-0.8.1 → chromatic_python-0.9.1}/chromatic/color/core.pyi +12 -12
  13. {chromatic_python-0.8.1 → chromatic_python-0.9.1}/chromatic/color/palette.py +21 -26
  14. {chromatic_python-0.8.1 → chromatic_python-0.9.1}/chromatic/color/palette.pyi +2 -2
  15. chromatic_python-0.9.1/chromatic/data/__init__.py +14 -0
  16. {chromatic_python-0.8.1 → chromatic_python-0.9.1}/chromatic/data/userfont.py +40 -16
  17. {chromatic_python-0.8.1 → chromatic_python-0.9.1}/chromatic/data/userfont.pyi +3 -11
  18. {chromatic_python-0.8.1 → chromatic_python-0.9.1}/chromatic/image/_array.py +108 -109
  19. chromatic_python-0.9.1/chromatic_python.egg-info/PKG-INFO +180 -0
  20. {chromatic_python-0.8.1 → chromatic_python-0.9.1}/chromatic_python.egg-info/SOURCES.txt +8 -8
  21. {chromatic_python-0.8.1 → chromatic_python-0.9.1}/chromatic_python.egg-info/scm_file_list.json +8 -8
  22. chromatic_python-0.9.1/chromatic_python.egg-info/scm_version.json +8 -0
  23. chromatic_python-0.9.1/docs/cli/index.md +27 -0
  24. chromatic_python-0.9.1/docs/index.md +153 -0
  25. {chromatic_python-0.8.1 → chromatic_python-0.9.1}/mkdocs.yml +6 -0
  26. chromatic_python-0.9.1/mkdocs_hooks.py +40 -0
  27. {chromatic_python-0.8.1 → chromatic_python-0.9.1}/pyproject.toml +5 -1
  28. chromatic_python-0.9.1/tests/test_color_chain.py +244 -0
  29. chromatic_python-0.9.1/tests/test_colorconv.py +370 -0
  30. chromatic_python-0.9.1/tests/test_colorstr.py +241 -0
  31. chromatic_python-0.9.1/tests/test_image.py +143 -0
  32. chromatic_python-0.8.1/PKG-INFO +0 -159
  33. chromatic_python-0.8.1/README.md +0 -134
  34. chromatic_python-0.8.1/chromatic/data/__init__.py +0 -40
  35. chromatic_python-0.8.1/chromatic/data/__init__.pyi +0 -18
  36. chromatic_python-0.8.1/chromatic/data/_fetchers.py +0 -69
  37. chromatic_python-0.8.1/chromatic/data/images/butterfly.jpg +0 -0
  38. chromatic_python-0.8.1/chromatic/data/images/escher.png +0 -0
  39. chromatic_python-0.8.1/chromatic/data/images/goblin_virus.png +0 -0
  40. chromatic_python-0.8.1/chromatic/data/images/registry.json +0 -5
  41. chromatic_python-0.8.1/chromatic/demo.py +0 -327
  42. chromatic_python-0.8.1/chromatic_python.egg-info/PKG-INFO +0 -159
  43. chromatic_python-0.8.1/chromatic_python.egg-info/scm_version.json +0 -8
  44. chromatic_python-0.8.1/docs/index.md +0 -134
  45. chromatic_python-0.8.1/tests/test_color_str.py +0 -338
  46. {chromatic_python-0.8.1 → chromatic_python-0.9.1}/.gitattributes +0 -0
  47. {chromatic_python-0.8.1 → chromatic_python-0.9.1}/.github/dependabot.yml +0 -0
  48. {chromatic_python-0.8.1 → chromatic_python-0.9.1}/.github/workflows/docs.yml +0 -0
  49. {chromatic_python-0.8.1 → chromatic_python-0.9.1}/.github/workflows/release.yml +0 -0
  50. {chromatic_python-0.8.1 → chromatic_python-0.9.1}/.gitignore +0 -0
  51. {chromatic_python-0.8.1 → chromatic_python-0.9.1}/banner.png +0 -0
  52. {chromatic_python-0.8.1 → chromatic_python-0.9.1}/chromatic/__init__.py +0 -0
  53. {chromatic_python-0.8.1 → chromatic_python-0.9.1}/chromatic/color/__init__.py +0 -0
  54. {chromatic_python-0.8.1 → chromatic_python-0.9.1}/chromatic/color/__init__.pyi +0 -0
  55. {chromatic_python-0.8.1 → chromatic_python-0.9.1}/chromatic/data/fonts/userfont.schema.json +0 -0
  56. {chromatic_python-0.8.1 → chromatic_python-0.9.1}/chromatic/data/fonts/vga437.ttf +0 -0
  57. {chromatic_python-0.8.1 → chromatic_python-0.9.1}/chromatic/image/__init__.py +0 -0
  58. {chromatic_python-0.8.1 → chromatic_python-0.9.1}/chromatic/image/__init__.pyi +0 -0
  59. {chromatic_python-0.8.1 → chromatic_python-0.9.1}/chromatic/image/_curses.py +0 -0
  60. {chromatic_python-0.8.1 → chromatic_python-0.9.1}/chromatic/image/_glyph.py +0 -0
  61. {chromatic_python-0.8.1 → chromatic_python-0.9.1}/chromatic_python.egg-info/dependency_links.txt +0 -0
  62. {chromatic_python-0.8.1 → chromatic_python-0.9.1}/chromatic_python.egg-info/entry_points.txt +0 -0
  63. {chromatic_python-0.8.1 → chromatic_python-0.9.1}/chromatic_python.egg-info/requires.txt +0 -0
  64. {chromatic_python-0.8.1 → chromatic_python-0.9.1}/chromatic_python.egg-info/top_level.txt +0 -0
  65. {chromatic_python-0.8.1 → chromatic_python-0.9.1}/docs/api/chromatic.md +0 -0
  66. {chromatic_python-0.8.1 → chromatic_python-0.9.1}/docs/api/color.md +0 -0
  67. {chromatic_python-0.8.1 → chromatic_python-0.9.1}/docs/api/data.md +0 -0
  68. {chromatic_python-0.8.1 → chromatic_python-0.9.1}/docs/api/image.md +0 -0
  69. {chromatic_python-0.8.1 → chromatic_python-0.9.1}/setup.cfg +0 -0
  70. {chromatic_python-0.8.1 → 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
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 crypt0lith
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.
@@ -0,0 +1,180 @@
1
+ Metadata-Version: 2.4
2
+ Name: chromatic-python
3
+ Version: 0.9.1
4
+ Summary: ANSI art image processing and colored terminal text
5
+ Author: crypt0lith
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/crypt0lith/chromatic
8
+ Project-URL: Documentation, https://crypt0lith.github.io/chromatic
9
+ Keywords: ansi,ascii,art,font,image,terminal,parser
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.12
12
+ Classifier: Programming Language :: Python :: 3.13
13
+ Classifier: Programming Language :: Python :: 3.14
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
16
+ Classifier: Typing :: Typed
17
+ Requires-Python: <4.0,>=3.12
18
+ Description-Content-Type: text/markdown
19
+ License-File: LICENSE
20
+ Requires-Dist: numpy<2.8,>=2.1
21
+ Requires-Dist: pillow>=12.2.0
22
+ Requires-Dist: scipy>=1.11.4
23
+ Requires-Dist: opencv-python
24
+ Requires-Dist: fonttools>=4.60.2
25
+ Requires-Dist: lazy_loader
26
+ Dynamic: license-file
27
+
28
+ ![image](https://raw.githubusercontent.com/crypt0lith/chromatic/master/banner.png)
29
+
30
+ [![image](https://img.shields.io/pypi/v/chromatic-python)](https://pypi.org/project/chromatic-python/)
31
+ ![image](https://img.shields.io/pypi/pyversions/chromatic-python)
32
+ [![image](https://static.pepy.tech/badge/chromatic-python)](https://pepy.tech/projects/chromatic-python)
33
+ [![image](https://mypy-lang.org/static/mypy_badge.svg)](https://mypy-lang.org/)
34
+ [![CodSpeed](https://img.shields.io/endpoint?url=https://codspeed.io/badge.json)](https://app.codspeed.io/crypt0lith/chromatic?utm_source=badge)
35
+
36
+ Chromatic is a library for ANSI art image processing and colored terminal text.
37
+
38
+ It offers a collection of algorithms and types for a variety of use cases:
39
+
40
+ - Image-to-ASCII / Image-to-ANSI conversions.
41
+ - ANSI art rendering, with support for user-defined fonts.
42
+ - A `ColorStr` type for low-level control over ANSI SGR strings.
43
+ - [colorama](https://github.com/tartley/colorama/)-style wrappers (`Fore`, `Back`, `Style`).
44
+ - Conversion between 16-color, 256-color, and true-color (RGB) ANSI colorspace via the `colorbytes` type.
45
+ - Et Cetera 😲
46
+
47
+ ### Usage
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`.
74
+
75
+ #### `color_chain`
76
+
77
+ ```python
78
+ from chromatic import color_chain
79
+
80
+ cc = color_chain(
81
+ [ColorStr("hello", fg=0xFF0000), ColorStr(" world", fg=0x00FF00)], ansi_type="8b"
82
+ )
83
+
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
94
+ cc2 = color_chain("\x1b[38;5;196mhello\x1b[38;5;46m world")
95
+
96
+ assert cc == cc2
97
+ ```
98
+
99
+ The constructor also parses a raw SGR string.
100
+ It infers the color depth from the sequence, so `cc2` needs no `ansi_type`.
101
+
102
+ ```python
103
+ arr = cc.term_array()
104
+
105
+ assert arr.dtype == [("char", "<U1"), ("sgr", "<u8"), ("rgb", "u1", (2, 4))]
106
+ assert str(color_chain.fromarray(arr)) == str(cc)
107
+ ```
108
+
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`.
111
+
112
+ #### `img2ansi`
113
+
114
+ ```python
115
+ from chromatic import img2ansi
116
+
117
+ cc = img2ansi("input.png")
118
+ ```
119
+
120
+ `img2ansi` reads an image and returns a `color_chain`.
121
+
122
+ ```python
123
+ arr = img2ansi("input.png", outarray=True)
124
+
125
+ assert color_chain.fromarray(arr) == cc
126
+ ```
127
+
128
+ `outarray=True` returns the underlying `ndarray` instead.
129
+
130
+ #### `ansi2img`
131
+
132
+ ```python
133
+ from chromatic import ansi2img
134
+
135
+ img = ansi2img(cc)
136
+ img.show()
137
+ ```
138
+
139
+ `ansi2img` renders a `color_chain` back to an image.
140
+ It also accepts a dtype-matching array.
141
+
142
+ #### `ansify`
143
+
144
+ ```python
145
+ from chromatic import ansify
146
+
147
+ img = ansify("input.png")
148
+ arr = img.info["ansi_array"]
149
+ ```
150
+
151
+ `ansify` runs both directions in one call, returning the rendered image with the array it rendered from on `Image.info`.
152
+
153
+ #### Animated images
154
+
155
+ ```python
156
+ frames = img2ansi("input.gif")
157
+
158
+ assert isinstance(frames, list)
159
+ assert all(isinstance(f, color_chain) for f in frames)
160
+ ```
161
+
162
+ An animated image renders to a `list[color_chain]`, one per frame.
163
+
164
+ ```shell
165
+ chromatic image ansify input.gif --stdout
166
+ ```
167
+
168
+ The [CLI](https://crypt0lith.github.io/chromatic/cli/image/#chromatic-image-ansify) renders and plays one straight to the terminal.
169
+
170
+ ### Installation
171
+
172
+ Install the package using `pip`:
173
+
174
+ ```shell
175
+ pip install chromatic-python
176
+ ```
177
+
178
+ ### Credits
179
+
180
+ Banner artwork: [main rules by Crasher (2002)](https://16colo.rs/pack/galza-14/CRS-MAIN.ANS)
@@ -0,0 +1,153 @@
1
+ ![image](https://raw.githubusercontent.com/crypt0lith/chromatic/master/banner.png)
2
+
3
+ [![image](https://img.shields.io/pypi/v/chromatic-python)](https://pypi.org/project/chromatic-python/)
4
+ ![image](https://img.shields.io/pypi/pyversions/chromatic-python)
5
+ [![image](https://static.pepy.tech/badge/chromatic-python)](https://pepy.tech/projects/chromatic-python)
6
+ [![image](https://mypy-lang.org/static/mypy_badge.svg)](https://mypy-lang.org/)
7
+ [![CodSpeed](https://img.shields.io/endpoint?url=https://codspeed.io/badge.json)](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,