この記事は209年4月14日に開催された技術書典6にて頒布した「KLabTechBook Vol.4」に掲載したものです。

現在開催中の技術書典15オンラインマーケットにて新刊「KLabTechBook Vol.12」を頒布(電子版無料、紙+電子 500円)しています。 また、既刊も在庫があるものは物理本をオンラインマーケットで頒布しているほか、 KLabのブログからもすべての既刊のPDFを無料DLできます。 合わせてごらんください。

KLabTechBook Vol.12


QRコード1は、いまや誰もが知っている2次元バーコードとなりました。 日本国内でもこの数年で何社もQRコードを利用した決済サービスを提供しはじめており、 大規模なキャッシュバックキャンペーンなどでも世間を賑わせています。

ところで、このQRコードについてみなさんはどれだけ知っていますか? 決済サービス以外にもURLの共有に利用されることが多いため、 何らかの文字列を表現できるものだと思っている人が多いと思います。 実際そのとおりで、QRコードには主に文字列情報が格納されています。

そこからも想像できるとおり、QRコード自体に決済機能があるわけではありません。 QRコードから取引情報の文字列を読み取ったアプリケーションが、その情報を元に個別の処理を行っています。 つまり、決済サービスにとってQRコードである必要はまったくないのです。 読み取り精度の高さや集積度、表現できる文字種のバランスがよいため、QRコードが選ばれているのでしょう。

この章では、QRコードに文字列がどのように格納されているか具体的に見ていきたいと思います。

QRコードのモード

QRコードにはデータの種類を示す「モード」があり、 モードを切り替えながらデータを格納するようになっています。 また、データをどのようなビット列に符号化するのかも、モードごとに決められています。

ここでは代表的な4つのモードについて、 具体的にどのようなデータがどのようなビット列として表現されるのかを紹介していきます。

8ビットバイトモード

まず最初に紹介するのは8ビットバイトモードです。 その名のとおり1バイトをそのまま8ビットとして表現するモードで、 後述する他のモードに比べて空間効率がよくないモードです。 そのかわり、原理的にどんなデータでも格納することができます。

ひとつ注意すべき点として、デフォルトの文字コード解釈が実装によってまちまちだということです。 実は、JISの規格(JIS X 0510)にはデフォルトの文字コードは ISO-8859-1(Latin1)と書かれていますが、 ISOの規格(ISO/ICE 18005:2000)では JIS X 0201(JIS8)と書かれていて、混乱の元になっています。

どちらの文字コードもASCIIコード部分は互換がありますので2、その範囲内の文字だけを使うのであれば問題ありません。 非ASCIIコードを含む文字列を格納する場合は、ECIモード3によって文字コードを明示したほうがよいです。

数字モード

このモードでは、0〜9の数字だけからなる文字列が格納できます。 格納する文字列を3文字ずつに区切り、それぞれを10ビットで表現します4。 つまり、1文字あたり3.33ビットという超高密度で記録できるモードです。

たとえば「1234567890」を符号化してみましょう。 まず3文字ずつ、”012” “345” “678” “9” に分割してから、それぞれを10ビットで表現します。 モードを表すヘッダも含めるとリスト1のようなビット列を格納することになります。

▼リスト1 数字モードでのビット列

0001      	(数字モード)
0000001010	(文字数=10)
0000001100	(012)
0101011001	(345)
1010100110	(678)
1001      	(9)

8ビットバイトモードで同じ文字列を表す場合、 それぞれの数字をASCIIコードで表現するのでリスト2のようなビット列を格納することになります。

▼リスト2 8ビットバイトモードでのビット列

