ideamaxfx 0.1.0__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.
- ideamaxfx-0.1.0/LICENSE +21 -0
- ideamaxfx-0.1.0/PKG-INFO +362 -0
- ideamaxfx-0.1.0/README.md +320 -0
- ideamaxfx-0.1.0/pyproject.toml +61 -0
- ideamaxfx-0.1.0/setup.cfg +4 -0
- ideamaxfx-0.1.0/src/ideamaxfx/__init__.py +27 -0
- ideamaxfx-0.1.0/src/ideamaxfx/animate/__init__.py +64 -0
- ideamaxfx-0.1.0/src/ideamaxfx/animate/bar.py +146 -0
- ideamaxfx-0.1.0/src/ideamaxfx/animate/composer.py +85 -0
- ideamaxfx-0.1.0/src/ideamaxfx/animate/core.py +60 -0
- ideamaxfx-0.1.0/src/ideamaxfx/animate/counter.py +84 -0
- ideamaxfx-0.1.0/src/ideamaxfx/animate/easing.py +151 -0
- ideamaxfx-0.1.0/src/ideamaxfx/animate/export.py +126 -0
- ideamaxfx-0.1.0/src/ideamaxfx/animate/heatmap.py +137 -0
- ideamaxfx-0.1.0/src/ideamaxfx/animate/line.py +136 -0
- ideamaxfx-0.1.0/src/ideamaxfx/animate/morph.py +44 -0
- ideamaxfx-0.1.0/src/ideamaxfx/animate/network.py +95 -0
- ideamaxfx-0.1.0/src/ideamaxfx/animate/pie.py +131 -0
- ideamaxfx-0.1.0/src/ideamaxfx/animate/radar.py +116 -0
- ideamaxfx-0.1.0/src/ideamaxfx/animate/scatter.py +106 -0
- ideamaxfx-0.1.0/src/ideamaxfx/animate/stagger.py +41 -0
- ideamaxfx-0.1.0/src/ideamaxfx/color/__init__.py +30 -0
- ideamaxfx-0.1.0/src/ideamaxfx/color/accessibility.py +97 -0
- ideamaxfx-0.1.0/src/ideamaxfx/color/adjust.py +81 -0
- ideamaxfx-0.1.0/src/ideamaxfx/color/convert.py +132 -0
- ideamaxfx-0.1.0/src/ideamaxfx/color/harmonies.py +110 -0
- ideamaxfx-0.1.0/src/ideamaxfx/color/interpolate.py +59 -0
- ideamaxfx-0.1.0/src/ideamaxfx/color/palette.py +121 -0
- ideamaxfx-0.1.0/src/ideamaxfx/compose/__init__.py +19 -0
- ideamaxfx-0.1.0/src/ideamaxfx/compose/overlay.py +65 -0
- ideamaxfx-0.1.0/src/ideamaxfx/compose/pixelate.py +74 -0
- ideamaxfx-0.1.0/src/ideamaxfx/compose/reflection.py +62 -0
- ideamaxfx-0.1.0/src/ideamaxfx/compose/rounded.py +41 -0
- ideamaxfx-0.1.0/src/ideamaxfx/compose/shadow.py +65 -0
- ideamaxfx-0.1.0/src/ideamaxfx/compose/tilt_shift.py +71 -0
- ideamaxfx-0.1.0/src/ideamaxfx/effects/__init__.py +34 -0
- ideamaxfx-0.1.0/src/ideamaxfx/effects/blend.py +70 -0
- ideamaxfx-0.1.0/src/ideamaxfx/effects/bloom.py +53 -0
- ideamaxfx-0.1.0/src/ideamaxfx/effects/chromatic.py +71 -0
- ideamaxfx-0.1.0/src/ideamaxfx/effects/duotone.py +40 -0
- ideamaxfx-0.1.0/src/ideamaxfx/effects/glass.py +84 -0
- ideamaxfx-0.1.0/src/ideamaxfx/effects/glow.py +96 -0
- ideamaxfx-0.1.0/src/ideamaxfx/effects/grain.py +45 -0
- ideamaxfx-0.1.0/src/ideamaxfx/effects/halftone.py +65 -0
- ideamaxfx-0.1.0/src/ideamaxfx/effects/noise.py +70 -0
- ideamaxfx-0.1.0/src/ideamaxfx/effects/patterns.py +132 -0
- ideamaxfx-0.1.0/src/ideamaxfx/effects/pipeline.py +251 -0
- ideamaxfx-0.1.0/src/ideamaxfx/effects/scanlines.py +48 -0
- ideamaxfx-0.1.0/src/ideamaxfx/effects/vignette.py +49 -0
- ideamaxfx-0.1.0/src/ideamaxfx/layout/__init__.py +10 -0
- ideamaxfx-0.1.0/src/ideamaxfx/layout/badge.py +54 -0
- ideamaxfx-0.1.0/src/ideamaxfx/layout/callout.py +89 -0
- ideamaxfx-0.1.0/src/ideamaxfx/layout/divider.py +63 -0
- ideamaxfx-0.1.0/src/ideamaxfx/layout/legend.py +74 -0
- ideamaxfx-0.1.0/src/ideamaxfx/layout/progress_bar.py +87 -0
- ideamaxfx-0.1.0/src/ideamaxfx/layout/stat_card.py +63 -0
- ideamaxfx-0.1.0/src/ideamaxfx/py.typed +0 -0
- ideamaxfx-0.1.0/src/ideamaxfx/text/__init__.py +11 -0
- ideamaxfx-0.1.0/src/ideamaxfx/text/emboss.py +102 -0
- ideamaxfx-0.1.0/src/ideamaxfx/text/gradient.py +74 -0
- ideamaxfx-0.1.0/src/ideamaxfx/text/neon.py +62 -0
- ideamaxfx-0.1.0/src/ideamaxfx/text/outline.py +58 -0
- ideamaxfx-0.1.0/src/ideamaxfx/text/shadow.py +64 -0
- ideamaxfx-0.1.0/src/ideamaxfx/texture/__init__.py +10 -0
- ideamaxfx-0.1.0/src/ideamaxfx/texture/dots.py +46 -0
- ideamaxfx-0.1.0/src/ideamaxfx/texture/grid.py +157 -0
- ideamaxfx-0.1.0/src/ideamaxfx/texture/perlin.py +182 -0
- ideamaxfx-0.1.0/src/ideamaxfx/texture/stripes.py +138 -0
- ideamaxfx-0.1.0/src/ideamaxfx/utils/__init__.py +6 -0
- ideamaxfx-0.1.0/src/ideamaxfx/utils/convert.py +64 -0
- ideamaxfx-0.1.0/src/ideamaxfx/utils/fonts.py +66 -0
- ideamaxfx-0.1.0/src/ideamaxfx/watermark/__init__.py +7 -0
- ideamaxfx-0.1.0/src/ideamaxfx/watermark/footer.py +72 -0
- ideamaxfx-0.1.0/src/ideamaxfx/watermark/image_mark.py +59 -0
- ideamaxfx-0.1.0/src/ideamaxfx/watermark/text_mark.py +58 -0
- ideamaxfx-0.1.0/src/ideamaxfx.egg-info/PKG-INFO +362 -0
- ideamaxfx-0.1.0/src/ideamaxfx.egg-info/SOURCES.txt +88 -0
- ideamaxfx-0.1.0/src/ideamaxfx.egg-info/dependency_links.txt +1 -0
- ideamaxfx-0.1.0/src/ideamaxfx.egg-info/requires.txt +16 -0
- ideamaxfx-0.1.0/src/ideamaxfx.egg-info/top_level.txt +1 -0
- ideamaxfx-0.1.0/tests/test_animate.py +247 -0
- ideamaxfx-0.1.0/tests/test_color.py +119 -0
- ideamaxfx-0.1.0/tests/test_compose.py +283 -0
- ideamaxfx-0.1.0/tests/test_edge_cases.py +838 -0
- ideamaxfx-0.1.0/tests/test_effects.py +145 -0
- ideamaxfx-0.1.0/tests/test_layout.py +262 -0
- ideamaxfx-0.1.0/tests/test_text.py +87 -0
- ideamaxfx-0.1.0/tests/test_texture.py +220 -0
- ideamaxfx-0.1.0/tests/test_utils.py +141 -0
- ideamaxfx-0.1.0/tests/test_watermark.py +185 -0
ideamaxfx-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 IDEAMAX
|
|
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.
|
ideamaxfx-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ideamaxfx
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Post-production effects, animated build-up, and visual toolkit for data visualizations
|
|
5
|
+
Author-email: IDEAMAX <info@ideamax.eu>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/devideamax/ideamaxfx
|
|
8
|
+
Project-URL: Documentation, https://ideamaxfx.readthedocs.io
|
|
9
|
+
Project-URL: Repository, https://github.com/devideamax/ideamaxfx
|
|
10
|
+
Project-URL: Changelog, https://github.com/devideamax/ideamaxfx/blob/main/CHANGELOG.md
|
|
11
|
+
Keywords: visualization,data-viz,effects,animation,charts,post-production,pillow
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Intended Audience :: Science/Research
|
|
15
|
+
Classifier: Topic :: Scientific/Engineering :: Visualization
|
|
16
|
+
Classifier: Topic :: Multimedia :: Graphics
|
|
17
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
24
|
+
Classifier: Typing :: Typed
|
|
25
|
+
Requires-Python: >=3.9
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
License-File: LICENSE
|
|
28
|
+
Requires-Dist: Pillow>=10.0
|
|
29
|
+
Requires-Dist: numpy>=1.24
|
|
30
|
+
Requires-Dist: imageio>=2.31
|
|
31
|
+
Provides-Extra: matplotlib
|
|
32
|
+
Requires-Dist: matplotlib>=3.7; extra == "matplotlib"
|
|
33
|
+
Provides-Extra: full
|
|
34
|
+
Requires-Dist: matplotlib>=3.7; extra == "full"
|
|
35
|
+
Requires-Dist: scipy>=1.10; extra == "full"
|
|
36
|
+
Provides-Extra: dev
|
|
37
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
38
|
+
Requires-Dist: pytest-cov; extra == "dev"
|
|
39
|
+
Requires-Dist: ruff; extra == "dev"
|
|
40
|
+
Requires-Dist: mypy; extra == "dev"
|
|
41
|
+
Dynamic: license-file
|
|
42
|
+
|
|
43
|
+
# ideamaxfx
|
|
44
|
+
|
|
45
|
+
**Post-production effects, animated chart build-up, and visual toolkit for Python.**
|
|
46
|
+
|
|
47
|
+
[](https://www.python.org/downloads/)
|
|
48
|
+
[](LICENSE)
|
|
49
|
+
[]()
|
|
50
|
+
[]()
|
|
51
|
+
[](https://github.com/astral-sh/ruff)
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## What It Does
|
|
56
|
+
|
|
57
|
+
- **Post-Production Effects Pipeline** -- Chainable API for cinematic finishing: grain, glow, scanlines, vignette, chromatic aberration, bloom, halftone, duotone, glass card, pattern overlays, and blend modes. Every method returns `self` so you can build complex multi-effect stacks in a single expression.
|
|
58
|
+
|
|
59
|
+
- **Animated Chart Build-Up** -- Generate GIF/APNG sequences where chart elements appear progressively with easing: bar, line, radar, scatter, pie, counter, heatmap, network, and morph transitions. Ships with 15 built-in easing functions and automatic GIF size optimization via gifsicle.
|
|
60
|
+
|
|
61
|
+
- **Visual Toolkit** -- Text effects (neon, gradient, outline, shadow, emboss), layout components (stat cards, progress bars, badges), color utilities, image composition, texture generators, and watermark tools. Pure Pillow core with optional matplotlib/scipy for advanced use cases.
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Installation
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
pip install ideamaxfx
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Include optional dependencies for chart rendering and advanced interpolation:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
pip install ideamaxfx[full] # includes matplotlib + scipy
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## Quick Start
|
|
80
|
+
|
|
81
|
+
### Effects Pipeline
|
|
82
|
+
|
|
83
|
+
```python
|
|
84
|
+
from ideamaxfx import EffectsPipeline
|
|
85
|
+
from PIL import Image
|
|
86
|
+
|
|
87
|
+
img = Image.open("chart.png")
|
|
88
|
+
result = (EffectsPipeline(img)
|
|
89
|
+
.grain(0.06)
|
|
90
|
+
.glow(color=(0, 245, 212))
|
|
91
|
+
.scanlines(spacing=4)
|
|
92
|
+
.vignette(0.3)
|
|
93
|
+
.export("finished.png"))
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Animated Bar Chart
|
|
97
|
+
|
|
98
|
+
```python
|
|
99
|
+
from ideamaxfx.animate import bar_grow, export_gif
|
|
100
|
+
|
|
101
|
+
frames = bar_grow(
|
|
102
|
+
labels=['Goals', 'Assists', 'Saves'],
|
|
103
|
+
values=[68, 72, 45],
|
|
104
|
+
colors=['#d4213d', '#006633', '#0056a0'],
|
|
105
|
+
easing='ease_out_elastic'
|
|
106
|
+
)
|
|
107
|
+
export_gif(frames, 'animated.gif', max_kb=500)
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Text Effects
|
|
111
|
+
|
|
112
|
+
```python
|
|
113
|
+
from ideamaxfx.text import neon_text, gradient_text
|
|
114
|
+
from ideamaxfx.utils import load_font
|
|
115
|
+
|
|
116
|
+
font = load_font(size=48)
|
|
117
|
+
img = neon_text(canvas, 20, 20, "ELITE", font=font, color=(0, 245, 212))
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## Modules
|
|
123
|
+
|
|
124
|
+
| Module | Description | Key Functions |
|
|
125
|
+
|--------|-------------|---------------|
|
|
126
|
+
| `effects` | Post-production effects | `grain`, `glow`, `glow_border`, `halftone`, `scanlines`, `glass_card`, `duotone`, `vignette`, `chromatic_aberration`, `bloom`, `blue_noise`, `pattern_overlay`, `blend`, `EffectsPipeline` |
|
|
127
|
+
| `animate` | Animated build-up | `bar_grow`, `line_draw`, `radar_sweep`, `scatter_fade`, `counter_roll`, `pie_fill`, `heatmap_reveal`, `network_build`, `morph`, `stagger_delays`, `compose_animations`, `export_gif`, `export_apng` |
|
|
128
|
+
| `text` | Text effects | `gradient_text`, `neon_text`, `outline_text`, `shadow_text`, `emboss_text` |
|
|
129
|
+
| `color` | Color utilities | `hex_to_rgb`, `rgb_to_hex`, `rgb_to_hsl`, `hsl_to_rgb`, `interpolate_colors`, `complementary`, `triadic`, `analogous`, `extract_palette`, `contrast_ratio`, `wcag_check` |
|
|
130
|
+
| `layout` | UI components | `stat_card`, `progress_bar`, `badge`, `legend_block`, `divider`, `callout` |
|
|
131
|
+
| `compose` | Image composition | `rounded_corners`, `drop_shadow`, `mirror_reflection`, `tilt_shift`, `pixelate`, `color_overlay` |
|
|
132
|
+
| `texture` | Pattern generators | `perlin_noise`, `grid_pattern`, `stripe_pattern`, `dot_pattern` |
|
|
133
|
+
| `watermark` | Branding tools | `text_watermark`, `image_watermark`, `footer_bar` |
|
|
134
|
+
| `utils` | Helpers | `load_font`, `mpl_to_pil`, `numpy_to_pil`, `pil_to_numpy` |
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## Effects Pipeline API
|
|
139
|
+
|
|
140
|
+
`EffectsPipeline` wraps a PIL `Image` and returns `self` from every effect method, enabling fluent call chains. Call `.export(path)` to save the result to disk, or access the `.image` property to get the current frame without writing a file. The pipeline operates on an internal copy, so the original image is never mutated.
|
|
141
|
+
|
|
142
|
+
```python
|
|
143
|
+
pipeline = EffectsPipeline(img)
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
| Method | Parameters | Description |
|
|
147
|
+
|--------|-----------|-------------|
|
|
148
|
+
| `.grain(intensity, monochrome)` | `intensity: float = 0.06`, `monochrome: bool = True` | Film grain noise overlay |
|
|
149
|
+
| `.glow(color, radius, intensity)` | `color: (R,G,B) = (0,245,212)`, `radius: int = 20`, `intensity: float = 0.5` | Bright-area glow with RGB tint |
|
|
150
|
+
| `.halftone(dot_size, spacing, angle)` | `dot_size: int = 6`, `spacing: int = 8`, `angle: float = 45.0` | Halftone dot pattern conversion |
|
|
151
|
+
| `.scanlines(spacing, opacity, color)` | `spacing: int = 4`, `opacity: float = 0.3`, `color: (R,G,B) = (0,0,0)` | CRT scanline overlay |
|
|
152
|
+
| `.glass(x, y, w, h, blur, tint, radius)` | `x, y, w, h: int`, `blur: int = 15`, `tint: (R,G,B,A) = (20,25,40,160)`, `radius: int = 12` | Glassmorphism card region |
|
|
153
|
+
| `.duotone(dark, light)` | `dark: (R,G,B) = (10,10,40)`, `light: (R,G,B) = (255,200,50)` | Two-tone color mapping |
|
|
154
|
+
| `.vignette(strength, radius)` | `strength: float = 0.3`, `radius: float = 1.0` | Edge darkening |
|
|
155
|
+
| `.chromatic(offset, direction)` | `offset: int = 5`, `direction: str = "horizontal"` | Channel-shift chromatic aberration |
|
|
156
|
+
| `.bloom(threshold, radius, intensity)` | `threshold: int = 200`, `radius: int = 15`, `intensity: float = 0.4` | Bloom glow on bright regions |
|
|
157
|
+
| `.export(path, quality)` | `path: str`, `quality: int = 95` | Save to disk, returns `Image` |
|
|
158
|
+
| `.image` | property | Current image copy (no save) |
|
|
159
|
+
|
|
160
|
+
### Example: full chain
|
|
161
|
+
|
|
162
|
+
```python
|
|
163
|
+
from ideamaxfx import EffectsPipeline
|
|
164
|
+
from PIL import Image
|
|
165
|
+
|
|
166
|
+
result = (EffectsPipeline(Image.open("input.png"))
|
|
167
|
+
.grain(0.04)
|
|
168
|
+
.bloom(threshold=180, radius=20, intensity=0.5)
|
|
169
|
+
.chromatic(offset=3)
|
|
170
|
+
.scanlines(spacing=3, opacity=0.2)
|
|
171
|
+
.vignette(0.35)
|
|
172
|
+
.export("cinematic.png"))
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
## Animation Export
|
|
178
|
+
|
|
179
|
+
The `animate` module produces a list of PIL `Image` frames. Use `export_gif` or `export_apng` to save them.
|
|
180
|
+
|
|
181
|
+
```python
|
|
182
|
+
from ideamaxfx.animate import export_gif, export_apng
|
|
183
|
+
|
|
184
|
+
# GIF with automatic optimization
|
|
185
|
+
export_gif(frames, "output.gif", fps=15, max_colors=128, max_kb=500)
|
|
186
|
+
|
|
187
|
+
# Lossless APNG
|
|
188
|
+
export_apng(frames, "output.png", fps=15)
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
**`export_gif` parameters:**
|
|
192
|
+
|
|
193
|
+
| Parameter | Type | Default | Description |
|
|
194
|
+
|-----------|------|---------|-------------|
|
|
195
|
+
| `frames` | `list[Image]` | required | PIL Image frame sequence |
|
|
196
|
+
| `output_path` | `str` | required | Destination file path |
|
|
197
|
+
| `fps` | `int` | `15` | Frames per second |
|
|
198
|
+
| `max_colors` | `int` | `128` | Maximum palette colors |
|
|
199
|
+
| `max_kb` | `int` | `500` | Target max file size in KB |
|
|
200
|
+
| `lossy` | `int` | `40` | gifsicle lossy level (0-200) |
|
|
201
|
+
| `optimize` | `bool` | `True` | Use gifsicle if available |
|
|
202
|
+
|
|
203
|
+
When gifsicle is installed, `export_gif` runs a two-pass optimization: first at the requested settings, then a more aggressive pass if the file exceeds `max_kb`. Without gifsicle it falls back to Pillow's built-in GIF writer with adaptive palette quantization.
|
|
204
|
+
|
|
205
|
+
**`export_apng` parameters:**
|
|
206
|
+
|
|
207
|
+
| Parameter | Type | Default | Description |
|
|
208
|
+
|-----------|------|---------|-------------|
|
|
209
|
+
| `frames` | `list[Image]` | required | PIL Image frame sequence |
|
|
210
|
+
| `output_path` | `str` | required | Destination file path |
|
|
211
|
+
| `fps` | `int` | `15` | Frames per second |
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
## Easing Functions
|
|
216
|
+
|
|
217
|
+
All 15 easing functions accept `t` in the range `[0.0, 1.0]` and return the eased value. Pass the function name as a string to any `easing` parameter in the `animate` module, or call `get_easing(name)` to retrieve the callable directly.
|
|
218
|
+
|
|
219
|
+
| Name | Description |
|
|
220
|
+
|------|-------------|
|
|
221
|
+
| `linear` | Constant speed, no acceleration |
|
|
222
|
+
| `ease_in_quad` | Quadratic ease-in (accelerating) |
|
|
223
|
+
| `ease_out_quad` | Quadratic ease-out (decelerating) |
|
|
224
|
+
| `ease_in_out_quad` | Quadratic ease-in then ease-out |
|
|
225
|
+
| `ease_in_cubic` | Cubic ease-in |
|
|
226
|
+
| `ease_out_cubic` | Cubic ease-out |
|
|
227
|
+
| `ease_in_out_cubic` | Cubic ease-in then ease-out |
|
|
228
|
+
| `ease_in_quart` | Quartic ease-in |
|
|
229
|
+
| `ease_out_quart` | Quartic ease-out |
|
|
230
|
+
| `ease_in_out_quart` | Quartic ease-in then ease-out |
|
|
231
|
+
| `ease_out_elastic` | Spring overshoot with oscillation |
|
|
232
|
+
| `ease_out_bounce` | Bouncing ball decay |
|
|
233
|
+
| `ease_out_back` | Slight overshoot past target |
|
|
234
|
+
| `ease_in_expo` | Exponential ease-in |
|
|
235
|
+
| `ease_out_expo` | Exponential ease-out |
|
|
236
|
+
|
|
237
|
+
Use by name:
|
|
238
|
+
|
|
239
|
+
```python
|
|
240
|
+
from ideamaxfx.animate import bar_grow
|
|
241
|
+
|
|
242
|
+
frames = bar_grow(labels=["A", "B"], values=[80, 60], easing="ease_out_bounce")
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
Or retrieve the function directly:
|
|
246
|
+
|
|
247
|
+
```python
|
|
248
|
+
from ideamaxfx.animate import get_easing
|
|
249
|
+
|
|
250
|
+
fn = get_easing("ease_out_elastic")
|
|
251
|
+
value = fn(0.5) # returns eased float in 0.0-1.0
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
---
|
|
255
|
+
|
|
256
|
+
## Standalone Effects
|
|
257
|
+
|
|
258
|
+
Each effect is also available as a standalone function that takes a PIL `Image` and returns a new `Image`. Use these when you need a single effect without the pipeline wrapper.
|
|
259
|
+
|
|
260
|
+
```python
|
|
261
|
+
from ideamaxfx.effects import grain, vignette, bloom
|
|
262
|
+
|
|
263
|
+
img = grain(img, intensity=0.05)
|
|
264
|
+
img = bloom(img, threshold=190, radius=12, intensity=0.3)
|
|
265
|
+
img = vignette(img, strength=0.25)
|
|
266
|
+
img.save("output.png")
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
Additional standalone functions not exposed on the pipeline:
|
|
270
|
+
|
|
271
|
+
| Function | Module | Description |
|
|
272
|
+
|----------|--------|-------------|
|
|
273
|
+
| `glow_border(img, color, width, radius)` | `effects` | Glowing border around image edges |
|
|
274
|
+
| `blue_noise(width, height)` | `effects` | Generate blue noise dither pattern |
|
|
275
|
+
| `pattern_overlay(img, pattern, opacity)` | `effects` | Tile a pattern over an image |
|
|
276
|
+
| `blend(base, overlay, mode, opacity)` | `effects` | Photoshop-style blend modes |
|
|
277
|
+
|
|
278
|
+
---
|
|
279
|
+
|
|
280
|
+
## Color Utilities
|
|
281
|
+
|
|
282
|
+
The `color` module provides conversion, harmony, palette extraction, and accessibility checking.
|
|
283
|
+
|
|
284
|
+
```python
|
|
285
|
+
from ideamaxfx.color import hex_to_rgb, complementary, contrast_ratio, wcag_check
|
|
286
|
+
|
|
287
|
+
rgb = hex_to_rgb("#d4213d") # (212, 33, 61)
|
|
288
|
+
comp = complementary(rgb) # complementary hue
|
|
289
|
+
ratio = contrast_ratio((255, 255, 255), rgb) # WCAG contrast ratio
|
|
290
|
+
passes = wcag_check((255, 255, 255), rgb) # AA/AAA compliance dict
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
---
|
|
294
|
+
|
|
295
|
+
## Requirements
|
|
296
|
+
|
|
297
|
+
**Core** (installed automatically):
|
|
298
|
+
|
|
299
|
+
| Package | Version |
|
|
300
|
+
|---------|---------|
|
|
301
|
+
| Python | >= 3.9 |
|
|
302
|
+
| Pillow | >= 10.0 |
|
|
303
|
+
| numpy | >= 1.24 |
|
|
304
|
+
| imageio | >= 2.31 |
|
|
305
|
+
|
|
306
|
+
**Optional** (install via `pip install ideamaxfx[full]`):
|
|
307
|
+
|
|
308
|
+
| Package | Version | Purpose |
|
|
309
|
+
|---------|---------|---------|
|
|
310
|
+
| matplotlib | >= 3.7 | Chart rendering backends |
|
|
311
|
+
| scipy | >= 1.10 | Advanced interpolation and filters |
|
|
312
|
+
|
|
313
|
+
**Optional system tool:**
|
|
314
|
+
|
|
315
|
+
| Tool | Purpose |
|
|
316
|
+
|------|---------|
|
|
317
|
+
| [gifsicle](https://www.lcdf.org/gifsicle/) | GIF optimization (auto-detected at export time) |
|
|
318
|
+
|
|
319
|
+
---
|
|
320
|
+
|
|
321
|
+
## Development
|
|
322
|
+
|
|
323
|
+
```bash
|
|
324
|
+
git clone https://github.com/devideamax/ideamaxfx.git
|
|
325
|
+
cd ideamaxfx
|
|
326
|
+
pip install -e ".[dev]"
|
|
327
|
+
pytest tests/
|
|
328
|
+
ruff check src/
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
The `[dev]` extra installs `pytest`, `pytest-cov`, `ruff`, and `mypy`.
|
|
332
|
+
|
|
333
|
+
Run the type checker:
|
|
334
|
+
|
|
335
|
+
```bash
|
|
336
|
+
mypy src/
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
---
|
|
340
|
+
|
|
341
|
+
## Contributing
|
|
342
|
+
|
|
343
|
+
1. Fork the repository.
|
|
344
|
+
2. Create a feature branch from `main`.
|
|
345
|
+
3. Add tests for new functionality.
|
|
346
|
+
4. Ensure `pytest tests/` and `ruff check src/` pass.
|
|
347
|
+
5. Open a pull request.
|
|
348
|
+
|
|
349
|
+
---
|
|
350
|
+
|
|
351
|
+
## License
|
|
352
|
+
|
|
353
|
+
MIT License. Copyright (c) 2026 IDEAMAX.
|
|
354
|
+
|
|
355
|
+
See [LICENSE](LICENSE) for the full text.
|
|
356
|
+
|
|
357
|
+
---
|
|
358
|
+
|
|
359
|
+
## Links
|
|
360
|
+
|
|
361
|
+
- **GitHub:** [github.com/devideamax/ideamaxfx](https://github.com/devideamax/ideamaxfx)
|
|
362
|
+
- **Changelog:** [CHANGELOG.md](./CHANGELOG.md)
|
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
# ideamaxfx
|
|
2
|
+
|
|
3
|
+
**Post-production effects, animated chart build-up, and visual toolkit for Python.**
|
|
4
|
+
|
|
5
|
+
[](https://www.python.org/downloads/)
|
|
6
|
+
[](LICENSE)
|
|
7
|
+
[]()
|
|
8
|
+
[]()
|
|
9
|
+
[](https://github.com/astral-sh/ruff)
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## What It Does
|
|
14
|
+
|
|
15
|
+
- **Post-Production Effects Pipeline** -- Chainable API for cinematic finishing: grain, glow, scanlines, vignette, chromatic aberration, bloom, halftone, duotone, glass card, pattern overlays, and blend modes. Every method returns `self` so you can build complex multi-effect stacks in a single expression.
|
|
16
|
+
|
|
17
|
+
- **Animated Chart Build-Up** -- Generate GIF/APNG sequences where chart elements appear progressively with easing: bar, line, radar, scatter, pie, counter, heatmap, network, and morph transitions. Ships with 15 built-in easing functions and automatic GIF size optimization via gifsicle.
|
|
18
|
+
|
|
19
|
+
- **Visual Toolkit** -- Text effects (neon, gradient, outline, shadow, emboss), layout components (stat cards, progress bars, badges), color utilities, image composition, texture generators, and watermark tools. Pure Pillow core with optional matplotlib/scipy for advanced use cases.
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Installation
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
pip install ideamaxfx
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Include optional dependencies for chart rendering and advanced interpolation:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
pip install ideamaxfx[full] # includes matplotlib + scipy
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Quick Start
|
|
38
|
+
|
|
39
|
+
### Effects Pipeline
|
|
40
|
+
|
|
41
|
+
```python
|
|
42
|
+
from ideamaxfx import EffectsPipeline
|
|
43
|
+
from PIL import Image
|
|
44
|
+
|
|
45
|
+
img = Image.open("chart.png")
|
|
46
|
+
result = (EffectsPipeline(img)
|
|
47
|
+
.grain(0.06)
|
|
48
|
+
.glow(color=(0, 245, 212))
|
|
49
|
+
.scanlines(spacing=4)
|
|
50
|
+
.vignette(0.3)
|
|
51
|
+
.export("finished.png"))
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Animated Bar Chart
|
|
55
|
+
|
|
56
|
+
```python
|
|
57
|
+
from ideamaxfx.animate import bar_grow, export_gif
|
|
58
|
+
|
|
59
|
+
frames = bar_grow(
|
|
60
|
+
labels=['Goals', 'Assists', 'Saves'],
|
|
61
|
+
values=[68, 72, 45],
|
|
62
|
+
colors=['#d4213d', '#006633', '#0056a0'],
|
|
63
|
+
easing='ease_out_elastic'
|
|
64
|
+
)
|
|
65
|
+
export_gif(frames, 'animated.gif', max_kb=500)
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Text Effects
|
|
69
|
+
|
|
70
|
+
```python
|
|
71
|
+
from ideamaxfx.text import neon_text, gradient_text
|
|
72
|
+
from ideamaxfx.utils import load_font
|
|
73
|
+
|
|
74
|
+
font = load_font(size=48)
|
|
75
|
+
img = neon_text(canvas, 20, 20, "ELITE", font=font, color=(0, 245, 212))
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## Modules
|
|
81
|
+
|
|
82
|
+
| Module | Description | Key Functions |
|
|
83
|
+
|--------|-------------|---------------|
|
|
84
|
+
| `effects` | Post-production effects | `grain`, `glow`, `glow_border`, `halftone`, `scanlines`, `glass_card`, `duotone`, `vignette`, `chromatic_aberration`, `bloom`, `blue_noise`, `pattern_overlay`, `blend`, `EffectsPipeline` |
|
|
85
|
+
| `animate` | Animated build-up | `bar_grow`, `line_draw`, `radar_sweep`, `scatter_fade`, `counter_roll`, `pie_fill`, `heatmap_reveal`, `network_build`, `morph`, `stagger_delays`, `compose_animations`, `export_gif`, `export_apng` |
|
|
86
|
+
| `text` | Text effects | `gradient_text`, `neon_text`, `outline_text`, `shadow_text`, `emboss_text` |
|
|
87
|
+
| `color` | Color utilities | `hex_to_rgb`, `rgb_to_hex`, `rgb_to_hsl`, `hsl_to_rgb`, `interpolate_colors`, `complementary`, `triadic`, `analogous`, `extract_palette`, `contrast_ratio`, `wcag_check` |
|
|
88
|
+
| `layout` | UI components | `stat_card`, `progress_bar`, `badge`, `legend_block`, `divider`, `callout` |
|
|
89
|
+
| `compose` | Image composition | `rounded_corners`, `drop_shadow`, `mirror_reflection`, `tilt_shift`, `pixelate`, `color_overlay` |
|
|
90
|
+
| `texture` | Pattern generators | `perlin_noise`, `grid_pattern`, `stripe_pattern`, `dot_pattern` |
|
|
91
|
+
| `watermark` | Branding tools | `text_watermark`, `image_watermark`, `footer_bar` |
|
|
92
|
+
| `utils` | Helpers | `load_font`, `mpl_to_pil`, `numpy_to_pil`, `pil_to_numpy` |
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## Effects Pipeline API
|
|
97
|
+
|
|
98
|
+
`EffectsPipeline` wraps a PIL `Image` and returns `self` from every effect method, enabling fluent call chains. Call `.export(path)` to save the result to disk, or access the `.image` property to get the current frame without writing a file. The pipeline operates on an internal copy, so the original image is never mutated.
|
|
99
|
+
|
|
100
|
+
```python
|
|
101
|
+
pipeline = EffectsPipeline(img)
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
| Method | Parameters | Description |
|
|
105
|
+
|--------|-----------|-------------|
|
|
106
|
+
| `.grain(intensity, monochrome)` | `intensity: float = 0.06`, `monochrome: bool = True` | Film grain noise overlay |
|
|
107
|
+
| `.glow(color, radius, intensity)` | `color: (R,G,B) = (0,245,212)`, `radius: int = 20`, `intensity: float = 0.5` | Bright-area glow with RGB tint |
|
|
108
|
+
| `.halftone(dot_size, spacing, angle)` | `dot_size: int = 6`, `spacing: int = 8`, `angle: float = 45.0` | Halftone dot pattern conversion |
|
|
109
|
+
| `.scanlines(spacing, opacity, color)` | `spacing: int = 4`, `opacity: float = 0.3`, `color: (R,G,B) = (0,0,0)` | CRT scanline overlay |
|
|
110
|
+
| `.glass(x, y, w, h, blur, tint, radius)` | `x, y, w, h: int`, `blur: int = 15`, `tint: (R,G,B,A) = (20,25,40,160)`, `radius: int = 12` | Glassmorphism card region |
|
|
111
|
+
| `.duotone(dark, light)` | `dark: (R,G,B) = (10,10,40)`, `light: (R,G,B) = (255,200,50)` | Two-tone color mapping |
|
|
112
|
+
| `.vignette(strength, radius)` | `strength: float = 0.3`, `radius: float = 1.0` | Edge darkening |
|
|
113
|
+
| `.chromatic(offset, direction)` | `offset: int = 5`, `direction: str = "horizontal"` | Channel-shift chromatic aberration |
|
|
114
|
+
| `.bloom(threshold, radius, intensity)` | `threshold: int = 200`, `radius: int = 15`, `intensity: float = 0.4` | Bloom glow on bright regions |
|
|
115
|
+
| `.export(path, quality)` | `path: str`, `quality: int = 95` | Save to disk, returns `Image` |
|
|
116
|
+
| `.image` | property | Current image copy (no save) |
|
|
117
|
+
|
|
118
|
+
### Example: full chain
|
|
119
|
+
|
|
120
|
+
```python
|
|
121
|
+
from ideamaxfx import EffectsPipeline
|
|
122
|
+
from PIL import Image
|
|
123
|
+
|
|
124
|
+
result = (EffectsPipeline(Image.open("input.png"))
|
|
125
|
+
.grain(0.04)
|
|
126
|
+
.bloom(threshold=180, radius=20, intensity=0.5)
|
|
127
|
+
.chromatic(offset=3)
|
|
128
|
+
.scanlines(spacing=3, opacity=0.2)
|
|
129
|
+
.vignette(0.35)
|
|
130
|
+
.export("cinematic.png"))
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## Animation Export
|
|
136
|
+
|
|
137
|
+
The `animate` module produces a list of PIL `Image` frames. Use `export_gif` or `export_apng` to save them.
|
|
138
|
+
|
|
139
|
+
```python
|
|
140
|
+
from ideamaxfx.animate import export_gif, export_apng
|
|
141
|
+
|
|
142
|
+
# GIF with automatic optimization
|
|
143
|
+
export_gif(frames, "output.gif", fps=15, max_colors=128, max_kb=500)
|
|
144
|
+
|
|
145
|
+
# Lossless APNG
|
|
146
|
+
export_apng(frames, "output.png", fps=15)
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
**`export_gif` parameters:**
|
|
150
|
+
|
|
151
|
+
| Parameter | Type | Default | Description |
|
|
152
|
+
|-----------|------|---------|-------------|
|
|
153
|
+
| `frames` | `list[Image]` | required | PIL Image frame sequence |
|
|
154
|
+
| `output_path` | `str` | required | Destination file path |
|
|
155
|
+
| `fps` | `int` | `15` | Frames per second |
|
|
156
|
+
| `max_colors` | `int` | `128` | Maximum palette colors |
|
|
157
|
+
| `max_kb` | `int` | `500` | Target max file size in KB |
|
|
158
|
+
| `lossy` | `int` | `40` | gifsicle lossy level (0-200) |
|
|
159
|
+
| `optimize` | `bool` | `True` | Use gifsicle if available |
|
|
160
|
+
|
|
161
|
+
When gifsicle is installed, `export_gif` runs a two-pass optimization: first at the requested settings, then a more aggressive pass if the file exceeds `max_kb`. Without gifsicle it falls back to Pillow's built-in GIF writer with adaptive palette quantization.
|
|
162
|
+
|
|
163
|
+
**`export_apng` parameters:**
|
|
164
|
+
|
|
165
|
+
| Parameter | Type | Default | Description |
|
|
166
|
+
|-----------|------|---------|-------------|
|
|
167
|
+
| `frames` | `list[Image]` | required | PIL Image frame sequence |
|
|
168
|
+
| `output_path` | `str` | required | Destination file path |
|
|
169
|
+
| `fps` | `int` | `15` | Frames per second |
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## Easing Functions
|
|
174
|
+
|
|
175
|
+
All 15 easing functions accept `t` in the range `[0.0, 1.0]` and return the eased value. Pass the function name as a string to any `easing` parameter in the `animate` module, or call `get_easing(name)` to retrieve the callable directly.
|
|
176
|
+
|
|
177
|
+
| Name | Description |
|
|
178
|
+
|------|-------------|
|
|
179
|
+
| `linear` | Constant speed, no acceleration |
|
|
180
|
+
| `ease_in_quad` | Quadratic ease-in (accelerating) |
|
|
181
|
+
| `ease_out_quad` | Quadratic ease-out (decelerating) |
|
|
182
|
+
| `ease_in_out_quad` | Quadratic ease-in then ease-out |
|
|
183
|
+
| `ease_in_cubic` | Cubic ease-in |
|
|
184
|
+
| `ease_out_cubic` | Cubic ease-out |
|
|
185
|
+
| `ease_in_out_cubic` | Cubic ease-in then ease-out |
|
|
186
|
+
| `ease_in_quart` | Quartic ease-in |
|
|
187
|
+
| `ease_out_quart` | Quartic ease-out |
|
|
188
|
+
| `ease_in_out_quart` | Quartic ease-in then ease-out |
|
|
189
|
+
| `ease_out_elastic` | Spring overshoot with oscillation |
|
|
190
|
+
| `ease_out_bounce` | Bouncing ball decay |
|
|
191
|
+
| `ease_out_back` | Slight overshoot past target |
|
|
192
|
+
| `ease_in_expo` | Exponential ease-in |
|
|
193
|
+
| `ease_out_expo` | Exponential ease-out |
|
|
194
|
+
|
|
195
|
+
Use by name:
|
|
196
|
+
|
|
197
|
+
```python
|
|
198
|
+
from ideamaxfx.animate import bar_grow
|
|
199
|
+
|
|
200
|
+
frames = bar_grow(labels=["A", "B"], values=[80, 60], easing="ease_out_bounce")
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
Or retrieve the function directly:
|
|
204
|
+
|
|
205
|
+
```python
|
|
206
|
+
from ideamaxfx.animate import get_easing
|
|
207
|
+
|
|
208
|
+
fn = get_easing("ease_out_elastic")
|
|
209
|
+
value = fn(0.5) # returns eased float in 0.0-1.0
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
---
|
|
213
|
+
|
|
214
|
+
## Standalone Effects
|
|
215
|
+
|
|
216
|
+
Each effect is also available as a standalone function that takes a PIL `Image` and returns a new `Image`. Use these when you need a single effect without the pipeline wrapper.
|
|
217
|
+
|
|
218
|
+
```python
|
|
219
|
+
from ideamaxfx.effects import grain, vignette, bloom
|
|
220
|
+
|
|
221
|
+
img = grain(img, intensity=0.05)
|
|
222
|
+
img = bloom(img, threshold=190, radius=12, intensity=0.3)
|
|
223
|
+
img = vignette(img, strength=0.25)
|
|
224
|
+
img.save("output.png")
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
Additional standalone functions not exposed on the pipeline:
|
|
228
|
+
|
|
229
|
+
| Function | Module | Description |
|
|
230
|
+
|----------|--------|-------------|
|
|
231
|
+
| `glow_border(img, color, width, radius)` | `effects` | Glowing border around image edges |
|
|
232
|
+
| `blue_noise(width, height)` | `effects` | Generate blue noise dither pattern |
|
|
233
|
+
| `pattern_overlay(img, pattern, opacity)` | `effects` | Tile a pattern over an image |
|
|
234
|
+
| `blend(base, overlay, mode, opacity)` | `effects` | Photoshop-style blend modes |
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## Color Utilities
|
|
239
|
+
|
|
240
|
+
The `color` module provides conversion, harmony, palette extraction, and accessibility checking.
|
|
241
|
+
|
|
242
|
+
```python
|
|
243
|
+
from ideamaxfx.color import hex_to_rgb, complementary, contrast_ratio, wcag_check
|
|
244
|
+
|
|
245
|
+
rgb = hex_to_rgb("#d4213d") # (212, 33, 61)
|
|
246
|
+
comp = complementary(rgb) # complementary hue
|
|
247
|
+
ratio = contrast_ratio((255, 255, 255), rgb) # WCAG contrast ratio
|
|
248
|
+
passes = wcag_check((255, 255, 255), rgb) # AA/AAA compliance dict
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
---
|
|
252
|
+
|
|
253
|
+
## Requirements
|
|
254
|
+
|
|
255
|
+
**Core** (installed automatically):
|
|
256
|
+
|
|
257
|
+
| Package | Version |
|
|
258
|
+
|---------|---------|
|
|
259
|
+
| Python | >= 3.9 |
|
|
260
|
+
| Pillow | >= 10.0 |
|
|
261
|
+
| numpy | >= 1.24 |
|
|
262
|
+
| imageio | >= 2.31 |
|
|
263
|
+
|
|
264
|
+
**Optional** (install via `pip install ideamaxfx[full]`):
|
|
265
|
+
|
|
266
|
+
| Package | Version | Purpose |
|
|
267
|
+
|---------|---------|---------|
|
|
268
|
+
| matplotlib | >= 3.7 | Chart rendering backends |
|
|
269
|
+
| scipy | >= 1.10 | Advanced interpolation and filters |
|
|
270
|
+
|
|
271
|
+
**Optional system tool:**
|
|
272
|
+
|
|
273
|
+
| Tool | Purpose |
|
|
274
|
+
|------|---------|
|
|
275
|
+
| [gifsicle](https://www.lcdf.org/gifsicle/) | GIF optimization (auto-detected at export time) |
|
|
276
|
+
|
|
277
|
+
---
|
|
278
|
+
|
|
279
|
+
## Development
|
|
280
|
+
|
|
281
|
+
```bash
|
|
282
|
+
git clone https://github.com/devideamax/ideamaxfx.git
|
|
283
|
+
cd ideamaxfx
|
|
284
|
+
pip install -e ".[dev]"
|
|
285
|
+
pytest tests/
|
|
286
|
+
ruff check src/
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
The `[dev]` extra installs `pytest`, `pytest-cov`, `ruff`, and `mypy`.
|
|
290
|
+
|
|
291
|
+
Run the type checker:
|
|
292
|
+
|
|
293
|
+
```bash
|
|
294
|
+
mypy src/
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
---
|
|
298
|
+
|
|
299
|
+
## Contributing
|
|
300
|
+
|
|
301
|
+
1. Fork the repository.
|
|
302
|
+
2. Create a feature branch from `main`.
|
|
303
|
+
3. Add tests for new functionality.
|
|
304
|
+
4. Ensure `pytest tests/` and `ruff check src/` pass.
|
|
305
|
+
5. Open a pull request.
|
|
306
|
+
|
|
307
|
+
---
|
|
308
|
+
|
|
309
|
+
## License
|
|
310
|
+
|
|
311
|
+
MIT License. Copyright (c) 2026 IDEAMAX.
|
|
312
|
+
|
|
313
|
+
See [LICENSE](LICENSE) for the full text.
|
|
314
|
+
|
|
315
|
+
---
|
|
316
|
+
|
|
317
|
+
## Links
|
|
318
|
+
|
|
319
|
+
- **GitHub:** [github.com/devideamax/ideamaxfx](https://github.com/devideamax/ideamaxfx)
|
|
320
|
+
- **Changelog:** [CHANGELOG.md](./CHANGELOG.md)
|