Inside a QR Code: Finder, Alignment and Timing Patterns — featured illustration
Technology

Inside a QR Code: Finder, Alignment and Timing Patterns

6 min read
Create a QR code

Turn a QR code upside down and it still scans. Photograph it at a sharp angle, wrap it around a bottle, catch it in a mirror on a shop window, and a decoder still finds it, squares it up and reads it. That tolerance is not clever software compensating for a dumb image. It is built into the picture.

Most of the modules in a QR code carry data. A minority carry structure, and those are the ones that make the rest readable.

The three corner squares

The finder patterns are the first thing anyone notices: three concentric squares in three corners. Each is 7x7 modules, made of a dark 7x7 outer ring, a light 5x5 ring inside it, and a solid dark 3x3 core.

The proportions are the point. Draw any straight line through the middle of a finder pattern and you cross dark, light, dark, light, dark in a 1:1:3:1:1 ratio of widths. Horizontally, vertically, and through the diagonal, the ratio holds. A decoder sweeps lines across the image looking for exactly that run of five, which is cheap to test and works at any scale, since a ratio does not care whether the code is 15mm on a business card or two meters across a wall.

Three hits give three points, and three points define a plane. From them the decoder derives position, scale and rotation before it has read a single bit. Each finder also sits inside a one-module light separator on its inner edges, which keeps data modules from touching the pattern and corrupting the ratio.

Why the fourth corner stays empty

Three squares, not four, and the omission is deliberate. Three points arranged at the corners of a right-angled triangle have exactly one right-angle vertex, and that vertex marks the top-left of the symbol. Rotation is resolved immediately.

Put a fourth finder in the remaining corner and you would have a shape with four-fold symmetry and no way to tell which way up it was. Every scan would carry four candidate orientations, and the decoder would have to try each in turn. The empty corner does real work by not being there.

Alignment patterns and bent surfaces

Alignment patterns are the smaller squares scattered through larger codes: 5x5 modules, a dark outer ring, a light inner ring, one dark module at the center.

Version 1 has none, because a 21x21 grid is small enough that the three finders pin it down. From version 2 a single alignment pattern appears toward the lower right. The count climbs with the version, reaching forty-six in the largest sizes, with centers laid out on a square grid and the three grid positions that would clash with finder patterns simply omitted.

What they fix is distortion that is not uniform. The three finders let a decoder map a flat rectangle, but a real photo is rarely a flat rectangle: the camera is off-axis, the label curves around a can, the paper has a fold through it, the lens bends the edges of the frame. Alignment patterns give the decoder known reference points in the interior, so it can correct the grid locally instead of assuming one global transform. Without them a large symbol read at an angle would drift out of register by the far corner, and every module past that point would be sampled in the wrong place. How the count grows with version, and what that does to the physical module size, are worth reading together.

Timing patterns set the ruler

Between the finder patterns run one row and one column of alternating dark and light modules, a single module wide, at a fixed offset from the top-left corner. This is the timing pattern, and it is the least decorative element in the symbol.

Its job is to establish the module pitch. Knowing where the code sits is not enough; the decoder also has to know how wide one module is and where each boundary falls. The alternating run gives it a ruler with marks at every module, so it can count positions across the symbol and stay in step even when scale drifts slightly across the image because of perspective.

There is a small piece of design elegance here. Where an alignment pattern happens to sit on the timing row or column in larger versions, the alignment pattern's own alternating structure lines up with the timing rhythm rather than interrupting it.

Format and version information

Two more reserved areas carry metadata rather than payload.

Format information wraps around the finder patterns: fifteen bits recording the error correction level and which of the eight mask patterns was applied. It appears in every version, and it is stored twice in two separate locations with its own error detection, because a decoder that cannot read the format bits cannot read anything at all. Which correction level ends up recorded there has real consequences for damage tolerance and capacity, and it is the setting that decides how much artwork a logo-bearing code can survive.

Version information is the pair of 6x3 blocks near the top-right and bottom-left finders, and it exists only from version 7 upward. Smaller symbols do not need it, since the module count alone identifies the version.

A single module beside the lower-left format area is always dark, in every symbol ever made. It carries no message; it is a fixed reference.

Masking, and why identical data can look different

The data region is not written down raw. One of eight mask patterns is applied over it with an exclusive-or, flipping a regular subset of the modules. The encoder generates candidates, scores each against penalty rules, and keeps the best one.

The rules penalize long runs of a single color, large solid blocks, and unbalanced dark-to-light ratios. One rule matters more than the others: any run in the data imitating the 1:1:3:1:1 finder ratio is heavily penalized, since a false finder pattern in the middle of the data region would send the decoder hunting for a symbol that is not there.

This is why the same content can produce visibly different codes at different correction levels, and why the visual texture of a code is not something you set directly. Under the mask, the data is written into the remaining modules in a two-module-wide zigzag that starts at the bottom right and works upward, then down, then up, skipping every reserved area described above.

The quiet zone is part of the symbol

Four modules of clear margin on all four sides, containing nothing. It is not padding added by a designer with an eye for whitespace; it is specified structure, and a decoder uses it to establish where the symbol ends and the background begins.

Crowd it with text, a border rule or a busy photograph and the scan-line search hunting for the 1:1:3:1:1 ratio can pick up surrounding artwork as part of the pattern. Codes that fail this way often look perfectly fine to a person, which is why the cause takes so long to spot. It is a standing entry on any list of reasons a code will not scan, and the easiest of them to fix.

Try this on something you have already made: zoom in until individual modules are visible, lay a ruler across a corner square, and check that the dark and light bands really do come out at 1:1:3:1:1. If they do not, the artwork has been stretched non-uniformly, and no amount of error correction will rescue it. The read sequence starts and ends with that ratio.

Share this article