QR Fusion: Turning Functional QR Codes Into *Functional* Design
The technical story behind QR Fusion, an app that blends artwork with QR codes while maintaining 100% scannability through advanced image processing
The technical story behind QR Fusion, an app that blends artwork with QR codes while maintaining 100% scannability through advanced image processing
Blend any artwork with QR codes while keeping them 100% scannable. Perfect for designers who want beautiful, functional QR codes.
View on App StoreDownload on the App Store | Available for iOS & macOS
"A QR code doesn't have to look like a crossword puzzle stapled onto your poster."
I built QR Fusion after one too many layouts where the QR code fought everything else on the page. Black-and-white blocks clash with a careful palette. Designers either tuck the code in a corner or ship something that barely scans. I wanted a third option: blend any artwork with a QR code and still hit 100% scannability.
Stickers on road signs. Researchers showed you can trick self-driving cars into mis-reading speed-limit signs with a few stickers (read more here). That got me asking a narrower question: how little can I change a QR matrix before a phone camera gives up?
Matt Parker and Steve Mould's dual-image puzzle. In their YouTube collaboration they morph two AI-generated goals into one jigsaw that assembles into two pictures. I wondered whether I could morph a QR matrix and a photo the same way.
Designer friends stuck in Photoshop. Every designer I asked had the same complaint. QR codes are brittle. Touch them in Photoshop and you might break scannability. There was no safe "drop this in at the end of the layout" step. That gap is what I was trying to close.
Prepare both images
CIImage, origin rebased to (0,0), size n × n.Run a custom CIColorKernel
kernel vec4 combineImages(__sample original, __sample qr) {
float qrBrightness = qr.r; // 0 = dark module, 1 = light
float origBrightness = max(original.r,
max(original.g, original.b));
vec3 newColor = original.rgb;
// Dark QR module: make sure underlying pixel isn't too bright
if (qrBrightness < 0.5 && origBrightness > 0.31415) {
newColor *= 0.31415 / origBrightness;
}
// Light QR module: make sure pixel isn't too dark
if (qrBrightness >= 0.5 && origBrightness < 0.85618) {
newColor = (origBrightness > 0.0)
. original.rgb * (0.85618 / origBrightness)
: vec3(0.85618);
}
return vec4(newColor, original.a);
}
Those thresholds come from contrast sensitivity research. Scanners need clear separation between modules and background (Weber contrast). Human eyes forgive small color errors. Computer vision does not.
Apple's Core Image Programming Guide covers kernels if you want the plumbing. How QR Codes Work is a good refresher on error correction, which is what makes these tricks possible at all.
QR Fusion ships with multiple blend modes (lighten/darken, average, fade). The validator picks the safest setting by default. Power users can override.
I used AI tools where they helped: ChatGPT refactored memory-heavy loops, Claude flagged power-draw hot spots, Cursor suggested a smarter caching layer. The contrast math and validation loop are mine. The agents just sped up the boring parts.
If your brand palette deserves better than monochrome squares, give it a try and let me know what you make. The best feedback I get is a photo of a poster that scanned on the first try.
For a designer-focused walkthrough, see QR Fusion for Designers: Beautiful QR Codes That Fit Your Workflow.