aboutsummaryrefslogtreecommitdiff
path: root/tools/gen_pdf417_tables.py
diff options
context:
space:
mode:
Diffstat (limited to 'tools/gen_pdf417_tables.py')
-rw-r--r--tools/gen_pdf417_tables.py77
1 files changed, 77 insertions, 0 deletions
diff --git a/tools/gen_pdf417_tables.py b/tools/gen_pdf417_tables.py
new file mode 100644
index 0000000..7a66677
--- /dev/null
+++ b/tools/gen_pdf417_tables.py
@@ -0,0 +1,77 @@
+#!/usr/bin/env python3
+# Author: cirakg & claude ai
+# Summary: Generate the PDF417 table resources (patterns, EC factors, text table) from pdf417gen's published tables.
+"""PDF417 tables for the watch (ISO/IEC 15438), taken from pdf417gen so the
+2,787 bar patterns aren't typed by hand. Five JSON resources (the compiler
+warns about resources over 8 KB):
+
+- codes0, codes1, codes2: the 17-module pattern of every codeword (0-928)
+ in clusters 0, 3 and 6
+- ec: the Reed-Solomon factors (mod 929) for levels 0-8
+- text: per text-compaction submode (upper, lower, mixed, punctuation), the
+ value of ASCII 0-126 in that submode, or -1
+
+The app loads them only while it encodes a PDF417 code.
+
+ gen_pdf417_tables.py [--out-dir resources/pdf417]
+"""
+
+from __future__ import annotations
+
+import argparse
+import json
+from pathlib import Path
+
+from pdf417gen import codes, data
+
+SUBMODES = [data.UPPER, data.LOWER, data.MIXED, data.PUNCT]
+
+
+HEADER = {"_author": "cirakg & claude ai"}
+
+
+def tables() -> dict[str, object]:
+ """Resource name -> JSON content."""
+ text = [[data.CHARACTERS_LOOKUP.get(c, {}).get(mode, -1) for c in range(127)] for mode in SUBMODES]
+ out: dict[str, object] = {}
+ for k in range(3):
+ out[f"codes{k}"] = {
+ **HEADER,
+ "_summary": f"PDF417 cluster {3 * k} patterns (generated; do not edit).",
+ "v": list(codes.CODES[k]),
+ }
+ out["ec"] = {
+ **HEADER,
+ "_summary": "PDF417 EC factors per level (generated; do not edit).",
+ "v": [list(f) for f in data.ERROR_CORRECTION_FACTORS],
+ }
+ out["text"] = {**HEADER, "_summary": "PDF417 text submode values (generated; do not edit).", "v": text}
+ return out
+
+
+def resources_xml(names: list[str]) -> str:
+ rows = "\n".join(f' <jsonData id="Pdf417{name.capitalize()}" filename="{name}.json" />' for name in names)
+ return (
+ "<!--\n Author: cirakg & claude ai\n"
+ " Summary: The PDF417 tables as JSON resources, loaded only while a PDF417 code is encoded (generated).\n-->\n"
+ f"<resources>\n{rows}\n</resources>\n"
+ )
+
+
+def main(argv: list[str] | None = None) -> int:
+ parser = argparse.ArgumentParser(description=__doc__.splitlines()[0])
+ parser.add_argument("--out-dir", type=Path, default=Path("resources/pdf417"))
+ args = parser.parse_args(argv)
+ args.out_dir.mkdir(parents=True, exist_ok=True)
+ for old in args.out_dir.glob("*.json"):
+ old.unlink()
+ content = tables()
+ for name, value in content.items():
+ (args.out_dir / f"{name}.json").write_text(json.dumps(value, separators=(",", ":")) + "\n", encoding="utf-8")
+ (args.out_dir / "pdf417.xml").write_text(resources_xml(list(content)), encoding="utf-8")
+ print(f"wrote {len(content)} PDF417 table resources to {args.out_dir}")
+ return 0
+
+
+if __name__ == "__main__":
+ raise SystemExit(main())