|
| 1 | +`codext` can generate and read matrix barcodes. The `aztec` and `qr` codecs produce real, scannable Aztec and QR codes (with Reed-Solomon error correction), while `fakeqr` only mimics the aspect of a QR code, hiding the input in an image that is not a valid one. |
| 2 | + |
| 3 | +----- |
| 4 | + |
| 5 | +### Aztec Code |
| 6 | + |
| 7 | +This encodes the input as a real (standard, scannable) [Aztec code](https://en.wikipedia.org/wiki/Aztec_Code) (ISO/IEC 24778), a 2D matrix barcode with a central bulls-eye finder pattern and the data spiralling around it. It uses the optimal high-level compaction (upper, lower, mixed, punctuation and digit modes plus binary shift), selects the smallest symbol (compact 1 to 4 layers, then full 1 to 32 layers) that fits the data for the chosen error correction percentage (given in the codec name, 23% by default) and adds the Reed-Solomon error correction. Decoding recovers the size, layer count and error correction from the mode message and applies Reed-Solomon error correction, so that a damaged code can still be decoded ; it handles all the compaction modes, so that Aztec codes generated by other tools can be read. Like the other barcodes, the output is a grayscale PNG image by default, or plain text with the `-text` variant. |
| 8 | + |
| 9 | +**Codec** | **Conversions** | **Aliases** | **Comment** |
| 10 | +:---: | :---: | --- | --- |
| 11 | +`aztec` | text <-> Aztec code (image or text) | `aztec-N` (*N* being the error correction percentage), `aztec-text`, `aztec-N-text` | 23% by default ; the symbol size is chosen automatically |
| 12 | + |
| 13 | +```python |
| 14 | +>>> png = codext.encode(b"codext", "aztec") |
| 15 | +>>> png[:8] |
| 16 | +b'\x89PNG\r\n\x1a\n' |
| 17 | +>>> codext.decode(png, "aztec") |
| 18 | +b'codext' |
| 19 | +>>> print(codext.encode("Az", "aztec-text")) |
| 20 | + ███████ █ |
| 21 | + ██ █ █ |
| 22 | + ███ █ ███ |
| 23 | + ████████████ █ |
| 24 | +██ █ █ █ |
| 25 | + ██ █████ █ ██ |
| 26 | +██ █ █ █ ██ |
| 27 | + █ █ █ █ █ █ █ |
| 28 | +██ █ █ █ ████ |
| 29 | +██ █ █████ ████ |
| 30 | + ███ █ |
| 31 | +█ ████████████ |
| 32 | + ██ ██ |
| 33 | +█ █ ███ █ |
| 34 | +█ █ ███ █ █ |
| 35 | +>>> codext.decode(codext.encode("Az", "aztec-text"), "aztec") |
| 36 | +'Az' |
| 37 | +``` |
| 38 | + |
| 39 | +----- |
| 40 | + |
| 41 | +### Fake QR Code |
| 42 | + |
| 43 | +This hides the input bytes in something that looks like a [QR code](https://en.wikipedia.org/wiki/QR_code) but is not a valid one: each bit becomes a module (a dark module for a 1, a light one for a 0), laid out row by row in the smallest QR-like square grid (versions 1 to 40) that can hold them while skipping the three finder patterns (the corner squares) and the timing patterns (the dotted lines joining them), so that the result keeps the typical QR aspect. A 32-bit header holds the input length. An optional mask (one of the 8 QR mask patterns, given in the codec name) inverts part of the data modules depending on their coordinates, making the pixels look more random. By default, the fake QR code is a grayscale PNG image (one pixel per module), but the `-text` variant renders it as plain text instead, with a full block for a dark module and a space for a light one ; decoding accepts either form. |
| 44 | + |
| 45 | +**Codec** | **Conversions** | **Aliases** | **Comment** |
| 46 | +:---: | :---: | --- | --- |
| 47 | +`fakeqr` | text <-> fake QR code (image or text) | `fakeqr-N`, `fakeqr-text`, `fakeqr-text-N` (*N* being the mask pattern) | no mask by default ; *N* ranges from 0 to 7 |
| 48 | + |
| 49 | +```python |
| 50 | +>>> png = codext.encode(b"this is a test", "fakeqr") |
| 51 | +>>> png[:8] |
| 52 | +b'\x89PNG\r\n\x1a\n' |
| 53 | +>>> codext.decode(png, "fakeqr") |
| 54 | +b'this is a test' |
| 55 | +>>> codext.decode(codext.encode(b"this is a test", "fakeqr-3"), "fakeqr-3") |
| 56 | +b'this is a test' |
| 57 | +>>> print(codext.encode("test", "fakeqr-text")) |
| 58 | +███████ ███████ |
| 59 | +█ █ █ █ |
| 60 | +█ ███ █ █ ███ █ |
| 61 | +█ ███ █ █ ███ █ |
| 62 | +█ ███ █ █ ███ █ |
| 63 | +█ █ █ █ █ |
| 64 | +███████ █ █ █ ███████ |
| 65 | + ██ |
| 66 | +█ █ ███ █ █ ███ █ |
| 67 | +█ ███ █ |
| 68 | + █ |
| 69 | + |
| 70 | + █ |
| 71 | + |
| 72 | +███████ |
| 73 | +█ █ |
| 74 | +█ ███ █ |
| 75 | +█ ███ █ |
| 76 | +█ ███ █ |
| 77 | +█ █ |
| 78 | +███████ |
| 79 | +>>> codext.decode(codext.encode("test", "fakeqr-text"), "fakeqr") |
| 80 | +'test' |
| 81 | +``` |
| 82 | + |
| 83 | +----- |
| 84 | + |
| 85 | +### QR Code |
| 86 | + |
| 87 | +This encodes the input as a real (standard, scannable) [QR code](https://en.wikipedia.org/wiki/QR_code), as opposed to the `fakeqr` codec which only mimics the aspect of one. It uses the byte mode, selects the smallest version (1 to 40) that fits the data for the chosen error correction level (`L`, `M`, `Q` or `H`, given in the codec name, `M` by default) and picks the data mask with the lowest penalty score. Decoding reads the QR code back, recovering its error correction level and mask from the format information and applying Reed-Solomon error correction, so that a damaged QR code can still be decoded ; it also handles the numeric and alphanumeric modes, so that QR codes generated by other tools can be read. Like `fakeqr`, the QR code is a grayscale PNG image by default, or plain text with the `-text` variant. |
| 88 | + |
| 89 | +**Codec** | **Conversions** | **Aliases** | **Comment** |
| 90 | +:---: | :---: | --- | --- |
| 91 | +`qr` | text <-> QR code (image or text) | `qr-L`, `qr-M`, `qr-Q`, `qr-H`, `qr-text`, `qr-H-text` | `M` by default ; the mask is chosen automatically |
| 92 | + |
| 93 | +```python |
| 94 | +>>> png = codext.encode(b"codext", "qr") |
| 95 | +>>> png[:8] |
| 96 | +b'\x89PNG\r\n\x1a\n' |
| 97 | +>>> codext.decode(png, "qr") |
| 98 | +b'codext' |
| 99 | +>>> print(codext.encode("QR", "qr-h-text")) |
| 100 | +███████ █ ███████ |
| 101 | +█ █ █ █ █ |
| 102 | +█ ███ █ █ █ ███ █ |
| 103 | +█ ███ █ █ █ ███ █ |
| 104 | +█ ███ █ █ ██ █ ███ █ |
| 105 | +█ █ █ █ █ █ |
| 106 | +███████ █ █ █ ███████ |
| 107 | + █ ██ |
| 108 | + ██ ███ ███ █ |
| 109 | +█ █ █ █ ██ ██ |
| 110 | + █ █ █ ██████ |
| 111 | + ██ █ ███ ██ |
| 112 | +██ █ ██ ████ █ █ █ |
| 113 | + █ ████ █ ███ |
| 114 | +███████ ██ █ █ █ █ |
| 115 | +█ █ ███ █ █ |
| 116 | +█ ███ █ ██ █ █ █ |
| 117 | +█ ███ █ ███ █ █ █ |
| 118 | +█ ███ █ █ ████ ███ |
| 119 | +█ █ █ ███ ██ █ |
| 120 | +███████ ███ ██ █ |
| 121 | +>>> codext.decode(codext.encode("QR", "qr-h-text"), "qr") |
| 122 | +'QR' |
| 123 | +``` |
0 commit comments