カメラで読めないQRコードの正体と、中身の見方

ゲームのカードに印刷されたQRコード。公的機関が発行する書類の隅にあるQRコード。職場の伝票や部品ラベルに貼られたQRコード。カメラを向けても、何も起きない。読み取り枠は出ているのに、URL も文字列も出てこない。

そんなQRコードを手にして、「これは一体なんだろう」と思ったことはありませんか。コードが壊れているわけでも、端末が古いわけでもないかもしれません。

まずは実物で確認

まず実物を見てください。この記事のために用意したQRコードです。

白地に黒のQRコード。この記事のために作成したサンプルで、テキストではないバイナリデータが 14 バイト入っている。

スマートフォンのカメラアプリを向けてみてください。多くのアプリでは何も出てきません。アプリによっては、記号や見慣れない文字が並んだ文字列が出ます。エラーになるアプリもあります。

この記事をスマートフォンで読んでいて、画面のQRコードにカメラを向けられない場合は、スクリーンショットを撮ってから、画像のコードを読み取れるアプリで試してください。

このコードは実在の製品やサービスのデータではありません。説明のために作った独自のサンプルです。

QRコードに入れられるデータの種類

世の中のQRコードの多くには、URL や連絡先といったテキストが入っています。カメラアプリはそれを前提に、読み取った内容を文字として表示します。

ただし、規格が扱えるデータはテキストだけではありません。QRコードを開発した株式会社デンソーウェーブの公式サイトは、格納できるデータの種類として「数字」「英数字」「8 ビットバイト(バイナリ)」「漢字」の 4 つを挙げ、1 つのコードの中で混在させられるとしています(出典: QRコード規格化・標準化|株式会社デンソーウェーブ)。

このうち、「8 ビットバイト(バイナリ)」には、任意のバイト列を入れられます。 文字とは限りません。アプリやゲームが独自に決めた形式のデータを、そのまま詰めることができます。

読めないQRコードは、これかもしれません。中身が最初から文字ではないので、文字として表示しようとしても出せるものがありません。カメラアプリはコードを認識してはいるのに結果を出さず、読み取りに失敗したときと同じ見え方になります。

文字化けの正体

アプリによっては、テキストではないバイト列を無理にテキストとして表示しようとします。

上のQRコードを強制的にテキストとして読むと、こうなります。

QR<SOH>*<NUL>ÿ{<DLE>ã<U+81><U+9F>ÀZ<ETX>

<SOH> や <NUL> は、文字として表示できない制御文字を記号で書いたものです。これは、QRコードなどのバーコードの読み取りを行うライブラリ zxing-cpp で読み取った文字列を、制御文字を記号に置き換えて書き写したものです。アプリによって見え方は異なります。

意味が通らないのは、データが壊れているからではありません。中身に対して見せ方が合っていないだけです。写真のファイルをテキストエディタで開いたときと同じことが起きています。

中身の確かめ方

中身が文字でないなら、無理に文字へ変換するより、バイト列のまま見るほうが確実です。

QRefine は、そういうQRコードのために作ったアプリです。バイナリデータを無理にテキストへ変換せず、読み取ったデータを 16 進のバイト列で表示します。テキストとして読めない場合でも、このバイト列はテキスト欄と同じ画面に必ず表示されます。カメラのほか、写真ライブラリやスクリーンショットの中にあるコードも読み取れます。

ダウンロード無料(アプリ内課金あり)

上のQRコードを QRefine で読み取ると、画面はこうなります。

QRefine のコード詳細画面のスクリーンショット。テキストの欄が「(Binary Data)」と表示され、その下のバイナリ(16進)の欄に 5152012A00FF7B10E3819FC05A03 が並んでいる。

バイナリ(16進)の欄に並ぶ 14 バイトが、このコードの中身そのものです。

テキストの欄の「(Binary Data)」は、制御文字を含むか UTF-8 として読めないバイト列のときに出ます。

もう一つの原因、文字コードの解釈違い

中身がテキストなのに文字化けする場合もあります。書いたときと読むときで、文字コードが食い違っているケースです。

たとえば「名前」の 2 文字は、文字コードによって次のバイト列になります。

UTF-8     : E5 90 8D E5 89 8D
Shift_JIS : 96 BC 91 4F

96 BC 91 4F は UTF-8 としては成立しないので、読み取れなかった部分が ���O のような置換文字になります(どう見えるかはアプリによります)。逆に E5 90 8D E5 89 8D を Shift_JIS として読むと 蜷榊燕 になります。同じデータでも、読み方が違えば別の文字列に見えます。

QRefine では、読み取ったあとにテキストの読み方を選び直せます。選べるのは「読み取ったまま」「QR の指定に従う」「UTF-8」「Shift_JIS」「ISO-8859-1」の 5 つです。元のデータは書き換わらないので、いつでも戻せます。意味の通る文字列になれば、その読み方はデータと矛盾しないということです。ただし、それで作ったときの文字コードが判明するわけではありません。ASCII だけのデータはどの読み方でも同じ文字列になりますし、違う解釈でもたまたま読めてしまうことがあります。

Android でカメラから読み取る場合は、事前にカメラタブの「詳細情報を取得」を有効にしてください(画像から読み取る場合は不要です)。

まとめ

  • 読めないQRコードは、壊れているとは限りません。テキストではないバイナリデータが入っていることがあります
  • 文字化けは、そのバイト列を無理にテキストとして表示した結果です
  • 中身を確かめるには、文字に変換せず、16 進のバイト列のまま見ます
  • テキストが入っているのに読めない場合は、文字コードの解釈違いを疑い、読み方を切り替えて試します
  • どのアプリでも読み取り枠すら出ない場合は、中身ではなく画像や印刷の側に原因がある可能性が高いです

QRefine をダウンロード

ダウンロード無料(アプリ内課金あり)

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