QR kodu telefonsuz okumak: Kâğıt, kalem ve karekodun gizli düzeni
Noel Friedrich, QR kodlarını kâğıt kalemle çözmek için bir çalışma kâğıdı hazırladı. Konum karelerinden maskelere ve Reed–Solomon'a, karekodun içindeki düzeni adım adım açıyoruz.
Önünüzde bir karekod, elinizde telefon yok. Yalnız bir kurşun kalem, kareli bir çalışma kâğıdı ve biraz sabır var. Noel Friedrich'e göre bu kadarı yetiyor: Kodu kâğıda kare kare geçiriyorsunuz, birkaç kuralı tersine işletiyorsunuz ve sonunda içindeki internet adresini kendi gözünüzle okuyorsunuz. Friedrich'in tahminine göre iş, kodun boyuna ve sizin deneyiminize bağlı olarak 10 ile 120 dakika arasında sürüyor.
Friedrich bu yöntemi kendi sitesinde etkileşimli bir ders ve yazdırılabilir bir çalışma kâğıdı olarak yayımladı, ardından YouTube'a bir anlatım videosu koydu. Hackaday 21 Ekim'de projeyi okurlarına aktardı. Pratikte kimse menüdeki kodu kalemle çözmeyecek. Ama alıştırmanın asıl değeri başka: Her gün okuttuğumuz siyah beyaz kareler sihir değil, kuralları kamuya açık bir yazı düzeni. Bu yazıda Friedrich'in çalışma kâğıdını rehber alarak bir QR kodunun içinde neler olduğunu adım adım açıyoruz.
Bir fabrika sorunundan doğan kod
QR kodunun kendi hikâyesini, kodu geliştiren Japon şirket Denso Wave anlatıyor. Şirketin tarih sayfasına göre çizgili barkodlar yalnız 20 kadar harf ya da rakam taşıyabiliyordu. Barkod okuyucu üreten Denso Wave'e (o dönem DENSO CORPORATION'ın bir bölümü) gelen talep, daha fazla bilgi taşıyan ve Japon kanji ile kana karakterlerini de kodlayabilen bir sembol istiyordu.
Geliştirmeyi Masahiro Hara üstlendi ve şirketin anlatımına göre ekip yalnız iki kişiden oluşuyordu. Hara'nın derdi kodu olabildiğince hızlı okutmaktı. Çözüm, okuyucuya "burada bir kod var" diyen konum işaretleri eklemek oldu. Yaklaşık bir buçuk yıllık deneme yanılmanın ardından ortaya yaklaşık 7.000 rakam taşıyabilen ve Denso Wave'in verdiği bilgiye göre diğer kodlardan on kat daha hızlı okunan bir sembol çıktı. Denso Wave kodu 1994'te duyurdu. Adındaki QR, İngilizce "quick response", yani "hızlı yanıt" sözünün kısaltması.
Kodu ilk benimseyen otomotiv sektörü oldu. Üretim ve sevkiyatta kullanılan elektronik kanban kartları QR'a geçti. Yaygınlaşmanın asıl nedeni ise bir tercih: Denso Wave patentini elinde tuttu ama kullanmayacağını açıkladı ve teknik şartnameyi herkese açtı. Şirketin standartlar sayfası bu feragatin standartlaştırılmış QR kodları için geçerli olduğunu belirtiyor. Japonya'da kodun sıradan insanlara ulaşması 2002'de, QR okuyabilen cep telefonlarının satışa çıkmasıyla oldu.
| Ekim 1997 | AIM International standardı (ISS - QR Code) |
|---|---|
| Mart 1998 | Japonya elektronik sanayi birliği JEIDA standardı (JEIDA-55) |
| Ocak 1999 | Japon Sanayi Standardı (JIS X 0510) |
| Haziran 2000 | Uluslararası standart: ISO/IEC 18004 |
| Kasım 2004 | Micro QR Code, JIS X 0510 kapsamına alındı |
| Aralık 2011 | GS1, cep telefonları için standart olarak onayladı |
Tablodaki tarihler Denso Wave'in standartlaşma sayfasından alındı. Bugün kodun ayrıntılı tarifi ISO/IEC 18004 standardında duruyor. Aşağıdaki teknik ayrıntılar Denso Wave'in kendi açıklamalarına, Friedrich'in dersine ve standardı adım adım anlatan açık kaynaklara dayanıyor.
Köşedeki üç göz: Konum kareleri
Bir QR kodunun en tanıdık parçası üç köşedeki büyük karelerdir. Bunlara konum deseni (finder pattern) denir. Kameranın ilk aradığı şey bunlardır: Üçünü bulan yazılım kodun nerede olduğunu, ne kadar büyük olduğunu ve hangi açıyla durduğunu hesaplar. Dördüncü köşenin boş kalması da kodun yönünü ele verir.
Bu karelerin oranı rastgele değil. Denso Wave'in anlattığına göre Hara ve ekibi, okuyucunun yanlışlıkla başka bir şekli konum işareti sanmaması için günlerce el ilanı, dergi ve karton kutu üzerindeki baskıları inceledi. Görüntüleri siyah ve beyaz alanlara indirip hangi oranın baskılarda en az görüldüğünü aradılar. Sonuç 1:1:3:1:1 oldu. Konum karesinin ortasından geçen her çizgi bu sırayla karşılaşır: bir birim siyah, bir birim beyaz, üç birim siyah, bir birim beyaz, bir birim siyah. Okuyucu bu oranı hangi açıdan bakarsa baksın yakalayabildiği için kod 360 derece her yönden okunabiliyor.
Konum karelerinin dışında birkaç sabit parça daha var:
- Zamanlama desenleri: Konum karelerini birbirine bağlayan, siyah ve beyaz karelerin sırayla dizildiği iki noktalı çizgi. Okuyucu bunları cetvel gibi kullanarak her bir karenin, yani modülün, nerede başlayıp bittiğini hesaplar.
- Hizalama deseni: Konum karesinin küçük bir kopyası. Sürüm 2'den itibaren görünür ve eğik ya da kıvrık bir yüzeye basılmış kodu düzeltmeye yarar. Friedrich bunu şakayla "dördüncü göz" diye anar.
- Karanlık modül: Sol alttaki konum karesinin hemen yanında her zaman siyah olan tek bir kare.
- Sürüm bilgisi: Sürüm 7 ve üzerindeki kodlarda iki köşeye yerleştirilen, kodun boyunu bildiren 18 bitlik alan.
- Sessiz bölge: Kodun çevresinde bırakılması gereken, dört modül genişliğinde boş bir kenar.
QR kodları 40 boyda gelir ve bunlara sürüm denir. Denso Wave'e göre sürüm 1 kenarı 21 modül olan bir karedir, her sürümde kenara 4 modül eklenir ve sürüm 40'ta kenar 177 modüle ulaşır. Friedrich'in formülüyle sürüm = (kenar - 17) ÷ 4. Kâğıt kalemle okumaya başlamadan önce yapılacak ilk iş modülleri saymak ve kodun hangi sürüm olduğunu bulmaktır.
Sol üstteki beş bit: Biçim bilgisi
Okuyucunun bilmesi gereken iki ayar var: Kodun hangi hata düzeltme düzeyiyle üretildiği ve hangi maskenin uygulandığı. Bu ikisi "biçim bilgisi" denen kısa bir dizide saklanır. İlk iki bit düzeyi, sonraki üç bit maskenin numarasını verir. Bu beş bit BCH adlı bir hata düzeltme koduyla 15 bite genişletilir ve kodun iki ayrı yerine, konum karelerinin kenarına yazılır. Böylece biri bozulsa bile diğeri okunur.
İşin bir püf noktası var. Biçim bilgisi de sabit bir diziyle (101010000010010) XOR işlemine sokulur, yani bazı bitleri tersine çevrilir. Amaç, bilginin hiçbir zaman tamamen beyaz bir şerit hâlinde basılmamasıdır. Friedrich'in çalışma kâğıdı bu yüzden okurdan önce sol üst konum karesinin altındaki ilk beş biti okumasını istiyor. Kâğıttaki tabloya göre bu bitlerin ilk ikisi 00 ise düzey H, 10 ise M, 01 ise Q, 11 ise L. Sonraki üç bitin birinci ve üçüncüsü ters çevrilince ortaya maske numarası çıkıyor. Friedrich bu durumu "oyunun doğası gereği maske bilgisinin kendisi de maskelenmiş" diye özetliyor.
Maske: Desenleri bozmak için desen
Veriyi kodun içine düz yazmak sorun çıkarabilir. Rastgele bir mesaj geniş beyaz boşluklar, uzun siyah çizgiler ya da konum karesine benzeyen şekiller oluşturabilir ve okuyucunun kafasını karıştırabilir. Bu yüzden kodu üreten yazılım, veri alanının üzerine sekiz maskeden birini serer ve maskenin denk geldiği her modülün rengini tersine çevirir. Standart, her maske için ceza puanı hesaplanmasını ve en az sorunlu sonucu verenin seçilmesini öngörür.
Maskeler satır (y) ve sütun (x) numaralarına bağlı basit kurallardır. Friedrich'in dersinde yer alan formüllere göre bir modül şu koşul doğruysa ters çevrilir:
- Maske 0: (x + y) çift sayı
- Maske 1: y çift sayı (her ikinci satır)
- Maske 2: x, 3'e tam bölünüyor (her üçüncü sütun)
- Maske 3: (x + y), 3'e tam bölünüyor (çapraz çizgiler)
- Maske 4: (y÷2 ve x÷3 tam kısımlarının toplamı) çift sayı (dama tahtasına benzeyen bloklar)
- Maske 5, 6 ve 7: x ve y'nin çarpımının 2'ye ve 3'e bölümünden kalanlarla kurulan daha karmaşık desenler
Friedrich bu formülleri ezberlemek yerine desenlerin görüntüsünü akılda tutmayı öneriyor. İlk beş maskeyle çalışmanın kolay olduğunu, son üçünün ise "biraz can sıkıcı" olduğunu yazıyor. İyi haber de kendi örnekleminden: İncelediği kodların yaklaşık yüzde 70'inde ilk beş maskeden biri kullanılmış. Çalışma kâğıdında maskenin denk geldiği kareler çapraz bir çizgiyle işaretli. Okur bu karelerin yalnız sol üst yarısını boyuyor ve okurken bu kareleri ters çeviriyor. Böylece maske, kâğıt üzerinde kendiliğinden geri alınmış oluyor.
Zikzak yol ve veri bayt bayt
Veri bitleri kodun sağ alt köşesinden başlar ve iki modül genişliğinde sütunlar hâlinde yukarı, sonra aşağı doğru zikzak çizerek ilerler. Yol, konum karelerini, zamanlama çizgilerini ve biçim bilgisini atlayarak dolanır. Friedrich'in kâğıdında bu yol yeşil bir çizgiyle çizilmiş. Okur çizgiyi takip ederek dört bitlik gruplar topluyor ve her grubu onaltılık tabanda tek bir rakama (0'dan F'ye) çeviriyor.
Akışın ilk dört biti kodlama kipini bildirir. QR kodu farklı karakter kümeleri için farklı kipler tanımlar:
- 0001, sayısal kip: Yalnız 0-9 rakamları, en sıkı paketleme.
- 0010, alfasayısal kip: Büyük harfler, rakamlar ve birkaç işaret.
- 0100, bayt kipi: Her karakter için bir bayt. İnternet adresleri genellikle böyle kodlanır.
- 1000, kanji kipi: Japonca karakterler için. Kodun doğuşundaki ihtiyacın izini taşır.
Denso Wave'in verdiği üst sınırlar bu kiplerin farkını gösteriyor: En büyük QR kodu 7.089 rakam, 4.296 alfasayısal karakter, 2.953 bayt ya da 1.817 kanji taşıyabiliyor. Kipten sonra karakter sayısı gelir. Sürüm 1-5 arası bayt kipinde bu sayı 8 bitle yazılır. Ardından her iki onaltılık rakam bir karakter demektir. Friedrich ezber için birkaç anahtar değer öneriyor: 31 "1" rakamı, 41 büyük "A", 61 küçük "a", 2E nokta, 2F eğik çizgi, 3A iki nokta. Mesaj bitince 0000 bitiş işareti gelir. Kalan boşluk, standardın öngördüğü EC 11 EC 11 dolgu baytlarıyla doldurulur. Friedrich, okuyucuların çoğunun bu bölüme hiç bakmadığını, oraya pekâlâ gizli bir veri saklanabileceğini de ekliyor.
Kirli kodu kurtaran matematik: Reed–Solomon
QR kodunun yağlı bir etikette ya da yırtık bir afişte bile okunmasını sağlayan şey, verinin yanına eklenen hata düzeltme baytlarıdır. Denso Wave'in açıklamasına göre bu iş Reed–Solomon kodu ile yapılıyor. Şirket bu yöntemi müzik CD'lerinde de kullanılan ve aslen yapay uydu ve gezegen sondalarında iletişim gürültüsüne karşı geliştirilmiş bir matematik olarak tanımlıyor. Kodun hesap birimi 8 bitlik "kod sözcüğü"dür ve hesaplar 256 elemanlı bir sonlu cisim, GF(256) üzerinde yapılır.
Denso Wave'in örneği mantığı iyi özetliyor: Reed–Solomon, düzeltilecek her kod sözcüğü için iki kat ek kod sözcüğüne ihtiyaç duyar. 100 kod sözcüklük bir veriye 100 düzeltme kod sözcüğü eklenirse toplam 200 kod sözcüğünün 50'si bozulduğunda bile mesaj kurtarılabilir. Bu da toplamın yüzde 25'i eder. Kodu üreten kişi dört düzeyden birini seçer:
| Düzey | Kurtarılabilen kod sözcüğü (yaklaşık) |
|---|---|
| L (düşük) | %7 |
| M (orta) | %15 |
| Q (çeyrek) | %25 |
| H (yüksek) | %30 |
Oranlar Denso Wave'in standartlar sayfasından. Şirket, kodun kirlenebileceği fabrika ortamları için Q ya da H düzeyini, temiz ortamda çok veri gerektiğinde L'yi öneriyor ve en sık M'nin seçildiğini belirtiyor. Düzey yükseldikçe aynı mesaj için daha büyük bir kod gerekiyor.
Elle okuyan biri için önemli bir ayrıntı daha var: Büyük kodlarda veri birkaç bloğa bölünür ve her bloğun kendi düzeltme baytları vardır. Bloklar daha sonra iç içe geçirilir. Önce birinci bloğun ilk baytı, sonra ikinci bloğun ilk baytı, ardından birinci bloğun ikinci baytı yazılır. Friedrich'in açıklamasıyla, hasar çoğu zaman bölgeseldir. Bloklar iç içe geçince bir lekenin zararı tek bir bloğa yığılmaz, birkaç bloğa dağılır. Çalışma kâğıdında okur baytları bu sırayı tersine işleterek doğru kutulara yerleştiriyor.

