QR-codes zijn misschien wat over hun hype heen, ze worden nog altijd veel gebruikt. En met wat creativiteit kun je ze voorzien van leuke afbeeldingen.
Koen Vervloesem
Een QR-code is een tweedimensionale streepjescode: zwarte vierhoekjes op een rooster met een witte achtergrond. Zo'n QR-code lijkt een willekeurig patroon, maar de vierkantjes zijn zo opgesteld dat ze gegevens (tekst) voorstellen. Die tekst is vaak een url. Een QR-code scan je in met een speciale scanner, tegenwoordig is dat meestal een QR-scanapp op je smartphone. De app decodeert de QR-code en toont dan de tekst. Gaat het om een url, dan open je die url dus eenvoudig door de code op je smartphone in te scannen en hoef je de url niet meer handmatig in te typen.
QR-codes hebben talloze toepassingen [1].
In China bevatten treintickets QR-codes. De app van iDEAL scant QR-codes om betalingen vanaf drukwerk of een computerscherm op te starten en ook de app van ING kan dat. De Belgische bank KBC implementeert tweefactor-authenticatie doordat je bij het inloggen een QR-code op je scherm met de app KBC Sign op je smartphone inscant. En wifinetwerken voor gasten tonen de configuratie in een QR-code, zodat gasten niet een ingewikkeld wachtwoord op hun smartphone hoeven in te typen.
Creatief rond QR-codes
Een QR-code is een vierkant, maar niets belet je om daar omheen iets anders te tonen. Als je je scanapp gebruikt, scant die toch alleen het vierkant en trekt die zich niets aan van alles daarrond. Die eigenschap is al vaak op een creatieve manier uitgebuit, bijvoorbeeld in advertenties.
Zo heeft het tijdschrift van School of Rock eens een QR-code in zijn logo verwerkt. De Amerikaanse non-profitorganisatie Charity: Water integreerde een QR-code in een druppel. En reclamebureau BDDO bedacht een ingenieuze reclame voor het donkere bier Guinness. Een bierglas is bedrukt met een pixelvoorstelling van schuim, met in het midden een Q-code. Is het glas leeg, dan is de QR-code onleesbaar. Maar ook als je het glas vult met licht bier, krijgt de scanapp de QR-code niet gelezen door het gebrek aan contrast. Pas als je het glas vult met Guinness, dat er zo goed als zwart uitziet, komt de QR-code tevoorschijn en kun je deze scannen.
Deze QR-code van Guinness kun je alleen scannen wanneer je glas vol is van het donkere bier
Fouten corrigeren
Een QR-code stelt zijn data voor met behulp van een Reed-Solomon foutencorrigerende code. Dit is hetzelfde algoritme dat in de cd voorkomt dat een krasje op het oppervlak de cd onleesbaar maakt. Bij QR-codes is de bedoeling hetzelfde: zelfs als er een stukje van de QR-code is gescheurd of als de code niet helemaal zichtbaar is door tegenlicht, zijn de data nog altijd uit te lezen.
De specificatie van QR-codes definieert vier niveaus van foutencorrectie. Bij niveau L (Low) mag 7% van de bytes onleesbaar zijn en is de code dan nog altijd in staat om die bytes te reconstrueren. Bij niveau M (Medium) kan de code 15% corrigeren. Bij niveau Q (Quartile) ligt dat aantal zelfs op 25% en bij niveau H (High) is maar liefst 30% te herstellen. Hoe hoger het foutencorrectieniveau dat je kiest voor je QR-code, hoe minder data je uiteraard kunt voorstellen omdat je meer bytes redundantie inbouwt voor de foutencorrectie.
Hoeveel data?
Hoeveel data kun je in een QR-code opslaan? Dat hangt van drie eigenschappen af. Allereerst van het datatype dat je wilt voorstellen met de code: alleen cijfers (0 tot en met 9), alfanumerieke tekens (0–9, A–Z (alleen hoofdletters!), spatie, $, %, *, +, -, ., /, :), bytes of kanjitekens (QR-codes ontstonden in de Japanse auto-industrie). Daarnaast ook van de grootte van de QR-code. De specificatie definieert versie 1 (21 bij 21 pixels) tot en met versie 40 (177 bij 177 pixels). Tot slot hangt de hoeveelheid data ook af van het foutencorrectieniveau.Intentioneel fouten introduceren
In de QR-codes van iDeal is het logo zelfs in kleur verwerkt.
Voor de foutencorrectie is het midden gewoon ruis
De originele QR-code van de BBC en degene
die het logo van de televisiezender in het midden verwerkt
De foutencorrectie is bedoeld om fouten te corrigeren, maar het duurde niet lang voordat creatieve geesten deze mogelijkheid misbruikten om willekeurige afbeeldingen in de QR-codes zelf te steken. Zolang je niet boven het percentage fouten dat je mag maken komt, kun je de meeste pixels van de QR-code immers door willekeurige pixels vervangen. Kortom, je introduceert intentionele fouten omwille van hun artistiek effect, en door de foutencorrectie worden de gecodeerde gegevens nog altijd correct ingelezen. Maar je loopt dan wel het risico dat de gegevens niet meer leesbaar zijn als er daarna nog echt fouten gebeuren...
Zo introduceerde Duncan Robertson in 2008 het BBC-logo in een QR-code die de url http://bbc.co.uk/programmes voor de programmatie van de Britse televisiezender voorstelde. Dichter bij huis zien we dat iDeal zijn logo verwerkt in zijn QR-codes voor betalingen [2], inclusief kleur! Voor de QR-lezer maakt dat allemaal niet uit: de app herkent bij deze voorbeelden in het midden geen vierkantjes en ziet er gewoon ruis. Maar dankzij de foutencorrectie zijn de vierkantjes die er zouden moeten staan te reconstrueren. Deze aanpak werkt binnen zekere grenzen voor elk logo.
Afbeeldingen zonder fouten
Er is nog een derde, veel technischer manier om creatief te zijn met QR-codes. Russ Cox beschrijft die aanpak op zijn website en noemt die QArt [3]. Cox heeft een programma geschreven dat de data in een QR-code zo codeert dat de QR-code een afbeelding voorstelt, en dat zonder enige fouten te introduceren!
De lichte pixels vormen de boodschap, de donkere zijn redundante pixels voor de foutencorrectie. (bron: Russ Cox)
Hoe werkt dat? Daarvoor moeten we eerst in grote lijnen weten waaruit een QR-code bestaat. Elke QR-code heeft een aantal vaste elementen die een scanner helpen om de code te herkennen. Hoeveel elementen er juist zijn, hangt af van de grootte en het foutencorrectieniveau. Maar ze zijn goed te herkennen: je hebt altijd op de drie hoeken een vierkant (de ‘finder patterns’) en van de twee buitenste vierkanten naar het middelste loopt een stippellijn (de ‘timing patterns’). Bij de grotere versies heb je ook nog kleinere vierkantjes in een raster te beginnen vanaf de rechteronderhoek (de ‘alignment patterns’). Er zijn nog wat kleinere vaste elementen, maar die zijn voor ons verhaal minder belangrijk.
De bits uit de boodschap worden in een zigzaglijn
als pixels in de QR-code voorgesteld. (bron: Russ Cox)
De bits van de boodschap komen van rechtsonder naar linksboven in een zigzaglijn als pixels, waarbij ze de vaste elementen overslaan. Het is dus eenvoudig te voorspellen waar de bits in je boodschap in je QR-code terechtkomen. Zo kun je in principe elke willekeurige afbeelding in je QR-code krijgen, tenminste in het deel van de boodschap zelf; op de bits van de foutencorrigerende code heb je geen vat.
Enkele complicaties
In de praktijk zijn er nog enkele complicaties. Allereerst worden de data volgens een masker geXORd: we leggen de pixels van het masker over de pixels van de data en elke pixel krijgt dan een nieuwe waarde: 0 in de data en 0 in het masker wordt 0, 0 in de data en 1 in het masker wordt 1, 1 in de data en 0 in het masker wordt 1, en 1 in de data en 1 in het masker wordt 0. Deze binaire operator heet XOR (‘exclusive or’).
Met de software van Russ Cox maak je eenvoudig
QR-codes zoals deze met het favicon van HCC
De specificatie van QR-codes definieert acht maskers. Een QR-encoder past die alle acht afzonderlijk toe en kiest dan degene die het minste lijnen in het resultaat geeft, zodat scanners niet per ongeluk een lijn als een deel van een finding pattern beschouwen. Maar omdat we controle over de pixels willen, kiezen we gewoon een masker en coderen dan onze data ermee.
Een andere complicatie is: we willen dat als iemand de QR-code scant, er wel zinnige data uitkomt. Russ kwam tot een elegante oplossing: hij codeert een url, met erachter een anker (#) en een lange reeks met cijfers die de reeks pixels voorstelt. De browser vindt dat anker dan niet, maar klaagt daarover niet als de webpagina zelf wel bestaat.
Hoe korter je de url in je QR-code houdt, hoe meer pixels je over hebt voor de afbeelding
Uiteindelijk heb je zo geen controle over het linkergedeelte van de QR-code (dat zijn de foutencorrigerende bits) en ook niet over het rechtergedeelte (die stellen de url voor). Maar in het midden kun je een willekeurige afbeelding tonen.
Russ heeft nog een wiskundige truc toegepast waarmee hij in staat is om de foutencorrigerende bits uit het linkergedeelte over het hele canvas uit te smeren. Zo komt hij uiteindelijk dan toch tot een verbluffend resultaat: een willekeurige afbeelding in een QR-code, alleen met wat schijnbare ruis die de foutencorrigerende bits voorstelt, en de foutencorrectie werkt nog in het geheel. Op zijn website vind je een QArt Coder [4] om zelf zulke QR-codes te construeren.
Infolinks
[1] https://github.com/zxing/zxing/wiki/Barcode-Contents
[2] https://www.ideal.nl/ontvangen/aan-de-slag/qr-code/
[3] https://research.swtch.com/qart
[4] https://research.swtch.com/qr/draw