Damage tolerance: blur (real tattoo aging)
Tattoos don't fail through hard "blot" cover-ups. They fail through gradual ink bleed and edge softening: a year of normal skin life rounds the corners of the modules, ten years blurs them appreciably, thirty years can leave the QR a soft watercolor. This is the failure mode Tessera simulates and tests against.
The damage model is a Gaussian blur applied to the rendered QR canvas at a radius proportional to the chosen severity:
- Render the QR onto a clean canvas at high resolution (20 px per module).
- Apply a Gaussian blur with radius = (severity / 100) × moduleSize × 3. So 5% ≈ one-sixth of a module of blur, 30% ≈ nearly a full module of blur.
- Re-run the round-trip decoders against the blurred image.
- Repeat at 0%, 5%, 10%, 15%, 20%, 25%, 30%. Blur is deterministic, so a single trial per level is enough.
- Record the highest level at which the QR still decoded correctly.
Reading the severity scale in tattoo-aging terms:
- 0%: pristine, the day after the tattoo heals.
- 5%: a fresh-ish tattoo after a few years; just-perceptible softening.
- 15%: ~15-year-old tattoo with normal aging on a forearm or calf.
- 30%: heavily blurred. A 30+ year old tattoo, or a poorly placed/maintained one, or a small dense one that ran together early.
The permanence bar is 5% blur tolerated. Every QR Tessera generates is swept through all seven levels on load and the highest level the decoders still read is reported on the live tolerance log on the right side of the damage preview.
Why a binary OK/FAIL per level rather than a pass-rate? Blur is deterministic; there's no random variable to average over. The test is "at this exact blur radius, do any decoders still read the exact input back?": a clean, reproducible yes-or-no.
Importantly, the actual measured tolerance for your QR is shown live in the UI and recorded on the spec sheet. If your input pushes the QR up to v6 or v10 (more redundancy per block), you'll see and record a much higher tolerance number. The 5% bar is just the floor below which Tessera won't ship. The damage preview on the generator lets you drag the slider and watch the verdict flip in real time.
Why finders aren't damaged in this model. Gaussian blur affects every pixel uniformly, including the finder patterns. That's accurate to real tattoos: ink bleed doesn't respect the spec. But the blur scale is calibrated so the finders are still detectable up to severe damage levels; losing the finders means losing detection entirely, with no recovery path. If a real tattoo gets so blurry the decoder can't find it, the recommendation is "ask the artist to touch it up", not "rely on a spec layer that wasn't designed for finder loss".
Real-world tattoo failure modes (ink spread, fading) usually correspond to blur levels far less than 10% on the Tessera scale. A QR that survives 10% blur in this simulation will almost certainly survive normal aging at sensible module sizes.
Why fewer modules win for tattoos. Higher EC levels (H over Q) buy more algorithmic damage recovery, but they pay for it in more modules for the same data. For tattoos, the failure mode is blur, and what helps with blur is physical module size, not algorithmic recovery: bigger modules ⇒ more skin per module ⇒ more margin before edges merge with neighbors ⇒ more pixels per module when a phone reads it. The artist's needle has its own resolution limit (about 0.3 mm dots), which puts a hard floor on viable module size. So Tessera's tattoo-optimal recommendation is the smallest version that fits the data at any EC level, with the highest EC level that fits at that version: maximum module size, with whatever EC headroom is still available. The generator's tattoo specs panel suggests this combination automatically and lets you apply it with one click.