#!/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' ' for name in names)
return (
"\n"
f"\n{rows}\n\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())