hexatess-code 0.1.0__tar.gz → 0.2.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.
- {hexatess_code-0.1.0 → hexatess_code-0.2.0}/LICENSE +1 -1
- {hexatess_code-0.1.0 → hexatess_code-0.2.0}/PKG-INFO +9 -4
- {hexatess_code-0.1.0 → hexatess_code-0.2.0}/README.md +7 -2
- {hexatess_code-0.1.0 → hexatess_code-0.2.0}/pyproject.toml +1 -1
- {hexatess_code-0.1.0 → hexatess_code-0.2.0}/src/hexatess/__init__.py +4 -4
- {hexatess_code-0.1.0 → hexatess_code-0.2.0}/src/hexatess/cli.py +2 -2
- {hexatess_code-0.1.0 → hexatess_code-0.2.0}/src/hexatess/decoder.py +1 -1
- {hexatess_code-0.1.0 → hexatess_code-0.2.0}/src/hexatess/encoder.py +6 -4
- {hexatess_code-0.1.0 → hexatess_code-0.2.0}/src/hexatess/header.py +1 -1
- {hexatess_code-0.1.0 → hexatess_code-0.2.0}/src/hexatess_code.egg-info/PKG-INFO +9 -4
- {hexatess_code-0.1.0 → hexatess_code-0.2.0}/tests/test_codec.py +1 -1
- {hexatess_code-0.1.0 → hexatess_code-0.2.0}/tests/test_conformance.py +1 -1
- {hexatess_code-0.1.0 → hexatess_code-0.2.0}/setup.cfg +0 -0
- {hexatess_code-0.1.0 → hexatess_code-0.2.0}/src/hexatess/galois.py +0 -0
- {hexatess_code-0.1.0 → hexatess_code-0.2.0}/src/hexatess/geometry.py +0 -0
- {hexatess_code-0.1.0 → hexatess_code-0.2.0}/src/hexatess/masks.py +0 -0
- {hexatess_code-0.1.0 → hexatess_code-0.2.0}/src/hexatess/reedsolomon.py +0 -0
- {hexatess_code-0.1.0 → hexatess_code-0.2.0}/src/hexatess/render.py +0 -0
- {hexatess_code-0.1.0 → hexatess_code-0.2.0}/src/hexatess/resilience.py +0 -0
- {hexatess_code-0.1.0 → hexatess_code-0.2.0}/src/hexatess_code.egg-info/SOURCES.txt +0 -0
- {hexatess_code-0.1.0 → hexatess_code-0.2.0}/src/hexatess_code.egg-info/dependency_links.txt +0 -0
- {hexatess_code-0.1.0 → hexatess_code-0.2.0}/src/hexatess_code.egg-info/entry_points.txt +0 -0
- {hexatess_code-0.1.0 → hexatess_code-0.2.0}/src/hexatess_code.egg-info/requires.txt +0 -0
- {hexatess_code-0.1.0 → hexatess_code-0.2.0}/src/hexatess_code.egg-info/top_level.txt +0 -0
- {hexatess_code-0.1.0 → hexatess_code-0.2.0}/tests/test_galois.py +0 -0
- {hexatess_code-0.1.0 → hexatess_code-0.2.0}/tests/test_geometry.py +0 -0
- {hexatess_code-0.1.0 → hexatess_code-0.2.0}/tests/test_header.py +0 -0
- {hexatess_code-0.1.0 → hexatess_code-0.2.0}/tests/test_masks.py +0 -0
- {hexatess_code-0.1.0 → hexatess_code-0.2.0}/tests/test_reedsolomon.py +0 -0
- {hexatess_code-0.1.0 → hexatess_code-0.2.0}/tests/test_render.py +0 -0
- {hexatess_code-0.1.0 → hexatess_code-0.2.0}/tests/test_resilience.py +0 -0
|
@@ -27,4 +27,4 @@ The format specification (SPECIFICATION.md) is additionally released under
|
|
|
27
27
|
the Creative Commons Attribution 4.0 International license (CC-BY-4.0), so
|
|
28
28
|
that anyone may implement compatible encoders/decoders in any language,
|
|
29
29
|
under any license, without restriction. Provide attribution as:
|
|
30
|
-
"Hexatess Code Specification v0.
|
|
30
|
+
"Hexatess Code Specification v0.2, https://github.com/<you>/hexatess-code".
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: hexatess-code
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: Hexatess Code - an experimental 2D barcode on a hexagonal grid with Reed-Solomon error correction
|
|
5
5
|
Author: The Hexatess Code Authors
|
|
6
6
|
License: MIT License
|
|
@@ -32,7 +32,7 @@ License: MIT License
|
|
|
32
32
|
the Creative Commons Attribution 4.0 International license (CC-BY-4.0), so
|
|
33
33
|
that anyone may implement compatible encoders/decoders in any language,
|
|
34
34
|
under any license, without restriction. Provide attribution as:
|
|
35
|
-
"Hexatess Code Specification v0.
|
|
35
|
+
"Hexatess Code Specification v0.2, https://github.com/<you>/hexatess-code".
|
|
36
36
|
|
|
37
37
|
Project-URL: Homepage, https://github.com/lovro-abram/hexatess-code
|
|
38
38
|
Project-URL: Specification, https://github.com/lovro-abram/hexatess-code/blob/main/SPECIFICATION.md
|
|
@@ -59,6 +59,11 @@ Requires-Dist: pytest>=7.0; extra == "dev"
|
|
|
59
59
|
Dynamic: license-file
|
|
60
60
|
|
|
61
61
|
# Hexatess Code 🐝
|
|
62
|
+
[](https://pypi.org/project/hexatess-code/)
|
|
63
|
+
|
|
64
|
+
[](https://pypi.org/project/hexatess-code/)
|
|
65
|
+
|
|
66
|
+
[](https://github.com/lovro-abram/hexatess-code/actions/workflows/ci.yml)
|
|
62
67
|
|
|
63
68
|
**An experimental 2D barcode on a hexagonal grid** — with a hexagonal
|
|
64
69
|
bullseye finder, spiral serialization and a continuously selectable
|
|
@@ -81,7 +86,7 @@ text, stats = decode(grid) # ('Hello, Hexatess!', {...})
|
|
|
81
86
|
* **A** — a real encoded symbol: hexagonal bullseye finder (rings 0–4),
|
|
82
87
|
orientation key (ring 5: two dark cells), data region (rings 6…)
|
|
83
88
|
filled in spiral order, and a quiet zone of at least 1 module;
|
|
84
|
-
* **B** — finder close-up:
|
|
89
|
+
* **B** — finder close-up: dark centre (rule `bit = 1 − ring mod 2`),
|
|
85
90
|
alternating dark/light rings, and the key — the first two canonical
|
|
86
91
|
ring-5 cells set dark, breaking the 60-fold symmetry and marking the
|
|
87
92
|
spiral start direction;
|
|
@@ -162,7 +167,7 @@ concentrate inside whole bytes.
|
|
|
162
167
|
The format is deliberately **specification-first**: everything needed
|
|
163
168
|
for an independent implementation is in
|
|
164
169
|
[`SPECIFICATION.md`](SPECIFICATION.md), and
|
|
165
|
-
[`test_vectors/vectors_v0.
|
|
170
|
+
[`test_vectors/vectors_v0.2.json`](test_vectors/vectors_v0.2.json)
|
|
166
171
|
contains fixed inputs/outputs (grids, headers, damaged symbols, expected
|
|
167
172
|
results) to verify conformance. If your Rust/Go/JS decoder passes the
|
|
168
173
|
vectors, it speaks Hexatess Code.
|
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
# Hexatess Code 🐝
|
|
2
|
+
[](https://pypi.org/project/hexatess-code/)
|
|
3
|
+
|
|
4
|
+
[](https://pypi.org/project/hexatess-code/)
|
|
5
|
+
|
|
6
|
+
[](https://github.com/lovro-abram/hexatess-code/actions/workflows/ci.yml)
|
|
2
7
|
|
|
3
8
|
**An experimental 2D barcode on a hexagonal grid** — with a hexagonal
|
|
4
9
|
bullseye finder, spiral serialization and a continuously selectable
|
|
@@ -21,7 +26,7 @@ text, stats = decode(grid) # ('Hello, Hexatess!', {...})
|
|
|
21
26
|
* **A** — a real encoded symbol: hexagonal bullseye finder (rings 0–4),
|
|
22
27
|
orientation key (ring 5: two dark cells), data region (rings 6…)
|
|
23
28
|
filled in spiral order, and a quiet zone of at least 1 module;
|
|
24
|
-
* **B** — finder close-up:
|
|
29
|
+
* **B** — finder close-up: dark centre (rule `bit = 1 − ring mod 2`),
|
|
25
30
|
alternating dark/light rings, and the key — the first two canonical
|
|
26
31
|
ring-5 cells set dark, breaking the 60-fold symmetry and marking the
|
|
27
32
|
spiral start direction;
|
|
@@ -102,7 +107,7 @@ concentrate inside whole bytes.
|
|
|
102
107
|
The format is deliberately **specification-first**: everything needed
|
|
103
108
|
for an independent implementation is in
|
|
104
109
|
[`SPECIFICATION.md`](SPECIFICATION.md), and
|
|
105
|
-
[`test_vectors/vectors_v0.
|
|
110
|
+
[`test_vectors/vectors_v0.2.json`](test_vectors/vectors_v0.2.json)
|
|
106
111
|
contains fixed inputs/outputs (grids, headers, damaged symbols, expected
|
|
107
112
|
results) to verify conformance. If your Rust/Go/JS decoder passes the
|
|
108
113
|
vectors, it speaks Hexatess Code.
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "hexatess-code"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.2.0"
|
|
8
8
|
description = "Hexatess Code - an experimental 2D barcode on a hexagonal grid with Reed-Solomon error correction"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.8"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""Hexatess Code - an experimental 2D barcode on a hexagonal grid.
|
|
2
2
|
|
|
3
|
-
Reference implementation of specification v0.
|
|
3
|
+
Reference implementation of specification v0.2. The symbol is a
|
|
4
4
|
hexagonal lattice with a hexagonal bullseye finder, an
|
|
5
5
|
orientation key ring, spiral serialization from the centre outwards,
|
|
6
6
|
a Reed-Solomon protected header and a continuously selectable
|
|
@@ -18,7 +18,7 @@ Quick start
|
|
|
18
18
|
'Hello, Hexatess!'
|
|
19
19
|
|
|
20
20
|
See SPECIFICATION.md in the repository for the full format
|
|
21
|
-
specification, and test_vectors/vectors_v0.
|
|
21
|
+
specification, and test_vectors/vectors_v0.2.json for conformance
|
|
22
22
|
data usable by independent implementations.
|
|
23
23
|
"""
|
|
24
24
|
|
|
@@ -57,8 +57,8 @@ from .reedsolomon import rs_correct_msg, rs_encode_msg
|
|
|
57
57
|
from .render import render, sample_grid_from_image
|
|
58
58
|
from .resilience import add_blob_damage, add_random_noise, run_tests
|
|
59
59
|
|
|
60
|
-
__version__ = "0.
|
|
61
|
-
SPEC_VERSION = "0.
|
|
60
|
+
__version__ = "0.2.0"
|
|
61
|
+
SPEC_VERSION = "0.2"
|
|
62
62
|
|
|
63
63
|
__all__ = [
|
|
64
64
|
# high-level API
|
|
@@ -25,7 +25,7 @@ def main(argv=None):
|
|
|
25
25
|
ap = argparse.ArgumentParser(
|
|
26
26
|
prog="hexatess",
|
|
27
27
|
description="Hexatess Code - hexagonal-grid 2D barcode "
|
|
28
|
-
"(reference implementation, spec v0.
|
|
28
|
+
"(reference implementation, spec v0.2)")
|
|
29
29
|
ap.add_argument("text", nargs="?", help="text to encode (UTF-8)")
|
|
30
30
|
ap.add_argument("-o", "--output", default="hexatess.png",
|
|
31
31
|
help="output PNG path (default: %(default)s)")
|
|
@@ -46,7 +46,7 @@ def main(argv=None):
|
|
|
46
46
|
run_tests()
|
|
47
47
|
|
|
48
48
|
if args.demo or args.text:
|
|
49
|
-
text = args.text or "Hexatess Code v0.
|
|
49
|
+
text = args.text or "Hexatess Code v0.2 - " * 6
|
|
50
50
|
grid, params = encode(text, ec_pct=args.ec, mask_id="auto"
|
|
51
51
|
if args.mask is None else args.mask)
|
|
52
52
|
render(grid, args.output, size_px=args.size)
|
|
@@ -2,10 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
Turns UTF-8 text into a hexagonal module grid ``{(q, r): 0|1}``.
|
|
4
4
|
|
|
5
|
-
Layout summary (specification v0.
|
|
5
|
+
Layout summary (specification v0.2):
|
|
6
6
|
|
|
7
7
|
* rings 0..4 -- hexagonal bullseye finder, ring ``k`` filled with
|
|
8
|
-
``k mod 2`` (bit 1 = dark module; the centre module is
|
|
8
|
+
``1 - (k mod 2)`` (bit 1 = dark module; the centre module is DARK
|
|
9
|
+
since spec v0.2);
|
|
9
10
|
* ring 5 -- orientation key: all modules light except the first two
|
|
10
11
|
cells of ``hex_ring(5)`` (``(-5, 5)`` and ``(-4, 5)``) which are dark;
|
|
11
12
|
* rings 6..rmax -- payload bits in spiral order: header (80 bits,
|
|
@@ -62,7 +63,8 @@ def encode(text: str, ec_pct: int = 30, mask_id="auto", min_rings=None):
|
|
|
62
63
|
data = text.encode("utf-8")
|
|
63
64
|
if len(data) > MAX_DATA_BYTES:
|
|
64
65
|
raise ValueError(
|
|
65
|
-
"
|
|
66
|
+
"the radius limit supports up to %d bytes of data"
|
|
67
|
+
% MAX_DATA_BYTES)
|
|
66
68
|
blocks = plan_blocks(len(data), ec_pct)
|
|
67
69
|
ecc_total = sum(e for _, e in blocks)
|
|
68
70
|
need_bits = MODE_BITS + (len(data) + ecc_total) * 8
|
|
@@ -110,7 +112,7 @@ def encode(text: str, ec_pct: int = 30, mask_id="auto", min_rings=None):
|
|
|
110
112
|
grid = {}
|
|
111
113
|
for k in range(BULLSEYE_RINGS + 1):
|
|
112
114
|
for c in hex_ring(k):
|
|
113
|
-
grid[c] = k % 2
|
|
115
|
+
grid[c] = 1 - (k % 2) # centre DARK (v0.2), rings alternate
|
|
114
116
|
for c in hex_ring(KEY_RING):
|
|
115
117
|
grid[c] = 0
|
|
116
118
|
key = hex_ring(KEY_RING)
|
|
@@ -7,7 +7,7 @@ import math
|
|
|
7
7
|
from .reedsolomon import rs_encode_msg, rs_correct_msg
|
|
8
8
|
|
|
9
9
|
# ----------------------------------------------------------------------
|
|
10
|
-
# Symbol constants (fixed in specification v0.
|
|
10
|
+
# Symbol constants (fixed in specification v0.2)
|
|
11
11
|
# ----------------------------------------------------------------------
|
|
12
12
|
|
|
13
13
|
BULLSEYE_RINGS = 4 # rings 0..4 form the hexagonal bullseye finder
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: hexatess-code
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: Hexatess Code - an experimental 2D barcode on a hexagonal grid with Reed-Solomon error correction
|
|
5
5
|
Author: The Hexatess Code Authors
|
|
6
6
|
License: MIT License
|
|
@@ -32,7 +32,7 @@ License: MIT License
|
|
|
32
32
|
the Creative Commons Attribution 4.0 International license (CC-BY-4.0), so
|
|
33
33
|
that anyone may implement compatible encoders/decoders in any language,
|
|
34
34
|
under any license, without restriction. Provide attribution as:
|
|
35
|
-
"Hexatess Code Specification v0.
|
|
35
|
+
"Hexatess Code Specification v0.2, https://github.com/<you>/hexatess-code".
|
|
36
36
|
|
|
37
37
|
Project-URL: Homepage, https://github.com/lovro-abram/hexatess-code
|
|
38
38
|
Project-URL: Specification, https://github.com/lovro-abram/hexatess-code/blob/main/SPECIFICATION.md
|
|
@@ -59,6 +59,11 @@ Requires-Dist: pytest>=7.0; extra == "dev"
|
|
|
59
59
|
Dynamic: license-file
|
|
60
60
|
|
|
61
61
|
# Hexatess Code 🐝
|
|
62
|
+
[](https://pypi.org/project/hexatess-code/)
|
|
63
|
+
|
|
64
|
+
[](https://pypi.org/project/hexatess-code/)
|
|
65
|
+
|
|
66
|
+
[](https://github.com/lovro-abram/hexatess-code/actions/workflows/ci.yml)
|
|
62
67
|
|
|
63
68
|
**An experimental 2D barcode on a hexagonal grid** — with a hexagonal
|
|
64
69
|
bullseye finder, spiral serialization and a continuously selectable
|
|
@@ -81,7 +86,7 @@ text, stats = decode(grid) # ('Hello, Hexatess!', {...})
|
|
|
81
86
|
* **A** — a real encoded symbol: hexagonal bullseye finder (rings 0–4),
|
|
82
87
|
orientation key (ring 5: two dark cells), data region (rings 6…)
|
|
83
88
|
filled in spiral order, and a quiet zone of at least 1 module;
|
|
84
|
-
* **B** — finder close-up:
|
|
89
|
+
* **B** — finder close-up: dark centre (rule `bit = 1 − ring mod 2`),
|
|
85
90
|
alternating dark/light rings, and the key — the first two canonical
|
|
86
91
|
ring-5 cells set dark, breaking the 60-fold symmetry and marking the
|
|
87
92
|
spiral start direction;
|
|
@@ -162,7 +167,7 @@ concentrate inside whole bytes.
|
|
|
162
167
|
The format is deliberately **specification-first**: everything needed
|
|
163
168
|
for an independent implementation is in
|
|
164
169
|
[`SPECIFICATION.md`](SPECIFICATION.md), and
|
|
165
|
-
[`test_vectors/vectors_v0.
|
|
170
|
+
[`test_vectors/vectors_v0.2.json`](test_vectors/vectors_v0.2.json)
|
|
166
171
|
contains fixed inputs/outputs (grids, headers, damaged symbols, expected
|
|
167
172
|
results) to verify conformance. If your Rust/Go/JS decoder passes the
|
|
168
173
|
vectors, it speaks Hexatess Code.
|
|
@@ -67,7 +67,7 @@ def test_bullseye_pattern():
|
|
|
67
67
|
grid, params = encode("bullseye", ec_pct=30)
|
|
68
68
|
for k in range(BULLSEYE_RINGS + 1):
|
|
69
69
|
for c in hex_ring(k):
|
|
70
|
-
assert grid[c] == k % 2
|
|
70
|
+
assert grid[c] == 1 - (k % 2) # centre DARK (spec v0.2)
|
|
71
71
|
key = hex_ring(KEY_RING)
|
|
72
72
|
for c in key[2:]:
|
|
73
73
|
assert grid[c] == 0
|
|
@@ -16,7 +16,7 @@ from test_vectors.generate_vectors import grid_from_hex
|
|
|
16
16
|
|
|
17
17
|
HERE = os.path.dirname(os.path.abspath(__file__))
|
|
18
18
|
ROOT = os.path.dirname(HERE)
|
|
19
|
-
VECTOR_FILE = os.path.join(ROOT, "test_vectors", "vectors_v0.
|
|
19
|
+
VECTOR_FILE = os.path.join(ROOT, "test_vectors", "vectors_v0.2.json")
|
|
20
20
|
|
|
21
21
|
with open(VECTOR_FILE, "r", encoding="utf-8") as fh:
|
|
22
22
|
VECTORS = json.load(fh)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|