Kalemle Reed–Solomon hesabı neden yok?
Friedrich'in yöntemi düzeltme baytlarını tamamen yok sayıyor. Kodu eksiksiz ve doğru kopyaladıysanız onlara ihtiyacınız yok. Friedrich hesabın elle yapılmasının kuramsal olarak mümkün olduğunu ama birkaç saat süreceğini, hataya çok açık olduğunu ve eğlenceli olmadığını yazıyor. Aynı nedenle elle QR kodu çizmeyi de öğretmiyor: Gereken binlerce XOR işlemi ona göre zahmete değmez. Yine de bir gün birinin bu işte ustalaşmasının kaçınılmaz olduğunu düşünüyor.
Ders, bilinçli bir sınırla geliyor: Yalnız sürüm 1-5 arası kodlar, yalnız bayt kipi ve tek parçalı mesajlar. Friedrich bu sınırı rastgele çizmemiş. Openverse üzerinden Flickr'dan Creative Commons lisanslı 1.024 QR kodu görüntüsü indirip çözümlemiş. Örnekleminde kodların yaklaşık yüzde 90'ı bayt kipini kullanıyor. Tek parçalı, bayt kipinde, sürüm 1-5 arası kodların oranı yüzde 79,8. Yani bu kurallarla gerçek dünyadaki kodların kabaca beşte dördü okunabiliyor. Örneklemin internetten toplanan görüntülerle sınırlı olduğunu ve Friedrich'in "QR kodları konusunda uzman olmadığını, güvenilir bir kaynak olduğunu iddia etmediğini" kendisinin yazdığını da not edelim.
Kötü görünen ama çalışan kodlar
Hata düzeltmenin bir de yaratıcı yanı var. Kodun bir kısmı bozulsa da okunabildiğine göre, bazı modüller bilerek değiştirilip kodun üstüne resim ya da yazı işlenebilir. Friedrich bunu bir adım ileri taşıyıp "insanın okuyabileceği QR kodları" üretiyor. Hazırladığı araç, mesajı küçük bir piksel yazı tipiyle kodun yüzeyine yazıyor. Friedrich'e göre bunu yaparken yalnız hata düzeltmeyi zorlamıyor, dolgu baytlarını, maskeyi ve hizalamayı da değiştirerek düzeltme kapasitesinin olabildiğince azını harcayan bir tasarım arıyor. Friedrich bu fikirlerin matematiği için Russ Cox'un QArt adlı yazısını öneriyor. Yazının kalitesi henüz okunması zahmetli düzeyde ama ilke açık: Kodun okunabilmesi için her modülün doğru olması gerekmiyor.
Noel Friedrich'in kendi YouTube kanalında yayımladığı videoda yöntem baştan sona anlatılıyor:
Sırada ne var?
Friedrich'in dersi bir telefonun yarım saniyede yaptığı işi saatlerce süren bir uğraşa çeviriyor. Kendisi de bunun ne heyecan verici ne de "hızlı yanıt" olduğunu, ama eğlenceli ve dinlendirici olduğunu söylüyor. Çalışma kâğıdını basılı kullanmayı öneriyor, çünkü dijital bir cihaz kullanmak "işin ruhuna aykırı". Açık kalan soru kendi koyduğu meydan okuma: Reed–Solomon hesabını kalemle yapıp sıfırdan, elle bir QR kodu çizen ilk kişi kim olacak?
Fotoğraf: Bobmath, CC BY-SA 3.0, Wikimedia Commons