Spec & internals
Mask patterns 0 to 7: the eight formulas and why they exist
A QR code's data region is XORed with one of eight mask patterns, chosen to avoid misleading shapes: large same-colour areas, poor dark-light balance, and runs that mimic the finder patterns' 1:1:3:1:1 signature. The masks are fixed formulas over row and column, and the chosen one is recorded in the format information.
Why masking exists
Data is arbitrary, and arbitrary data sometimes draws exactly what a scanner must not see: a solid dark slab that swallows the local threshold, a checkerboard-free expanse with no edges to lock onto, or (worst) a run of modules in the 1:1:3:1:1 ratio that imitates a finder pattern and sends the detector chasing a false corner. An unmasked symbol would scan well for some payloads and terribly for others, with the difference invisible to the person generating it.
Masking fixes the distribution, not the data: XOR the data region with a fixed, decoder-known pattern so the printed modules look statistically tame whatever the payload. XOR is self-inverse, so the decoder applies the same pattern once more and the original bits fall out. Nothing is encrypted, nothing is lost.
The eight formulas
For a module at row i, column j (counted from 0, top-left), the module is flipped when the condition holds:
| Mask | Condition | Visual character |
|---|---|---|
| 0 | (i + j) mod 2 = 0 | Checkerboard |
| 1 | i mod 2 = 0 | Horizontal stripes |
| 2 | j mod 3 = 0 | Vertical bars, every third column |
| 3 | (i + j) mod 3 = 0 | Diagonal stripes |
| 4 | (⌊i/2⌋ + ⌊j/3⌋) mod 2 = 0 | Coarse brick pattern |
| 5 | (i·j) mod 2 + (i·j) mod 3 = 0 | Grid lattice |
| 6 | ((i·j) mod 2 + (i·j) mod 3) mod 2 = 0 | Dense weave |
| 7 | ((i+j) mod 2 + (i·j) mod 3) mod 2 = 0 | Diagonal lattice |
Two rules govern their application:
- Only the data and error-correction region is masked. Function patterns: finders, separators, timing, alignment, and the format/version fields are never touched; their geometry is the specification.
- Exactly one mask covers the whole symbol. The 3-bit mask number is stored in the format information, read before any data, so the decoder knows precisely what to undo.
How one is chosen
The encoder is supposed to render the symbol all eight ways and score each with four penalty rules measuring runs, blocks, finder-lookalikes and dark/light imbalance; the lowest total wins. Because the choice depends on the payload, the same data at the same version can legitimately wear different masks from different generators, the main reason two tools produce different-looking codes for identical input. Any of the eight is valid; the scoring only optimises scannability.
Decoders do not care which mask was picked. They read the mask number from the format bits and un-XOR. A "wrong" (suboptimally chosen) mask costs scan robustness at the margins, not correctness. This is also why hand-rolled encoders that hard-code mask 0 still produce working codes, and why you should judge any generator by whether its output decodes cleanly under stress rather than by which patterns it favours.
FAQ
What is a mask pattern in a QR code?
One of eight fixed XOR patterns applied to the data region so the printed modules avoid problem shapes: big same-colour areas, imbalance, and runs that imitate finder patterns. The decoder reads the mask number from the format information and reverses it.
Why are there exactly eight mask patterns?
The standard defines eight formulas: enough variety that at least one scores well on any payload, while the mask number still fits in the 3 bits reserved for it in the format information.
Does masking encrypt the QR code data?
No. Masking is a reversible XOR with a public, standardised pattern, applied purely to improve scannability. Anyone decoding the symbol removes it mechanically; it provides zero secrecy.
Are the finder patterns masked too?
No. Masking applies only to the data and error-correction region. Finder, separator, timing and alignment patterns, plus the format and version fields, keep their fixed appearance. That fixedness is what scanners rely on.
Try it: free, no signup
Related
- Mask selection and penalty scores: how the best mask wins, Encoders score all eight masked symbols on four penalty rules: runs (N1=3), 2×2 blocks (N2=3), finder-lookalikes (N3=40), balance (N4=10): lowest wins.
- Format information: the 15 bits everything depends on, Format information encodes the EC level and mask in 5 bits, protects them with BCH(15,5), XORs with a fixed mask, and is written twice beside the finders.
- QR code bit stream walkthrough, from text to modules, The full encoding pipeline: mode indicator, character count, data, terminator, pad bytes 0xEC 0x11, Reed–Solomon, interleaving, zig-zag placement, masking.
- Why two generators produce different QR codes, Version selection, EC defaults, mode segmentation and mask choice can all legally differ. How to tell a harmless difference from an actual bug.