Skip to content
Adrien Hubert

QR code, taken apart.

A QR encoder written from scratch for this page, with no library. It handles byte mode in versions 1 to 10. Switch to the layers view to see which modules carry your text and which carry the error correction. Then pick up the damage brush and find out how much of the symbol you can ruin before it stops scanning.

Hover a module to see where it belongs.

version
-
bytes used
-
data codewords
-
ecc codewords
-
format bits, after the 0x5412 xor
-
  • finder, separator
  • timing
  • alignment
  • format info
  • version info
  • data codewords
  • ecc codewords
  • remainder bits

    Eight masks, scored. Lowest penalty wins unless you pick one.

    Damage flips real modules. In the plain view you can point a phone at the screen and check the verdict.

    Note

    Most of a small QR code is not your text. The three big squares let a scanner find the symbol and its rotation. The dotted lines between them give it the module pitch, and the small squares in later versions correct for a bent page. Two copies of 15 format bits name the error correction level and the mask. Everything else is a stream of bytes laid down in two-module columns, starting at the bottom right corner and snaking up and down toward the left. Hover a coloured module to light up its whole codeword and follow the snake.

    The orange codewords are Reed-Solomon parity over GF(256). A block with 2t parity codewords can repair t wrong codewords without knowing where they are. The smallest symbols keep one to three parity codewords back to stop a decoder from confidently returning the wrong text, so a version 1 symbol at level L fixes 2 codewords rather than 3. Larger versions split the data into several blocks and interleave them byte by byte. A coffee stain then lands on neighbouring codewords that belong to different blocks, and each block absorbs a small share of it.

    The mask is an XOR pattern over the data area, chosen to avoid large flat patches and accidental copies of the finder pattern. Each candidate gets four penalties: long runs, 2 by 2 blocks of one colour, finder-like 1:1:3:1:1 sequences, and imbalance between dark and light. Any mask decodes, because the format bits say which one was used. Encoders do not agree on how to count the third rule. I checked this encoder against python-qrcode on 105 cases. With the mask fixed, every module matched. Left to choose, the two picked the same mask in 11 of 21 cases.

    The verdict counts bad codewords per block against what each block can repair. It is a model, not a decoder. A scanner can also fail when a finder is hidden or both format copies are damaged, and the page only warns about those. A phone is the real test.

    Sources

    • ISO/IEC 18004:2015. Information technology, automatic identification and data capture techniques, QR Code bar code symbology specification.
    • Reed, I. S. and Solomon, G. (1960). Polynomial Codes over Certain Finite Fields. Journal of the SIAM, 8(2), 300-304.
    • Nayuki. QR Code generator library. nayuki.io/page/qr-code-generator-library
    • Thonky. QR Code Tutorial. thonky.com/qr-code-tutorial