[Draft/RFC] Experimental Micro QR Code support (M2-M4 numeric)#426
Draft
nssmd wants to merge 1 commit into
Draft
[Draft/RFC] Experimental Micro QR Code support (M2-M4 numeric)#426nssmd wants to merge 1 commit into
nssmd wants to merge 1 commit into
Conversation
Adds a new module `qrcode.micro` providing experimental Micro QR Code
support per ISO/IEC 18004:2006 Annex F. The first iteration covers
the most common subset:
- Versions M2, M3, M4
- Numeric mode end-to-end
- Error-correction levels L and M (plus Q on M4)
- 0/1 matrix and ASCII rendering (image factories TBD)
Implementation
--------------
* Reuses the existing GF(256) arithmetic and `Polynomial` class from
`qrcode.base` for Reed-Solomon parity computation.
* Implements format-info BCH(15,5) with the Micro-QR generator
(G(x) = x^10+x^4+x^3+x^2+x+1, mask 0x4445) — distinct from the
full-QR BCH used elsewhere in the library.
* Implements the four Micro-QR mask patterns from Annex F.4 and the
Annex F.5 mask-evaluation score.
* Auto-version selection: smallest M2/M3/M4 that fits the payload
for the requested ECC level.
Verification
------------
13 round-trip tests (`qrcode/tests/test_micro.py`) generate a symbol,
render it as a PIL image, and decode it back through `zxing-cpp`,
which natively supports Micro QR. All five payload sizes covering
M2/M3/M4 round-trip identically. `zxing-cpp` is gated with
`pytest.importorskip` so the tests are skipped on CI runners that
don't have it installed.
Public API
----------
from qrcode.micro import MicroQRCode, MICRO_ECC_L
mqr = MicroQRCode("01234567", error_correction=MICRO_ECC_L)
print(mqr.to_ascii())
matrix = mqr.matrix # list[list[int]] of 0/1
Status: EXPERIMENTAL
--------------------
The module is intentionally side-by-side with `qrcode.QRCode` rather
than altering it, so we can iterate on the API in `qrcode.micro`
without affecting the stable codepath. Follow-ups before promoting:
- M1 (3-bit CCI, no mode indicator, 4-bit terminator)
- Alphanumeric and byte modes
- PIL / SVG image factories (currently ASCII / matrix only)
- Additional spec-vector tests against ISO/IEC 18004 Annex F figures
This PR is opened as a Draft / RFC: happy to split, scope down, or
land behind a `qrcode.experimental` namespace per maintainer
preference.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
[Draft / RFC] Experimental Micro QR Code support (M2-M4 numeric)
What this adds
A new module
qrcode.microthat encodes data as a Micro QR Codeper ISO/IEC 18004:2006 Annex F. The first iteration covers the
practically-most-useful subset:
matrix(list of int) andto_ascii()Why side-by-side, not bolted onto
QRCodeMicro QR has structurally different module placement, format-info
encoding, mask functions, and capacity tables than full QR. Forcing
those branches into
QRCodewould introduce manyif micro: ... else:arms in code that today is straight-line. Instead this PR introduces a
sibling class
MicroQRCodein a separate module, reusingqrcode.basefor the GF(256) arithmetic and Reed-Solomon polynomial machinery.
If you'd prefer a factory entry point on
QRCode, that's a smallfollow-up — the implementation here doesn't preclude it.
Verification
13 unit tests generate symbols, render to PIL, and round-trip through
zxing-cppwhich nativelysupports Micro QR. Every variant tested decodes back to the original
payload byte-for-byte:
Tests are gated with
pytest.importorskip("zxingcpp")so CI runnerswithout the optional dependency simply skip them.
Implementation notes
EXP_TABLE,LOG_TABLE,gexp,glog, and thePolynomialclass fromqrcode.base. No duplicated arithmetic.generator
G(x) = x^10 + x^4 + x^3 + x^2 + x + 1(= 0x537) andmask
0x4445(Annex F.5). This is different from the full-QRBCH used by
BCH_type_info— they are not interchangeable.Table F.4 and the Annex F.5 mask-selection score.
_best_fit()picks the smallest M2/M3/M4whose data capacity (after mode indicator + character count
indicator + terminator) fits the payload. Raises
ValueErrorwith
"capacity"in the message on overflow — distinct fromDataOverflowErrorto avoid implying full-QR semantics.Backward compatibility
Zero. New module, new class, new tests. Touches no existing public
API. Optional
zxing-cpptest dependency is not added topyproject.toml— it's only used when present.What's not in this PR
Intentionally out of scope, queued as follow-ups:
factory_kind="micro"entry on the existingqrcode.make/QRCodeif the maintainers prefer one entry point.Why this is a Draft / RFC
I'd like maintainer feedback before expanding scope. Specifically:
qrcode.microthe right placement, or should this live underqrcode.experimental.micro(or similar) until promoted?MicroQRCode(data, version, error_correction)vs.reusing
QRCodewith aformat=flag. I picked the former becausethe symbology really is different; happy to refactor.
zxing-cppfor tests: optional dependency vs. a dependency-freereference checker (the round-trip is the convincing test, but
committing a fixture-based byte-level check against ISO Annex F
examples is also feasible).
Discovered & built by the python-qrcode testing study group as part
of the same engagement that produced the bug-fix PR (#425). The
Micro QR work was driven by user demand — a few payloads in the
test corpus are short enough that M2/M3 would yield substantially
smaller symbols than v1 full-QR.