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.
Files changed (90) hide show
  1. ideamaxfx-0.1.0/LICENSE +21 -0
  2. ideamaxfx-0.1.0/PKG-INFO +362 -0
  3. ideamaxfx-0.1.0/README.md +320 -0
  4. ideamaxfx-0.1.0/pyproject.toml +61 -0
  5. ideamaxfx-0.1.0/setup.cfg +4 -0
  6. ideamaxfx-0.1.0/src/ideamaxfx/__init__.py +27 -0
  7. ideamaxfx-0.1.0/src/ideamaxfx/animate/__init__.py +64 -0
  8. ideamaxfx-0.1.0/src/ideamaxfx/animate/bar.py +146 -0
  9. ideamaxfx-0.1.0/src/ideamaxfx/animate/composer.py +85 -0
  10. ideamaxfx-0.1.0/src/ideamaxfx/animate/core.py +60 -0
  11. ideamaxfx-0.1.0/src/ideamaxfx/animate/counter.py +84 -0
  12. ideamaxfx-0.1.0/src/ideamaxfx/animate/easing.py +151 -0
  13. ideamaxfx-0.1.0/src/ideamaxfx/animate/export.py +126 -0
  14. ideamaxfx-0.1.0/src/ideamaxfx/animate/heatmap.py +137 -0
  15. ideamaxfx-0.1.0/src/ideamaxfx/animate/line.py +136 -0
  16. ideamaxfx-0.1.0/src/ideamaxfx/animate/morph.py +44 -0
  17. ideamaxfx-0.1.0/src/ideamaxfx/animate/network.py +95 -0
  18. ideamaxfx-0.1.0/src/ideamaxfx/animate/pie.py +131 -0
  19. ideamaxfx-0.1.0/src/ideamaxfx/animate/radar.py +116 -0
  20. ideamaxfx-0.1.0/src/ideamaxfx/animate/scatter.py +106 -0
  21. ideamaxfx-0.1.0/src/ideamaxfx/animate/stagger.py +41 -0
  22. ideamaxfx-0.1.0/src/ideamaxfx/color/__init__.py +30 -0
  23. ideamaxfx-0.1.0/src/ideamaxfx/color/accessibility.py +97 -0
  24. ideamaxfx-0.1.0/src/ideamaxfx/color/adjust.py +81 -0
  25. ideamaxfx-0.1.0/src/ideamaxfx/color/convert.py +132 -0
  26. ideamaxfx-0.1.0/src/ideamaxfx/color/harmonies.py +110 -0
  27. ideamaxfx-0.1.0/src/ideamaxfx/color/interpolate.py +59 -0
  28. ideamaxfx-0.1.0/src/ideamaxfx/color/palette.py +121 -0
  29. ideamaxfx-0.1.0/src/ideamaxfx/compose/__init__.py +19 -0
  30. ideamaxfx-0.1.0/src/ideamaxfx/compose/overlay.py +65 -0
  31. ideamaxfx-0.1.0/src/ideamaxfx/compose/pixelate.py +74 -0
  32. ideamaxfx-0.1.0/src/ideamaxfx/compose/reflection.py +62 -0
  33. ideamaxfx-0.1.0/src/ideamaxfx/compose/rounded.py +41 -0
  34. ideamaxfx-0.1.0/src/ideamaxfx/compose/shadow.py +65 -0
  35. ideamaxfx-0.1.0/src/ideamaxfx/compose/tilt_shift.py +71 -0
  36. ideamaxfx-0.1.0/src/ideamaxfx/effects/__init__.py +34 -0
  37. ideamaxfx-0.1.0/src/ideamaxfx/effects/blend.py +70 -0
  38. ideamaxfx-0.1.0/src/ideamaxfx/effects/bloom.py +53 -0
  39. ideamaxfx-0.1.0/src/ideamaxfx/effects/chromatic.py +71 -0
  40. ideamaxfx-0.1.0/src/ideamaxfx/effects/duotone.py +40 -0
  41. ideamaxfx-0.1.0/src/ideamaxfx/effects/glass.py +84 -0
  42. ideamaxfx-0.1.0/src/ideamaxfx/effects/glow.py +96 -0
  43. ideamaxfx-0.1.0/src/ideamaxfx/effects/grain.py +45 -0
  44. ideamaxfx-0.1.0/src/ideamaxfx/effects/halftone.py +65 -0
  45. ideamaxfx-0.1.0/src/ideamaxfx/effects/noise.py +70 -0
  46. ideamaxfx-0.1.0/src/ideamaxfx/effects/patterns.py +132 -0
  47. ideamaxfx-0.1.0/src/ideamaxfx/effects/pipeline.py +251 -0
  48. ideamaxfx-0.1.0/src/ideamaxfx/effects/scanlines.py +48 -0
  49. ideamaxfx-0.1.0/src/ideamaxfx/effects/vignette.py +49 -0
  50. ideamaxfx-0.1.0/src/ideamaxfx/layout/__init__.py +10 -0
  51. ideamaxfx-0.1.0/src/ideamaxfx/layout/badge.py +54 -0
  52. ideamaxfx-0.1.0/src/ideamaxfx/layout/callout.py +89 -0
  53. ideamaxfx-0.1.0/src/ideamaxfx/layout/divider.py +63 -0
  54. ideamaxfx-0.1.0/src/ideamaxfx/layout/legend.py +74 -0
  55. ideamaxfx-0.1.0/src/ideamaxfx/layout/progress_bar.py +87 -0
  56. ideamaxfx-0.1.0/src/ideamaxfx/layout/stat_card.py +63 -0
  57. ideamaxfx-0.1.0/src/ideamaxfx/py.typed +0 -0
  58. ideamaxfx-0.1.0/src/ideamaxfx/text/__init__.py +11 -0
  59. ideamaxfx-0.1.0/src/ideamaxfx/text/emboss.py +102 -0
  60. ideamaxfx-0.1.0/src/ideamaxfx/text/gradient.py +74 -0
  61. ideamaxfx-0.1.0/src/ideamaxfx/text/neon.py +62 -0
  62. ideamaxfx-0.1.0/src/ideamaxfx/text/outline.py +58 -0
  63. ideamaxfx-0.1.0/src/ideamaxfx/text/shadow.py +64 -0
  64. ideamaxfx-0.1.0/src/ideamaxfx/texture/__init__.py +10 -0
  65. ideamaxfx-0.1.0/src/ideamaxfx/texture/dots.py +46 -0
  66. ideamaxfx-0.1.0/src/ideamaxfx/texture/grid.py +157 -0
  67. ideamaxfx-0.1.0/src/ideamaxfx/texture/perlin.py +182 -0
  68. ideamaxfx-0.1.0/src/ideamaxfx/texture/stripes.py +138 -0
  69. ideamaxfx-0.1.0/src/ideamaxfx/utils/__init__.py +6 -0
  70. ideamaxfx-0.1.0/src/ideamaxfx/utils/convert.py +64 -0
  71. ideamaxfx-0.1.0/src/ideamaxfx/utils/fonts.py +66 -0
  72. ideamaxfx-0.1.0/src/ideamaxfx/watermark/__init__.py +7 -0
  73. ideamaxfx-0.1.0/src/ideamaxfx/watermark/footer.py +72 -0
  74. ideamaxfx-0.1.0/src/ideamaxfx/watermark/image_mark.py +59 -0
  75. ideamaxfx-0.1.0/src/ideamaxfx/watermark/text_mark.py +58 -0
  76. ideamaxfx-0.1.0/src/ideamaxfx.egg-info/PKG-INFO +362 -0
  77. ideamaxfx-0.1.0/src/ideamaxfx.egg-info/SOURCES.txt +88 -0
  78. ideamaxfx-0.1.0/src/ideamaxfx.egg-info/dependency_links.txt +1 -0
  79. ideamaxfx-0.1.0/src/ideamaxfx.egg-info/requires.txt +16 -0
  80. ideamaxfx-0.1.0/src/ideamaxfx.egg-info/top_level.txt +1 -0
  81. ideamaxfx-0.1.0/tests/test_animate.py +247 -0
  82. ideamaxfx-0.1.0/tests/test_color.py +119 -0
  83. ideamaxfx-0.1.0/tests/test_compose.py +283 -0
  84. ideamaxfx-0.1.0/tests/test_edge_cases.py +838 -0
  85. ideamaxfx-0.1.0/tests/test_effects.py +145 -0
  86. ideamaxfx-0.1.0/tests/test_layout.py +262 -0
  87. ideamaxfx-0.1.0/tests/test_text.py +87 -0
  88. ideamaxfx-0.1.0/tests/test_texture.py +220 -0
  89. ideamaxfx-0.1.0/tests/test_utils.py +141 -0
  90. ideamaxfx-0.1.0/tests/test_watermark.py +185 -0
@@ -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.
@@ -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
+ [![Python 3.9+](https://img.shields.io/badge/python-3.9%2B-blue)](https://www.python.org/downloads/)
48
+ [![MIT License](https://img.shields.io/badge/license-MIT-green)](LICENSE)
49
+ [![Tests](https://img.shields.io/badge/tests-341%20passed-brightgreen)]()
50
+ [![Coverage](https://img.shields.io/badge/coverage-91%25-brightgreen)]()
51
+ [![Code style: ruff](https://img.shields.io/badge/code%20style-ruff-000000)](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
+ [![Python 3.9+](https://img.shields.io/badge/python-3.9%2B-blue)](https://www.python.org/downloads/)
6
+ [![MIT License](https://img.shields.io/badge/license-MIT-green)](LICENSE)
7
+ [![Tests](https://img.shields.io/badge/tests-341%20passed-brightgreen)]()
8
+ [![Coverage](https://img.shields.io/badge/coverage-91%25-brightgreen)]()
9
+ [![Code style: ruff](https://img.shields.io/badge/code%20style-ruff-000000)](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)