qrforge 1.0.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 (36) hide show
  1. qrforge-1.0.0/LICENSE.md +7 -0
  2. qrforge-1.0.0/PKG-INFO +174 -0
  3. qrforge-1.0.0/README.md +140 -0
  4. qrforge-1.0.0/pyproject.toml +13 -0
  5. qrforge-1.0.0/qrforge/__init__.py +51 -0
  6. qrforge-1.0.0/qrforge/__main__.py +6 -0
  7. qrforge-1.0.0/qrforge/api.py +338 -0
  8. qrforge-1.0.0/qrforge/bits.py +39 -0
  9. qrforge-1.0.0/qrforge/cli.py +92 -0
  10. qrforge-1.0.0/qrforge/color.py +235 -0
  11. qrforge-1.0.0/qrforge/encoder.py +279 -0
  12. qrforge-1.0.0/qrforge/exceptions.py +19 -0
  13. qrforge-1.0.0/qrforge/gf.py +218 -0
  14. qrforge-1.0.0/qrforge/gradient.py +270 -0
  15. qrforge-1.0.0/qrforge/image.py +405 -0
  16. qrforge-1.0.0/qrforge/matrix.py +363 -0
  17. qrforge-1.0.0/qrforge/presets.py +97 -0
  18. qrforge-1.0.0/qrforge/render/__init__.py +1 -0
  19. qrforge-1.0.0/qrforge/render/ansi.py +75 -0
  20. qrforge-1.0.0/qrforge/render/pdf.py +119 -0
  21. qrforge-1.0.0/qrforge/render/raster.py +421 -0
  22. qrforge-1.0.0/qrforge/render/svg.py +312 -0
  23. qrforge-1.0.0/qrforge/shaders.py +828 -0
  24. qrforge-1.0.0/qrforge/shapes.py +234 -0
  25. qrforge-1.0.0/qrforge/style.py +185 -0
  26. qrforge-1.0.0/qrforge/tables.py +138 -0
  27. qrforge-1.0.0/qrforge/verify.py +210 -0
  28. qrforge-1.0.0/qrforge.egg-info/PKG-INFO +174 -0
  29. qrforge-1.0.0/qrforge.egg-info/SOURCES.txt +34 -0
  30. qrforge-1.0.0/qrforge.egg-info/dependency_links.txt +1 -0
  31. qrforge-1.0.0/qrforge.egg-info/entry_points.txt +2 -0
  32. qrforge-1.0.0/qrforge.egg-info/requires.txt +3 -0
  33. qrforge-1.0.0/qrforge.egg-info/top_level.txt +1 -0
  34. qrforge-1.0.0/setup.cfg +4 -0
  35. qrforge-1.0.0/setup.py +58 -0
  36. qrforge-1.0.0/tests/test_qrforge.py +419 -0
