QR コードを作っていてよくある疑問。内容はそれほど多くないのに、できあがったコードは細かくて見づらい。ところが他人の QR コードはかなり長い URL を読み取っているのに、ずっと粗く見える。
理由は QR コードの内部に4 つの符号化モードがあり、文字の種類によって通る経路が違い、占有する容量が数倍変わることがあるからです。これを理解すれば、QR コードの密度を自分でコントロールできます。
4 つの符号化モード:同じ情報でも大きさが違う
QR コードは文字の種類ごとに専用の符号化方式を用意しており、それぞれ「詰め込み効率」が異なります。
| モード | 対象の文字 | 1 文字あたり | 相対効率 |
|---|---|---|---|
| 数字モード | 0-9 | 約 3.33 ビット | 最高(約 40% 節約) |
| 英数字モード | 0-9 A-Z 空白 $%*+-./: | 約 5.5 ビット | 高い |
| バイトモード | その他すべて(漢字を含む) | 8 ビット | 基準 |
| 漢字モード | Shift-JIS の漢字 | 13 ビット | 日中で常用字ならやや有利 |
要点はここです。漢字 1 文字は UTF-8 で 3 バイト、つまり 24 ビットを占めます。英字 1 文字は 1 バイト(8 ビット)です。ですから同じ「20 文字」でも、中国語なら 480 ビット、英語なら 160 ビットで、3 倍の差がつきます。
これが中国語の QR コードが密になる最も直接的な理由です。
漢字モードは多少救うが、条件付き
QR 規格には専用の「漢字モード」があり、漢字 1 文字が 13 ビットで済み、バイトモードの 24 ビットより半分近く節約できます。魅力的に聞こえますが、厳しい制約があります。Shift-JIS に存在する漢字しか扱えないのです。
Shift-JIS は日本語の符号化で、収録されている漢字の集合は GB2312 や Unicode と完全には一致しません。したがって次のようになります。
- 多くの常用漢字は該当し、容量を節約できる
- 一部の簡体字、難字、そして漢字以外の文字(中国語の句読点や絵文字など)はバイトモードに戻るしかない
- 生成側が 2 つのモードを賢く切り替えられなければ、ほとんど節約にならない
実際のところ、多くの生成器は互換性と正確さを優先して、あえてバイトモードに統一しています。その結果、中国語の内容はすべて 24 ビット/文字で計算され、QR コードは密になります。
ついでに実用的なコツを 1 つ。中国語の句読点も 3 バイトです。句点「。」、読点「,」、頓号「、」はいずれも全角文字で、同じく 3 バイトを占めます。内容に句読点が多いなら、半角の記号に変えてみると多少節約できます。
誤り訂正レベル:冗長性と引き換えの耐性
QR コードで容量を食うもう 1 つの要素が誤り訂正符号です。リード・ソロモン符号でデータに冗長性を加え、図柄の一部が汚損しても元の内容を復元できるようにしています。4 つのレベルがあります。
- L レベル:約 7% の冗長性、約 7% の損傷を復元
- M レベル:約 15% の冗長性(最もよく使われる既定値)
- Q レベル:約 25% の冗長性
- H レベル:約 30% の冗長性で、最高の耐性
冗長性はそのまま場所を食います。同じバージョン 10(57×57 セル)でも、L レベルは 271 バイト、H レベルは 119 バイトしか入りません。実に 56% 近い減です。
ですから、画面に表示して読み取るだけの QR コードなら L か M で十分で、図柄も明らかに粗くなり読み取りやすくなります。摩耗し得る実物に印刷する場合や、中央にロゴを置く場合にだけ Q や H を使う価値があります。
中央にロゴを置けるのはまさにこの理屈です。ロゴで隠れた領域を損傷とみなし、H レベルの 30% の冗長性で補います。L レベルでロゴを置くと、ほぼ読み取れなくなります。
バージョン:QR コードの「サイズ段階」
QR コードには 40 のバージョンがあり、バージョン n の一辺は 4n + 17 セルです。
- バージョン 1:21 × 21
- バージョン 2:25 × 25
- バージョン 10:57 × 57
- バージョン 20:97 × 97
- バージョン 40:177 × 177
容量はバージョン 1 の数十バイトから、バージョン 40 の 2953 バイト(L レベル、バイトモード)まで広がります。生成器は内容の長さに応じて、足りる最小のバージョンを自動で選びます。
ここで注意すべき点が 2 つあります。
- セル数は一辺の二乗で増える。 バージョン 20 から 40 に上げても一辺は 2 倍に満たないのに、セル数は 3.3 倍になります。高バージョンの QR コードでは 1 セルが極端に小さくなります。
- セルが小さすぎると読み取れない。 理論上、安定して認識するには 1 セルあたり 2〜3 ピクセルが必要です。内容が多くてバージョン 20 以上になり、印刷サイズが大きくないと、実際には読み取れないことがよくあります。
実用的な結論:読み取りやすくするには
QR コードを鮮明で読み取りやすくしたいなら、この優先順位で最適化してください。
- 内容を短くする。 最も効果的な手段です。URL は短くできるだけ短くし、パラメータは削れるだけ削り、短縮 URL を挟んで転送するのが最も一般的です。内容が半分になれば、バージョンが何段も下がることがあります。
- 誤り訂正レベルを下げる。 画面表示なら L か M で、むやみに H を使わないこと。高いレベルが要るのはロゴを置く場合や摩耗しやすい素材に印刷する場合だけです。
- クワイエットゾーンを確保する。 QR コードの周囲には最低 4 セル分の白い余白(クワイエットゾーン)が必要で、認識アルゴリズムが境界を特定するために使います。白い縁を切り落とすのは読み取り失敗の最大の原因で、鮮明さの問題よりよく起きます。
- ピクセル数を確保する。 1 セルあたり 4 ピクセルあると安心です。バージョン 10(57 セル)なら最低 228 ピクセル幅が必要になります。
- 小さなビットマップを避ける。 どうしても画像に QR コードを埋め込むなら、書き出し時に十分な解像度を確保するか、ベクター形式(SVG)を使って拡大時のぼやけを避けてください。
自分の QR コードがどれくらい密かを知る方法
方法は 2 つあります。
1 つ目は、生成時にツールが示すバージョン番号を見ること。バージョンは低いほど読み取りやすいです。QR コード生成なら、現在の内容が使うバージョンとバイト数を表示するので、内容を変えながらバージョンの変化を見れば「数文字削るとバージョンが 1 つ下がる」感覚がつかめます。
2 つ目は、手元の QR コードをQR コード読み取りにかけて、バージョン、誤り訂正レベル、内容の種類を見ることです。長い内容のはずなのに低バージョンの QR コードなら、中に短縮 URL が入っている可能性が高いです。
どちらのツールもブラウザ内で動作し、生成した画像も読み取る画像もサーバーを経由しません。
ひと言でまとめると
QR コードの密度 = 内容のバイト数 ÷ 符号化効率 + 誤り訂正の冗長性。 中国語は 1 文字 3 バイト、句読点も 3 バイトなので、中国語のコードは本質的に密になります。粗くしたいなら最も効くのは内容を減らすことと誤り訂正レベルを下げることで、生成ツールを替えても解決しません。