無料QRコード作成サイトの「有効期限切れ」の正体を調べたら、自分で作ることにした
無料をうたうQRコード作成サイトの多くは動的QR方式で、期限が切れるとリダイレクトが止まり読めなくなる。仕組みを調べて、期限なし・透かしなし・ブラウザ内完結のQRコード作成ツールを自作した話。誤り訂正レベルとWIFI:形式の話も。
名刺に自分のサイトのURLをQRコードで載せようとして、「QRコード 作成 無料」で検索した。上位のサイトをいくつか開いて、率直に言って引いた。
あるサイトはダウンロードボタンを押すと会員登録を求めてくる。別のサイトは無料で作れるが、生成されたコードの隅にサービスのロゴが入る。そして一番驚いたのが、利用規約の奥に「無料プランで作成したQRコードには有効期限があります」と書いてあったやつだ。
QRコードに有効期限? QRコードはただの画像で、白黒のパターンにデータが焼き込まれているだけのはず。印刷したチラシのコードが、ある日突然読めなくなるなんて原理的におかしい。おかしいと思ったので調べた。この記事はその調査結果と、結局納得できるものがなくて自分でQRコード作成ツールを作った話だ。
「有効期限」の正体は、静的QRと動的QRの違いだった
調べてわかったのは、QRコードには実質2種類の作り方があるということ。
静的QRコードは、入力した内容(URLやテキスト)をそのままコード化する。コードの中に https://clvr.lol/ という文字列が直接入っているイメージで、一度生成すれば誰のサーバーにも依存しない。だから期限切れは原理的に存在しない。読めなくなるとしたら、リンク先のページ自体を消したときだけだ。
動的QRコードは、入力したURLをそのままコード化しない。サービス側が発行した短縮URL(リダイレクトURL)をコード化して、読み取り時にサービスのサーバーを経由して本来のURLへ飛ばす。この方式には正当なメリットがあって、印刷後にリンク先を差し替えられるし、読み取り回数の計測もできる。
ただし裏返すと、サービスのサーバーが飛ばしてくれる間しかコードは機能しない。無料期間が終わる、課金をやめる、サービス自体が終了する——どれかが起きた瞬間、リダイレクトが止まって「読めないQRコード」になる。つまり「QRコードの有効期限」の正体は、コードの期限ではなくリダイレクトURLの契約期限だった。
問題だと思うのは、多くのサイトでデフォルトが動的QRになっていて、ユーザーが仕組みを知らないまま「期限つきのコード」を印刷物に刷ってしまう構造になっていることだ。無料で作らせて、期限が近づいたら「延長するには有料プランへ」と迫る。ビジネスモデルとしては理解できるが、名刺に刷るURLひとつにサブスクを契約する気にはなれなかった。
それなら自分で作る。ブラウザ内で完結する静的QRなら話は単純
静的QRの生成自体は、実はまったく難しくない。QRコードの仕様はISO/IEC 18004として標準化されていて、生成アルゴリズムを実装したオープンソースライブラリがいくらでもある。npmのqrcodeを使えば、サーバーなしでブラウザのJavaScriptだけでCanvasに描画できる。
ということで作ったのがこれ。
設計方針は検索で嫌な思いをしたことの裏返しで、3つだけ。
- 有効期限なし。作るのは静的QRのみ。サーバーを経由しないので、うちのサイトが消えてもあなたのコードは読める
- 登録不要・透かしなし。ダウンロードボタンの先に会員登録画面はない
- 入力内容を送信しない。生成は全部ブラウザ内で完結する。これはWi-Fi用QRを作るとき特に重要で、自宅のWi-FiパスワードをどこのサーバーにもPOSTせずにコードにできる
URL・テキストのほか、Wi-Fi・メール・電話・SMS用のコードに対応して、サイズ・色・余白・誤り訂正レベルを調整してPNGとSVGで保存できるようにした。印刷物にはSVGが便利で、拡大しても劣化しない。
作る過程で学んだこと1: Wi-Fi QRの「WIFI:」形式とエスケープの罠
スマホのカメラをかざすとWi-Fiに自動接続できるQRコードは、中身がただのテキストで、こういう形式になっている。
WIFI:T:WPA;S:my-home-wifi;P:mypassword;;
T:が暗号化方式、S:がSSID、P:がパスワード。仕様としては単純だが、実装してみると罠があった。この形式では \ ; , : " が特別な意味を持つので、パスワードにセミコロンが含まれていると、エスケープせずに埋め込んだコードは壊れる。テスト中に ; 入りのパスワードで見事に接続に失敗して、バックスラッシュでエスケープする処理を足した。世の中のジェネレーターにも、ここを処理していないものが普通にありそうだと思った。
学んだこと2: 誤り訂正レベルは「汚れ耐性」と「密度」のトレードオフ
QRコードには誤り訂正レベルというオプションがあって、L・M・Q・Hの4段階でおよそ7%・15%・25%・30%まで欠損を復元できる。作るまでは「高いほど良いのでは」と思っていたが、実装して理解した。復元用のデータを余分に埋め込む仕組みなので、レベルを上げるほど同じ内容でもマス目(モジュール)が細かくなる。細かいコードは小さく印刷したときにかえって読みにくい。
QRコードの中央にロゴ画像を重ねても読めるのは、このおかげだ。レベルHならコードの約3割が隠れても復元できるので、中央のロゴを「汚れ」として吸収している。逆に言えば、レベルLでロゴを重ねると普通に読めなくなる。ツールにはプレビュー下にバージョンとモジュール数を表示するようにしたので、レベルを切り替えるとコードが細かくなっていくのが見える。迷ったら標準のMで十分、屋外掲示やロゴ重ねはH、というのが実装後の結論。
学んだこと3: 「QRコード」はデンソーウェーブの登録商標
調べていて初めて知ったこと。QRコードは1994年にデンソー(現デンソーウェーブ)が開発したもので、「QRコード」という名称は同社の登録商標だ。一方で仕様は前述のとおり国際標準化されていて、デンソーウェーブは規格に沿った利用について特許権を行使しない方針を公表している。だから誰でも無償でコードを生成・利用できる。
実務上の注意はひとつだけで、チラシや名刺に「QRコード」という文言を印刷する場合は、「二次元コード」と表記するか、登録商標である旨を注記しておくのが無難ということ。コード自体を刷るのは自由だ。
読めないQRコードの3大原因も、ツール側で潰した
作っている途中で「そもそも読めないコードを作らせない」方が親切だと気づいて、警告を仕込んだ。読み取り失敗の定番は次の3つ。
- 色の反転。背景が暗くてコードが明るい「反転」コードは、多くの読み取りアプリが認識できない。ツールでは前景と背景の相対輝度を計算して、反転していたら警告を出す
- コントラスト不足。薄いグレーのコードなどはカメラが拾えない。これも比率が低いと警告する
- 余白(クワイエットゾーン)の削りすぎ。コードの周囲には4モジュール分の余白が仕様上必要で、デザイン優先で詰めると読めなくなる。デフォルトを4にして、スライダーで意図的に減らせるだけにした
印刷するなら一辺2cm以上を目安にして、配布前に必ず実機で読み取りテストをする。ここだけはツールでは代替できないので、手でやってほしい。
同じ「ブラウザ内完結」の方針で作ったツールは他にもあって、QR入りのチラシ画像を軽くしたいときは画像圧縮・リサイズツールがそのまま使える。名刺のQRコードは無事に静的QRで入稿できて、これで10年後も読める。期限の心配をしながら使うくらいなら、仕組みが単純な静的QRで作るのが一番安心だと思う。