観測史上最速の梅雨明けとかで、とてつもなく暑いですね。もう今から夏が怖いです。あれ、梅雨明けたからもう夏・・・?

思ったよりも時間がかかってしまいましたが、前からやってみたかったことについて書こうと思います

こんなん出力できるようになりました

まずはこのQRコードを御覧下さい。

お手持ちのスマホとかでこれを読み解くと、 01234567 という表示ができるはず・・・です(私はできた)。このQRコードは、 https://github.com/derui/ocaml-qrcode で作ったライブラリから生成してみたやつです。大体思いたってからこれを出力できるようになるまで二ヶ月くらいかかりました・・・。

ずーっと仕様書とにらめっこしていたので、何となく貼られているQRコードを見てバージョンの想像がつくようになってきました。

なんで今更QRコード?

QRコードは様々なところで見るようになりましたし、日頃何も考えずに読み取っているという方もいると思います。ただ、JANなどの一次元バーコードもそうですが、当然ですがそれを実現するための仕組み、というのがあります。それに則っていないとそもそも読み込めませんから。

JANなどのコードは一次元なので、なんとなくわかりやすいのですが、QRコードの場合は二次元バーコードということで、どういう形になっているんだろう?というのが前々から興味がありました。

本当は読み込みまで作りたかったんですが、そっちは本当に画像処理になってくるので、さらに時間がかかりそうだなぁってことで、とりあえず出力ができるようになったところでこれ書いてます。

利用したライブラリ

基本的には、数値処理のところで多少楽というか厳密に利用するために、 stdintと、画像処理のためにcamlimagesを利用したくらいで、後は大体自作しました。特に、QRコードの中の処理では、1bit単位で扱わなければならない箇所が多かったので、bitを扱えるようなライブラリを自作してます。

難しかった部分

QRコードの詳細な仕様については、JIS登録などされていて著作権保護されているので、 JISC から閲覧などしていただくのがよろしいかと思います。その仕様の中で特に難しかった部分を挙げていきます。

JISCへの登録は無料ででき、かつ閲覧自体は無料です。なんでかログインにめっちゃ時間がかかるのがとても不思議ですけども。

BCH符号

QRコードの形式情報やバージョンという情報(QRコードには40番まであるんです。物理的に見たことは無いですが)を保存するとき、 BCH符号というものを利用しています。これ、符号処理という分野では非常によく利用されるものということなのですが、私は符号処理とかほとんどやったことない(はるか昔に圧縮・展開処理とか書いたことはありますが)ので、この回路を理解するのにめちゃくちゃ時間を使いました。

最終的には大学が公開しているPDFとか読み漁って実装する感じになりました。勉強にはなりましたけども

リードソロモン符号

多分QRコードを実装しようとした人(で、数学が苦手な人)が必ず躓くポイントではないかと思います。参考

QRコードは、誤り訂正が可能で、その誤り訂正レベルは4段階あります。誤り訂正符号として利用されているのが、RS符号、となります。なのでこの符号化を実装しないと、QRコード自体実装することができません。

Wikipediaを見ても、最初から有限体とかがあたりまえのように出てきて、 有限体ってなに・・・? となることうけあいです。わたしはなりました。特にややこしいのが GF(256) などのように表現される、拡張ガロア体と呼ばれるものの計算でした。わかってしまえばなんとなく ほう・・・ ってなるのですが、この表現と生成多項式とか色んなものが同時に襲ってくるイメージでした。とても辛い。

回路自体は、BCH符号などと似た感じにはなったので、そっちができていれば流用できる感じなのですが、とにかくこの計算結果で、どれがどうなれば正しいのか?というのを探し周りました。自分で計算したらよかったんじゃないか?というものふと浮かびはしたものの、検索するとみんな悩んでるんだな・・・って感じでした。

マスク処理

よくみるQRコードは、アレはデータがそのまま記述されているのではなく、読み取り精度を向上させるために、マスクをかけています。このマスクなんですが、ファインダーパターンとよばれる、QRコードの特徴の一つでもある左上、右上、左下にある正方形の領域や、それ以外の機能パターンと呼ばれるものにはかけられません。

これを制御する・・・というのが以外と難しかったです。マスクは、マトリックスとして生成→マスクかける→マスクの情報をマトリックスに書きこむ、という処理が必要になります。そのため、理解しきらないうちに作ったOCamlのモジュール間の関係がよくわからんことになってしまったりしてます。ここは反省点です。

たまには仕事から離れたものをやるのも面白い

実際、QRコードを出したいだけなら、自分で作成する必要はどこにもありません。制定自体結構前からあるものなので、出力したりするためのものはそこらじゅうにあるのは事実です。

しかし、作る過程で得られる知識であったり、作るという経験は中々得難いものじゃないかなーと思っています。仕事でやることばっかやってると滅入るってものありますけど。

もうちょっと頑張って読み取りまでできるようにしてみたいですが、これは気長にやっていこうかなと思います。出力もまだやらんとあかんことがいっぱいあるので。