RC RANDOM CHAOS

Hiding Photos Inside QR Codes with Two-Pass Error Diffusion

· via Hacker News

Original source

Dithered QR Codes

Hacker News →

QR codes split into two zones: function patterns (the bold corner squares scanners use to locate and orient the code) and data modules (everything else, which stores the payload). Because scanners only read the data modules after the finder patterns have pinned down the geometry, the data area tolerates a surprising amount of visual tampering — the trick brands exploit for stylized codes. One approach seen on Mastodon shrinks each data pixel into the center cell of a 3×3 grid, freeing the surrounding eight cells to carry a photo. The catch is that one in nine pixels is now dictated by the QR data rather than the image, producing salt-and-pepper noise on top of an already low-res, one-bit picture.

The author’s fix is layered dithering. Plain thresholding (black/white per pixel) loses midtones, so ordered dithering (Bayer) and then Floyd–Steinberg error diffusion — which pushes each pixel’s rounding error onto not-yet-processed neighbors — get closer to the true average brightness while making the QR noise less obvious. The key innovation is a two-pass diffusion: the first pass forces the data modules to their required colors and spreads that error (which can hit 95% when a dark region must go pure white) across the surrounding eight pixels; the second pass dithers the image normally. Diffusing the large forced errors rather than swallowing them is what cleans the picture up dramatically.

The generator adds refinements like rotating the code, trying alternate encodings for a nicer look, and leaning on QR error correction to flip a few stubborn data modules — though the author notes that hurts scannability more than it helps aesthetics. The whole thing is a deliberate trade-off: every bit of prettiness spends the redundancy that keeps codes readable on crumpled flyers, dim lighting, or a stranger’s cheap phone. Practical caveats include adding a quiet-zone margin and matching it to the finder-pattern color (white normally, black for inverted codes).

Read the full article

Continue reading at Hacker News →

This is an AI-generated summary. Read the original for the full story.