Damaged QR code generator
A perfect code, photographed badly. Out of focus, noisy, low resolution, faded, JPEG-compressed, rotated, cropped, photographed at an angle, or partly covered — with each image labeled by whether the data survives the damage.
This is a different failure from a broken symbol
A corrupted symbol has wrong modules. A damaged image has the right modules and a bad picture of them, and that is what actually happens in the world: the printer smears, the camera cannot focus, the laminate kills the contrast, somebody saves the code as a small JPEG, somebody photographs a sign from an angle in poor light.
The two need separate fixtures because they exercise separate code. A corrupted symbol tests error correction. A degraded image tests the front of the pipeline — binarisation, thresholding, sampling — before error correction gets anything to work with.
What is applied
- Blur, in fractions of a module: a quarter, a half, one and two. The interesting threshold is where neighbouring modules average into each other.
- Sensor noise at three amplitudes, of the kind a phone camera adds in poor light.
- Low resolution, downscaled by 2, 3, 4 and 6 and scaled back, on a sampling grid deliberately offset from the module grid — which is what a real scan does.
- Reduced contrast at 50%, 20% and 8%, standing in for faded print or a dark code on a dark background.
- JPEG artifacts from a real 8x8 discrete cosine transform with quantisation, not a blur pretending to be JPEG.
- Rotation by 2, 10 and 45 degrees, resampled bilinearly.
- Crops that eat the quiet zone and then the modules.
- A keystone warp, as though photographed from an angle.
- Obstructions covering 4%, 10% and 20% of the code.
What the verdict answers, precisely
A degraded photograph can fail in two independent ways, and conflating them would make every label here worthless. The symbol may not be found at all — a detection problem, involving finder patterns, perspective estimation and binarisation. Or it may be found and the data still not recovered.
These labels answer the second question only. Each image is sampled at the modules' true positions, which is what a reader that has already located and corrected the symbol would do. That makes this a strictly easier test than a scanner faces, and the consequence is worth stating plainly: a case marked lost will not read on any scanner, because the data is gone. A case marked survives may still fail on a phone that cannot find the code.
The rotation cases are the clearest illustration. The data survives a 45-degree rotation intact; whether your reader manages it depends entirely on whether it can detect a symbol that is not square to the frame. That is a real and separate thing to test, and pretending one number covers both would be the easier and less useful choice.
What the measurements show
Blur is the sharpest cliff. Up to about half a module of radius the code reads with error correction doing the work; past a full module the light and dark have averaged together and nothing recovers it.
Resolution has a hard floor at roughly one pixel per module — below that the information is genuinely absent rather than merely hard to read. A uniform contrast squeeze, by contrast, removes nothing at all: light stays lighter than dark, so a reader that thresholds adaptively still reads a code at 2% contrast while one using a fixed midpoint fails at 50%. That is a property of the reader, not the image, which is exactly why it is worth having fixtures for.
JPEG deserves its reputation, with a caveat: at six pixels per module the ringing stays at the module edges and the centers survive even at quality 5. At three pixels per module the same compression reaches the centers and the code dies. So the honest advice is not "never use JPEG" but "never use JPEG for a small code", and the fixtures are generated at the size where it actually matters.
Questions
What is the difference between this and the invalid code generator?
That one breaks the symbol — wrong modules, corrupted headers. This one keeps the symbol perfect and damages the picture of it: blur, noise, compression, angle. They test different halves of a scanner.
Does a case marked survives mean my scanner will read it?
Not necessarily. It means the data is recoverable once the symbol has been located and corrected. Finding the symbol in the image is a separate problem, and it is the one a rotated or low-contrast code makes hard.
Why is JPEG generated at a small module size?
Because that is where it does damage. At six pixels per module, JPEG at quality 5 does not flip a single module — the ringing stays on the edges. At three pixels per module it reaches the centers.
Is the blur a real blur?
Three passes of a separable box blur, which closely approximates a Gaussian. The JPEG cases likewise use a real 8x8 DCT with quantisation rather than an imitation.
Can I reproduce a specific image later?
Yes. The same content, level and seed produce byte-identical images, and the manifest records all three.
Make a different kind of code
Invalid QR code generator · QR code testing tool · Free QR code generator · QR code generator for a URL · Wi-Fi QR code generator · vCard QR code generator · QR code generator · Bulk QR code generator