Saramsha

No. 037  ·  23 October 2026

Enough Left to Read

A QR code's pixels are mostly your message — but a real share of them are Reed–Solomon parity, spare codewords that exist only to repair damage. Drag across the code to scratch it, the way a key in a pocket would, and watch how much of that it shrugs off.

About this piece

The parity was always part of the picture

A QR code looks like it is entirely your message, scaled up into little black and white squares. It isn't. Underneath the text there is a second layer, written in the same alphabet of dark and light modules, that exists purely so the first layer can be repaired. This page builds both layers from scratch in your browser — encodes the text you type, renders every module that comes out of it, and then decodes its own picture back into text. Nothing here is simulated; damage the grid and you are watching a real decoder fail or succeed.

The repair layer is Reed–Solomon coding, published by Irving Reed and Gustave Solomon in 1960 and now underneath nearly every format that has to survive physical damage: compact discs, DVDs, QR codes, the deep-space links to Voyager and the Mars rovers. The idea starts by cutting your message into bytes and treating them as coefficients of a polynomial, then evaluating that polynomial at a fixed set of points to get extra bytes — the ones this page calls parity, or the error-correction codewords. A byte going bad anywhere, in the message or in the parity itself, shows up as a mismatch at those evaluation points. Work backwards from exactly which points disagree and by how much, and you can recover both where the damage is and what the original byte was. That backward step needs arithmetic over a 256-element finite field (GF(256), the same one AES uses) rather than ordinary numbers, which is why it takes a page of algebra rather than a glance — but the shape of the argument is the same one behind Hamming's parity checks, scaled up from single bits to whole bytes.

You choose how much parity to add. QR calls the choice the error correction level: L spends the fewest codewords on repair and the most on your text, M and Q trade a little more text for a little more spare capacity, and H gives up nearly a third of the symbol's codewords so that nearly a third of them can go bad and still be reconstructed. Lower levels aren't a mistake to avoid — a sticker that will sit flat under glass forever can afford to spend its space on more text; a parcel label that will get scuffed, wet and refolded cannot.

Try the two kinds of damage on this page side by side and something that looks backwards happens: dragging a scratch across a third of the code often still decodes, while scattering the same number of flipped modules as noise usually kills it at a tenth of that. The quoted percentages (7% / 15% / 25% / 30%, roughly, for L/M/Q/H) are a budget of codewords — whole bytes — not modules, and a codeword with one wrong bit costs exactly the same repair budget as one with all eight bits wrong. A scratch is a burst: a few dozen modules in a row touch only a handful of codewords, each one many times over, so most of the budget goes unspent. Noise is the opposite: the same few dozen flips, spread one-per-codeword across the whole symbol, can exhaust the budget on nearly every block at once. The modules-damaged percentage this page shows you is exactly what your hand controls — watch it against the decoder's own verdict, not against the quoted codeword budget, because the two numbers are measuring different things.

This is also precisely why the codewords get shuffled before they are drawn. QR does not lay a block's bytes down next to each other; it interleaves them, taking one codeword from each block in turn so that a short physical burst — a scratch, a crease, a torn corner — lands a little damage on many blocks instead of a lot of damage on one. Reed–Solomon can only correct so many bad codewords per block, so spreading a burst thin across every block is what turns "this block is destroyed" into "every block lost one codeword, and every block can spare one." The same interleaving is exactly what makes scattered noise the harder case: it defeats the trick by doing on purpose, module by module, what interleaving was built to prevent a scratch from doing by accident.

Not every module is protected the same way, either. The three big squares — one in each corner but the bottom-right — are finder patterns: a fixed, unmistakable ring-in-a-ring shape that a camera's scanner uses to locate the code at all, work out its tilt, and figure out where the grid of modules actually falls on the image. They carry no error correction of their own, because their whole job happens before decoding starts. Break one and a real scanner never gets as far as reading a single data bit — which is exactly why this page checks them first and refuses outright rather than pretending Reed–Solomon could save a code that was never found in the first place. Everything else you can damage — the message, the parity, the timing ticks along two of the edges, even the small alignment square version 2 and up carry near the bottom-right — is fair game for the repair layer, which is also why the default here keeps the finder squares safe: so you can explore the budget the code is actually spending on your behalf, rather than the one failure mode that bypasses it entirely.

Everything on this page — the byte-mode encoder, the GF(256) arithmetic, the Reed–Solomon encode and decode, the module placement — is implemented here, in your browser; nothing is uploaded and no third-party library is loaded. Supported versions are QR versions 1–4 (21×21 to 33×33 modules), byte mode, a fixed mask pattern. Input is restricted to printable ASCII.