@@ -0,0 +1,7 @@
1
+ MIT License (Modified)
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to make derivative works based on the Software, provided that any substantial changes to the Software are clearly distinguished from the original work and are distributed under a different name.
4
+
5
+ The original copyright notice and disclaimer must be retained in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS," WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
qrforge-1.0.0/PKG-INFO ADDED
@@ -0,0 +1,174 @@
1
+ Metadata-Version: 2.4
2
+ Name: qrforge
3
+ Version: 1.0.0
4
+ Summary: Generate and heavily customise QR codes (shapes, gradients, shaders, logos, textures) in pure Python; Pillow optional.
5
+ Author: qrforge contributors
6
+ License: MIT
7
+ Keywords: qr,qrcode,barcode,svg,png,generator,art
8
+ Classifier: Development Status :: 5 - Production/Stable
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3 :: Only
13
+ Classifier: Programming Language :: Python :: 3.8
14
+ Classifier: Programming Language :: Python :: 3.9
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Topic :: Multimedia :: Graphics
19
+ Requires-Python: >=3.8
20
+ Description-Content-Type: text/markdown
21
+ License-File: LICENSE.md
22
+ Provides-Extra: imaging
23
+ Requires-Dist: pillow>=9; extra == "imaging"
24
+ Dynamic: author
25
+ Dynamic: classifier
26
+ Dynamic: description
27
+ Dynamic: description-content-type
28
+ Dynamic: keywords
29
+ Dynamic: license
30
+ Dynamic: license-file
31
+ Dynamic: provides-extra
32
+ Dynamic: requires-python
33
+ Dynamic: summary
34
+
35
+ # qrforge
36
+ ![Python Version](https://img.shields.io/badge/python-3.8+-blue.svg)
37
+ ![License](https://img.shields.io/badge/license-MIT-brightgreen.svg)
38
+ ![Tests](https://img.shields.io/badge/tests-passing-brightgreen.svg)
39
+ ![Dependencies](https://img.shields.io/badge/dependencies-0%20(required)-blue.svg)
40
+
41
+ An open-source Python library for **generating and art-directing QR codes**: custom module shapes, gradients, shaders, logos, image textures, backgrounds and shadows — output to PNG, SVG, PDF, terminal ANSI, ASCII or Pillow.
42
+
43
+ *qrforge implements the full QR encoding pipeline (modes, Reed–Solomon error correction, masking, versions 1–40) from scratch against the standard library. There are **zero required dependencies**; [Pillow](https://pillow.readthedocs.io) is used only for non-PNG image formats, PIL images, or JPEG/GIF/WEBP logos. PNG reading/writing is built in.*
44
+
45
+ > [!NOTE]
46
+ > **qrforge** is intended to produce both *correct* and *beautiful* QR codes. Every rendered symbol is round-trip verified by a bundled decoder, and the test-suite re-rasterises the SVG geometry to prove it reproduces the matrix — so "pretty" never comes at the cost of "scannable".
47
+
48
+ ## Installation
49
+
50
+ You can install qrforge using pip:
51
+
52
+ ```bash
53
+ pip install qrforge
54
+ ```
55
+
56
+ Or from source:
57
+
58
+ ```bash
59
+ pip install . # or copy the qrforge/ folder next to your code
60
+ pip install pillow # optional, only for non-PNG formats / PIL images
61
+ ```
62
+
63
+ ## Supported Python Versions
64
+
65
+ * Python 3.8 / 3.9 / 3.10 / 3.11 / 3.12 (or later)
66
+
67
+ ## Features
68
+
69
+ * **Correct encoder** – versions 1–40, EC levels L/M/Q/H, optimal numeric/alphanumeric/byte segmentation, automatic mask selection.
70
+ * **Shapes** – square, rounded, dot, diamond, hexagon, star, cross, squircle, leaf, heart etc. plus random-per-module mixes and your own SDF shapes.
71
+ * **Gradients & colours** – hex / `rgb()` / `hsl()` / CSS names; linear, radial and conic gradients for modules, eyes and background.
72
+ * **Shaders** – grain, glow, wave, twist, glitch, chromatic aberration, halftone, duotone, scanlines, vignette etc. plus custom Python or one-line expression shaders.
73
+ * **Logos & textures** – auto knockout zone, round/clip the logo, logo background, stroke, rotation, opacity; paint any image inside the modules.
74
+ * **Outputs** – PNG (pure-Python codec), SVG (tiny vector), PDF (vector), terminal ANSI, ASCII, Pillow, HTML.
75
+ * **22 ready-made presets** and a CLI.
76
+
77
+ ## Usage
78
+
79
+ ### Quickstart
80
+
81
+ ```python
82
+ import qrforge
83
+
84
+ qrforge.save("https://example.com", "code.png", "neon", scale=12)
85
+
86
+ qr = qrforge.QR("hello", ec="h")
87
+ qr.use_style(module_shape="dot", fg=["#ff0080", "#7928ca"], logo="logo.png")
88
+ qr.save("poster.png", scale=14)
89
+ qr.save("poster.svg")
90
+ print(qr.terminal())
91
+ ```
92
+
93
+ ### Colours & gradients
94
+
95
+ ```python
96
+ qr.use_style(fg=["#ff9a3c", "#ff4d6d", "#7b2ff7"]) # linear
97
+ qr.use_style(fg={"kind":"radial", "colors":["#fff","#1f6feb"]})
98
+ qr.use_style(fg={"kind":"conic", "colors":["#ff71ce","#01cdfe","#05ffa1"]})
99
+ ```
100
+
101
+ ### Shapes & eyes
102
+
103
+ ```python
104
+ qr.use_style(module_shape=["dot","star","hexagon"], seed=3, module_jitter=0.2,
105
+ eye_shape="rounded", eye_dot_shape="circle")
106
+
107
+ @qrforge.shape("wave") # register a custom shape (SDF in module units)
108
+ def wave(x, y, radius=0.0):
109
+ import math
110
+ return qrforge.shapes.sd_circle(x, y + 0.08*math.sin(x*9), 0.5)
111
+ ```
112
+
113
+ ### Shaders
114
+
115
+ ```python
116
+ qr.use_style(shaders=["wave:amplitude=4,wavelength=36", "chromatic:offset=2"])
117
+
118
+ @qrforge.shader # custom per-pixel shader
119
+ def heat(x, y, color, ctx):
120
+ return color.mix("#ff4400", ctx.uv(x, y)[1])
121
+ ```
122
+
123
+ ### Logos
124
+
125
+ ```python
126
+ qr.use_style(logo="logo.png", logo_size=0.26, logo_shape="rounded",
127
+ logo_radius=0.4, logo_bg="#ffffff", logo_stroke=("#000", 0.2),
128
+ logo_rotation=0, logo_opacity=1.0)
129
+ ```
130
+
131
+ ### Presets & overrides
132
+
133
+ Any preset's defaults (colours, shaders, etc.) can be overridden:
134
+
135
+ ```python
136
+ qrforge.save("hi", "out.png", "neon", fg="#00ff88", scale=12)
137
+ qrforge.presets.get("sunset", bg="#000000")
138
+ ```
139
+
140
+ Presets: `classic dots rounded soft confetti neon sunset blueprint brutal vapor
141
+ film halftone gold ice leaf circuit retro glitch minimal badge starry cross`.
142
+
143
+ ## Correctness
144
+
145
+ ```python
146
+ qr.verify() # decodes the symbol again
147
+ from qrforge.verify import decode
148
+ ```
149
+
150
+ ## CLI
151
+
152
+ ```bash
153
+ python -m qrforge "https://example.com" -o out.png -p neon -s 12 -e h
154
+ python -m qrforge "hi" --terminal
155
+ python -m qrforge --list-presets --list-shapes --list-shaders
156
+ ```
157
+
158
+ ## Testing
159
+
160
+ ```bash
161
+ python -m pytest tests -q
162
+ ```
163
+
164
+ The suite cross-checks the spec tables, Reed–Solomon correction, optimal
165
+ segmentation against a brute-force reference, the PNG codec against Pillow, and
166
+ re-rasterises every preset + the SVG geometry to prove each one still scans.
167
+
168
+ ## Contributing
169
+
170
+ Contributions are welcome! See [CONTRIBUTING.md](CONTRIBUTING.md). If you encounter any issues or have an edge use case, please open an issue using the templates in `.github/ISSUE_TEMPLATE`.
171
+
172
+ ## License
173
+
174
+ qrforge is released under the terms of the **MIT License (Modified)**. Please see the [LICENSE.md](LICENSE.md) file for the full text.
@@ -0,0 +1,140 @@
1
+ # qrforge
2
+ ![Python Version](https://img.shields.io/badge/python-3.8+-blue.svg)
3
+ ![License](https://img.shields.io/badge/license-MIT-brightgreen.svg)
4
+ ![Tests](https://img.shields.io/badge/tests-passing-brightgreen.svg)
5
+ ![Dependencies](https://img.shields.io/badge/dependencies-0%20(required)-blue.svg)
6
+
7
+ An open-source Python library for **generating and art-directing QR codes**: custom module shapes, gradients, shaders, logos, image textures, backgrounds and shadows — output to PNG, SVG, PDF, terminal ANSI, ASCII or Pillow.
8
+
9
+ *qrforge implements the full QR encoding pipeline (modes, Reed–Solomon error correction, masking, versions 1–40) from scratch against the standard library. There are **zero required dependencies**; [Pillow](https://pillow.readthedocs.io) is used only for non-PNG image formats, PIL images, or JPEG/GIF/WEBP logos. PNG reading/writing is built in.*
10
+
11
+ > [!NOTE]
12
+ > **qrforge** is intended to produce both *correct* and *beautiful* QR codes. Every rendered symbol is round-trip verified by a bundled decoder, and the test-suite re-rasterises the SVG geometry to prove it reproduces the matrix — so "pretty" never comes at the cost of "scannable".
13
+
14
+ ## Installation
15
+
16
+ You can install qrforge using pip:
17
+
18
+ ```bash
19
+ pip install qrforge
20
+ ```
21
+
22
+ Or from source:
23
+
24
+ ```bash
25
+ pip install . # or copy the qrforge/ folder next to your code
26
+ pip install pillow # optional, only for non-PNG formats / PIL images
27
+ ```
28
+
29
+ ## Supported Python Versions
30
+
31
+ * Python 3.8 / 3.9 / 3.10 / 3.11 / 3.12 (or later)
32
+
33
+ ## Features
34
+
35
+ * **Correct encoder** – versions 1–40, EC levels L/M/Q/H, optimal numeric/alphanumeric/byte segmentation, automatic mask selection.
36
+ * **Shapes** – square, rounded, dot, diamond, hexagon, star, cross, squircle, leaf, heart etc. plus random-per-module mixes and your own SDF shapes.
37
+ * **Gradients & colours** – hex / `rgb()` / `hsl()` / CSS names; linear, radial and conic gradients for modules, eyes and background.
38
+ * **Shaders** – grain, glow, wave, twist, glitch, chromatic aberration, halftone, duotone, scanlines, vignette etc. plus custom Python or one-line expression shaders.
39
+ * **Logos & textures** – auto knockout zone, round/clip the logo, logo background, stroke, rotation, opacity; paint any image inside the modules.
40
+ * **Outputs** – PNG (pure-Python codec), SVG (tiny vector), PDF (vector), terminal ANSI, ASCII, Pillow, HTML.
41
+ * **22 ready-made presets** and a CLI.
42
+
43
+ ## Usage
44
+
45
+ ### Quickstart
46
+
47
+ ```python
48
+ import qrforge
49
+
50
+ qrforge.save("https://example.com", "code.png", "neon", scale=12)
51
+
52
+ qr = qrforge.QR("hello", ec="h")
53
+ qr.use_style(module_shape="dot", fg=["#ff0080", "#7928ca"], logo="logo.png")
54
+ qr.save("poster.png", scale=14)
55
+ qr.save("poster.svg")
56
+ print(qr.terminal())
57
+ ```
58
+
59
+ ### Colours & gradients
60
+
61
+ ```python
62
+ qr.use_style(fg=["#ff9a3c", "#ff4d6d", "#7b2ff7"]) # linear
63
+ qr.use_style(fg={"kind":"radial", "colors":["#fff","#1f6feb"]})
64
+ qr.use_style(fg={"kind":"conic", "colors":["#ff71ce","#01cdfe","#05ffa1"]})
65
+ ```
66
+
67
+ ### Shapes & eyes
68
+
69
+ ```python
70
+ qr.use_style(module_shape=["dot","star","hexagon"], seed=3, module_jitter=0.2,
71
+ eye_shape="rounded", eye_dot_shape="circle")
72
+
73
+ @qrforge.shape("wave") # register a custom shape (SDF in module units)
74
+ def wave(x, y, radius=0.0):
75
+ import math
76
+ return qrforge.shapes.sd_circle(x, y + 0.08*math.sin(x*9), 0.5)
77
+ ```
78
+
79
+ ### Shaders
80
+
81
+ ```python
82
+ qr.use_style(shaders=["wave:amplitude=4,wavelength=36", "chromatic:offset=2"])
83
+
84
+ @qrforge.shader # custom per-pixel shader
85
+ def heat(x, y, color, ctx):
86
+ return color.mix("#ff4400", ctx.uv(x, y)[1])
87
+ ```
88
+
89
+ ### Logos
90
+
91
+ ```python
92
+ qr.use_style(logo="logo.png", logo_size=0.26, logo_shape="rounded",
93
+ logo_radius=0.4, logo_bg="#ffffff", logo_stroke=("#000", 0.2),
94
+ logo_rotation=0, logo_opacity=1.0)
95
+ ```
96
+
97
+ ### Presets & overrides
98
+
99
+ Any preset's defaults (colours, shaders, etc.) can be overridden:
100
+
101
+ ```python
102
+ qrforge.save("hi", "out.png", "neon", fg="#00ff88", scale=12)
103
+ qrforge.presets.get("sunset", bg="#000000")
104
+ ```
105
+
106
+ Presets: `classic dots rounded soft confetti neon sunset blueprint brutal vapor
107
+ film halftone gold ice leaf circuit retro glitch minimal badge starry cross`.
108
+
109
+ ## Correctness
110
+
111
+ ```python
112
+ qr.verify() # decodes the symbol again
113
+ from qrforge.verify import decode
114
+ ```
115
+
116
+ ## CLI
117
+
118
+ ```bash
119
+ python -m qrforge "https://example.com" -o out.png -p neon -s 12 -e h
120
+ python -m qrforge "hi" --terminal
121
+ python -m qrforge --list-presets --list-shapes --list-shaders
122
+ ```
123
+
124
+ ## Testing
125
+
126
+ ```bash
127
+ python -m pytest tests -q
128
+ ```
129
+
130
+ The suite cross-checks the spec tables, Reed–Solomon correction, optimal
131
+ segmentation against a brute-force reference, the PNG codec against Pillow, and
132
+ re-rasterises every preset + the SVG geometry to prove each one still scans.
133
+
134
+ ## Contributing
135
+
136
+ Contributions are welcome! See [CONTRIBUTING.md](CONTRIBUTING.md). If you encounter any issues or have an edge use case, please open an issue using the templates in `.github/ISSUE_TEMPLATE`.
137
+
138
+ ## License
139
+
140
+ qrforge is released under the terms of the **MIT License (Modified)**. Please see the [LICENSE.md](LICENSE.md) file for the full text.
@@ -0,0 +1,13 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ # Metadata lives in setup.py (the publish workflow seds the version token there),
6
+ # so this file only declares the build backend and tool configuration.
7
+
8
+ [tool.pytest.ini_options]
9
+ testpaths = ["tests"]
10
+ addopts = "-q"
11
+
12
+ [tool.setuptools]
13
+ # packages are discovered by setup.py via find_packages()
@@ -0,0 +1,51 @@
1
+ """qrforge -- generate and style QR codes with no dependencies.
2
+
3
+ import qrforge
4
+
5
+ qrforge.save("https://example.com", "hello.png", "neon", scale=12)
6
+
7
+ qr = qrforge.QR("hello", ec="h")
8
+ qr.use_style(module_shape="dot", fg=["#ff0080", "#7928ca"], logo="logo.png")
9
+ qr.save("hello.svg")
10
+
11
+ Everything (encoding, Reed-Solomon, rasterisation, the PNG codec) is written in
12
+ pure Python against the standard library. Pillow is used only when you ask for
13
+ a non-PNG format, a PIL image, or a non-PNG logo.
14
+ """
15
+
16
+ from .api import Artwork, QR, QRCode, make, png, save, svg, terminal
17
+ from .color import Color
18
+ from .exceptions import DataTooLong, QRForgeError, StyleError, UnsupportedFeature
19
+ from .gradient import Gradient, SolidFill
20
+ from .image import Pixmap
21
+ from .matrix import QRMatrix, build as build_matrix
22
+ from .shaders import Shader, expression, shader
23
+ from .shapes import Shape, custom as shape, register as register_shape
24
+ from .style import Style
25
+
26
+ __version__ = "1.0.0"
27
+
28
+ __all__ = [
29
+ "QR", "QRCode", "Artwork", "make", "save", "svg", "png", "terminal",
30
+ "Style", "Color", "Gradient", "SolidFill", "Pixmap", "QRMatrix", "build_matrix",
31
+ "Shader", "shader", "expression", "Shape", "shape", "register_shape",
32
+ "presets", "shapes", "shaders", "verify",
33
+ "QRForgeError", "DataTooLong", "StyleError", "UnsupportedFeature",
34
+ "__version__",
35
+ ]
36
+
37
+
38
+ def __getattr__(name):
39
+ """Lazily expose the heavier submodules (``qrforge.presets`` etc.)."""
40
+ if name in ("presets", "shapes", "shaders", "verify", "matrix", "encoder", "tables", "gf"):
41
+ from importlib import import_module
42
+ module = import_module(f".{name}", __name__)
43
+ globals()[name] = module
44
+ return module
45
+ raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
46
+
47
+
48
+ def preset(name: str) -> Style:
49
+ """Shortcut for ``qrforge.presets.get(name)``."""
50
+ from .presets import get
51
+ return get(name)
@@ -0,0 +1,6 @@
1
+ """Enable ``python -m qrforge``."""
2
+
3
+ from .cli import main
4
+
5
+ if __name__ == "__main__":
6
+ raise SystemExit(main())