Nano QR kód generáló

Fórumok

Mivel több HUP-os fórumtárs is mikrokontrollerezik, ezért gondoltam megosztom, hátha másnak is hasznos lesz.

Összedobtam egy minimalista QR kód generálót ANSI C-ben, kifejezetten URL-ek kódolására:
- Szabad és Nyílt Forráskódú, MIT licenszű
- irtó kicsi (kb. 150 SLoC), egyetlen egy függvény csak
- nincs semmi függősége (még libc se, de még csak libc fejlécek sem kellenek neki)
- nem foglal memóriát egyáltalán
- csak pár bájtot eszik a veremből
- pofon egyszerű használni, nem kell konfigurálni
- egy 53 x 53 pixeles szürkeárnyalatos képet köp ki (csak 0 (előtér) ill. 255 (háttér) színekkel)
- a bemenete egy legfeljebb 128 bájtos URL (vagy hát bármilyen UTF-8 sztring igazából)

Példa használatra (csak példa, semmilyen domain sem query paraméter nincs a függvénykönyvtárban, bármi lehet):

#define NANOQR_IMPLEMENTATION
#include "nanoqr.h"

uint8_t image[53][53];
nanoqr(image, "https://gitlab.com/bztsrc/nanoqr?errcode=1234&errpos=1234&when=1234");

Ennyi. Aztán a megadott URL-re lehet rakni egy JavaScriptet, ami megcsócsálja és ember számára érthető hibaüzenetekké formálja az URL paraméterében megadott kódokat.

Technikai részletek: QR version 9-et generál (mert a 128 bájtos tárhely elfogadhatónak tűnt, a 53 x 53 pixeles méret meg elég kicsi ahhoz, hogy elférjen LCD-kre, de akár LED-es kijezlőkre is). A hibajavító kód QUARTILE (eggyel rosszabb csak, mint a legjobb opció), a maszkszint fixen 1-es, az adathalmaza pedig bájt (mert az alfanumerikusból hiányzik a ?, &, =, szóval nemigazán kódolható vele URL). Ezeket bedrótoztam az egyszerűség kedvéért, hogy ne kelljen semmit állítgatni. Ha valakinek ez nem felelne meg, akkor nekik ott a Nayuki QR kódgeneráló, de az többet eszik és bonyibb használni is.

Hozzászólások

Szep :) Tenyleg teljesen warning-mentesen fordul 4 architekturan is, olyan 1.5k-2k koruli kod lesz minden esetben. 

Hm... az mennyire bonyolitana el a kodot hogyha 2809 bytenyi 0-255 kep helyett ~352 ... ~371 bytenyi bitmaszkot allitana elo? 

Szep :)

Kösz! :)

Hm... az mennyire bonyolitana el a kodot hogyha 2809 bytenyi 0-255 kep helyett ~352 ... ~371 bytenyi bitmaszkot allitana elo?

Nem annyira vészes. A képet két lépcsőben állítja elő:
1. először 255-el tölti fel (133. sor), majd bizonyos pixeleket 0-ára állít, hogy a jól ismert alap mintázat rákerüljön (134.-150. sor).
2. az adatpixelek berakásakor (153.-191. sor) szintén csak 0-ra állítás van, illetve itt előfordul még XOR.
Ezek triviálisan átírhatók bitenkénti "dst &= ~x" és "dst ^= x" utasításokra, ez nem okoz problémát.

A gond inkább azzal van, hogy az 53 nem osztható 8-cal, így nem egyértelmű, mennyire kéne venni a sorhosszt. Lehet 56-ra (azaz 7 bájtra), de az az alignment miatt gondot okoz sok helyen (pl. ha BMP-be akarod menteni), vagy még több paddinggal 64-re, aminél meg lehetne akár uint64_t-t is használni egy sorra (mondjuk mikrokontrollereknél ritkán van 64 bites szó, de nem kizárt). Viszont az is gond még ennél, hogy minden rendszer máshogy veszi, balra vagy jobbra legyen-e a legalacsonyabb bit, mármint az endianess problémán túl (a PNG és a BMP pl. eltérő sorrendet használ). Bájtoknál nincs ilyen probléma, annál mindenki balról jobbra olvassa a sort, és az endianess is tök mindegy.

Aztán meg az is van, hogy macerás egy bitmapből kirakni a képet. Ha fájlba akarod menteni, akkor grayscale-nek simán megy így bájtokkal egy-az-egyben, ha indexelt palettás a formátumod, akkor elég minden pixelre gondolkodás nélkül &1-et nyomni és meg is vagy (az indexméret úgyis 8 bit), és RGB-re konvertálni is triviális (csak megismétled 3szor a bájtot ha true-color, vagy kétszer, ha hi-color), stb. Bitmapet sokkal több kóddal és macerávan lehetne csak átalakítani a cél pixelformátumra, ráadásul mint említettem volt, annál folyamatos probléma, hogy mi is a bitsorrend és hogy mennyi legyen a padding, meg még endianess függő is, mert nemcsak 1 bájt egy sor.

Szóval mindezeket megfontolva jutottam arra, hogy jobb, ha bájt alapú a kép, tisztább, szárazabb érzés.

Meg egy gyors szakmai kerdes :) Ez a kod mennyire altalanosithato, akar #define-okkal, akar mint fuggvenyparameterrel hogy ne csak Version 9-et tudjon hanem (akar) kisebbet is? Igen, az biztos ront a hatekonysagan hogyha fuggvenyparameterrel adod at a negyzet meretet, de a forditaskor ismert meret mint megoldas is erdekes/hasznos lehet. Akkor masok a GF(2^8) parameterek?