2D symbology · optical channel
Blur isn't
damage. It's a
low-pass filter.
A QR code treats a smudged module as lost, and spends its redundancy evenly across the finest detail it has — exactly where a lens is weakest. Wavecode puts the payload where the channel still passes it, and decodes what survives instead of rounding it away.
1116 hexagonal cells · rate 1/2 LDPC · 64 bytes
Try it — this decodes for real
Blur them both until
one of them dies.
Both carry the identical 47-byte URL — the address of this page — at the same printed size, under the same blur. Nothing here is a mock-up: both images are decoded in your browser every time you move the slider.


Decoded by the same code that runs the scanner · jsQR for the QR, wavecode's own receiver for the other
Encoding
Four steps from
text to texture.
Bytes and a checksum
64 bytes of payload plus a 16-bit CRC, so a wrong answer can never be mistaken for a right one.
LDPC, not Reed-Solomon
A sparse parity graph at rate 1/2. Belief propagation runs on soft readings, so a faint cell still counts for something instead of being rounded off.
Onto a hexagonal lattice
Blur is round, so the sampling grid should be too. Hexagons need 13.4% fewer cells for the same circular bandwidth, and each one ends up bigger.
A ring that doubles as a ruler
The solid border locates the symbol, and its own edges measure the camera's blur, which is what tells the decoder how hard to sharpen.
The physics
Contrast dies as a
Gaussian in pitch.
Push a pattern of cell pitch p through a lens of blur radius σ and the contrast that comes back is not a gentle slope. It falls off a cliff, and where that cliff sits depends entirely on how big the cells are.
- 01Geometry beats ink. Six decibels of amplitude buys about 12% more blur tolerance. Bigger cells buy the rest.
- 02Half the ink is wasted. Where a flat binary design gives out, the optimal power allocation puts zero into 51% of the spatial frequencies. Blur already destroyed them.
- 03A QR code gets worse as it grows. More payload means a higher version, smaller modules, and less tolerance everywhere at once.
Geometry
A round channel wants
a round lattice.
Swap the square grid for a hexagonal one and the cell centres sit 1.0746× further apart for the same cell count. Cell separation is exactly what blur tolerance scales with, and it costs nothing: every cell still sits at a rail, so there is no peak-to-average penalty to pay for it.
| Lattice | Cells | Payload | Half-rate crossing |
|---|---|---|---|
| Square | 1156 | 66 B | 1.480% |
| Hexagonal | 1116 | 64 B | 1.549% |
Graceful failure
Or give up one
layer at a time.
A second variant puts the payload in a Haar wavelet pyramid instead of a flat grid. Every detail coefficient is exactly zero-mean over its parent block, so blurring to a given scale annihilates the fine levels and leaves the coarse ones untouched. Fine detail cannot corrupt coarse detail — by construction, not by margin.
That is only useful if the right information survives longest. The symbol on the test board is an equipment tag, written so the ordering of importance matches the ordering of range: identify it from across the floor, triage it from a few paces, pull the full record with it in your hand.
- A847213 — which asset. 8-cell detail, still reading at 1.8% blur, when nothing else is.
- BDUE-0412 — next inspection. 4-cell detail, holds to 1.2%. Enough to know whether to walk over.
- Cthe full record URL — 2-cell detail, needs 0.8% or better. The detail you only want once you are close.