0100    	(8ビットバイトモード)
00001010	(データ長=10)
00110000	(ASCII `0')
00110001	(ASCII `1')
00110010	(ASCII `2')
00110011	(ASCII `3')
00110100	(ASCII `4')
00110101	(ASCII `5')
00110110	(ASCII `6')
00110111	(ASCII `7')
00111000	(ASCII `8')
00111001	(ASCII `9')

これらのQRコードを図1に示します。 8ビットバイトモードでは数字モードよりも格納するデータ量が多いため、 最小のドット数のQRコードに収まらず、1段階ドット数の多いものにしました5

数字モードのQRコード(左)と8ビットバイトモードのQRコード(右)
▲図1 数字モードのQRコード(左)と8ビットバイトモードのQRコード(右)

英数字モード

このモードは、数字に加えてアルファベットの大文字、スペース、 8つの記号6の計45種の文字を格納できるモードです。

45種類の文字を0〜44にマッピングし、 先頭から2文字ずつ、次のように計算した値を格納していきます7

1文字目の値 * 45 + 2文字目の値

この値の最大値は 45 * 45 = 2025 なので11ビットに収まります。 つまり1文字あたり5.5ビットとなり、8ビットバイトモードにくらべて45%以上多くの情報を格納できます。

それでは、同じサイズ、同じエラー訂正レベルのQRコードに「QR-CODE/」を何回格納できるか、 英数字モードと8ビットバイトモードで比べてみましょう。

英数字モードでは「QR-CODE/」はリスト3のように符号化されます。

▼リスト3 英数字モードでのビット列

10010101101	(`Q'=26, `R'=27, 26*45+27=1197)
11101000001	(`-'=41, `C'=12, 41*45+12=1857)
10001000101	(`O'=24, `D'=13, 24*45+13=1093)
01010100001	(`E'=14, `/'=43, 14*45+43=673)

一方8ビットバイトモードでは、ASCIIコードをそのままリスト4のように符号化します。

▼リスト4 8ビットバイトモードでのビット列

01010001	(ASCII `Q')
01010010	(ASCII `R')
00101101	(ASCII `-')
01000011	(ASCII `C')
01001111	(ASCII `O')
01000100	(ASCII `D')
01000101	(ASCII `E')
00101111	(ASCII `/')

これを格納したQRコードを図2に示します。 読み取っていただくと分かるとおり、英数字モードでは「QR-CODE/QR-CODE/QR-C」まで格納できていますが、 8ビットバイトモードでは「QR-CODE/QR-COD」までしか格納できません。

英数字モードのQRコード(左)と8ビットバイトモードのQRコード(右)
▲図2 英数字モードのQRコード(左)と8ビットバイトモードのQRコード(右)

漢字モード

不思議に思うかもしれませんが、世界中で使われているQRコードの規格には、日本語の文字を格納するためのモードがあります。 QRコードを発明したのは株式会社デンソーの開発部門(現:株式会社デンソーウェーブ)で、日本生まれなのです。

Shift_JISの2バイト文字は、1バイト目が819FE0EF、 2バイト目が40FC8の範囲にコードされています。 1バイト目の値を詰めると002Eで表すことができ、 また2バイト目から40を引くと00BCで表すことができます。 1バイト目から計算した値にC0を掛けたものを2バイト目から計算した値に足して記録すると、 その値をC0で割った商から1バイト目、余りから2バイト目を取り出すことができます。

このモードではEBBFまでの文字を格納することができ9、最大の値は2A*C0 + BF-40 = 1FFFなので、13ビットで表すことができます。 つまり、8ビットバイトモードに比べて1文字あたり3ビットお得になります。

それでは、「技術書典」を漢字モードで格納してみましょう。 それぞれの文字を符号化するとリスト5のようになります。

▼リスト5 漢字モードでのビット列

1000         	(漢字モード)
00000100     	(文字数=4)
0011110011010	(`技'=8B5A, (8B-81)*C0+(5A-40)=079A)
0101010110000	(`術'=8F70, (8F-81)*C0+(70-40)=0AB0)
0101011010001	(`書'=8F91, (8F-81)*C0+(91-40)=0AD1)
0110110010100	(`典'=9354, (93-81)*C0+(54-40)=0D94)

これまで同様、8ビットバイトモードで符号化した場合はリスト6のようになります。 文字コードはUTF-8でもよいのですが、漢字モードに合わせてShift_JISにしました。 ECIモードでShift_JISであることを明示もしています。

▼リスト6 8ビットバイトモードでのビット列

0111            	(ECIモード)
00010100        	(Shift_JIS=20)
0100            	(8ビットバイトモード)
00001000        	(データ長=8)
1000101101011010	(`技'=8B5A)
1000111101110000	(`術'=8F70)
1000111110010001	(`書'=8F91)
1001001101010100	(`典'=9354)

これらを格納したQRコードを図3に示します。 8ビットバイトモードのデータ量は最小ドット数のQRコードには収まらないので、ドット数の多いものに格納しています。

漢字モードのQRコード(左)と8ビットバイトモードのQRコード(右)
▲図3 漢字モードのQRコード(左)と8ビットバイトモードのQRコード(右)

まとめ

今回は、QRコードにはデータをより効率よく格納するためのモードが備わっていることを紹介しました。

しかし現在広く使われているURLを格納するという用途には、 これらの空間効率のよいモードは表現できる文字種が足りず、8ビットバイトモードを使うしかありません。

そして、QRコードといえばURLという使われ方があまりにも浸透してしまったため、 8ビットバイトモードにしか対応していない手抜き実装なQRコードリーダーも存在するらしいです。 さらにいえば、8ビットバイトモードにはデフォルトの文字コードが規格によって異なるという問題もあります。

誰もが知っているQRコードですが、本当に誰でも読み取れるようにするためには、これらの事情を考慮しなくてはいけません。 それでもQRコードの読み取りやすさと十分な表現力は、これからもさまざまなサービスで利用されていくでしょう。

QRコード関連の実装をする際にはちょっとだけ思い出していただけると幸いです。


コラム: 某コミュニケーションツールのQRコードリーダー

おそらく多くの日本人のスマートフォンに入っているであろう某コミュニケーションツールにもQRコードリーダーが付属しており、 これを常用している人も少なからずいるのではないでしょうか。

しかし、そのQRコードリーダーでこの章に掲載したQRコードを読み取ると、対応していないフォーマットとしてエラーになると思います。

こちらで調べた限りでは、そのQRコードリーダーは「http://」など特定の文字列で始まっているもの以外はエラーとして扱うようです。 ご注意ください。


  1. QRコードは株式会社デンソーウェーブの登録商標です 

  2. 厳密には、5Cを「\」とするか「¥」とするかという違いがあります 

  3. 拡張チャネル解釈(Extended Channel Interpretations)モード。詳細は省きますが、これによって文字コードを指定できます 

  4. 末尾に余った桁がある場合、2文字なら7ビット、1文字なら4ビットで表します 

  5. エラー訂正レベルを下げることでも格納データ量は増やせますが、読み取りエラー耐性は下がります 

  6. $ % * + - . / : の8種類 

  7. 1文字余った場合は、その文字を最後に6ビットで表現します 

  8. 7Fも使われていませんが説明を簡単にするために省いています 

  9. この範囲を超える文字は漢字モードで格納することができませんが、JIS第2水準漢字までを十分にカバーしています