理系学生日記

おまえはいつまで学生気分なのか

JavaでのQRコード生成

QR コード

あまり知られていませんが、QR コードは日本発の規格になります。 スマートフォンで打ち込むのが面倒なデータをカメラ読込のみで入力できることから世界的にも普及しておりまして、先日は iOS の Chrome に QR コードをスキャンする機能も追加されたのは記憶に新しいところです。

Java における QR コードライブラリ

Java で QR コードを作る場合、zxing (Zebra Crossing) を使用するのがスタンダードのようです。 これとは別に、QRGenというライブラリもあるのですが、こちらも内部で zxing を使用しています。QRGen については、すごく使いやすいインタフェースを提供してくれているので、そちらを使うという選択もアリだとは思います。

本日(2017/03/11) 時点でのデータは以下のとおり。

ライブラリ ライセンス Star 最終 commit
zxing Apache License 2.0 12,454 2017/03/08
QRGen Apache License 2.0 593 2016/10/31
Barcode4J Apache License 2.0 - 2012/????

zxing を用いた実装

最初に、作成した画像をそのままブラウザに返却する想定の実装例です。これにより、以下のような QR コードが生成されます。

    // QR コードで表現するコンテンツ
    final String contents = "kiririmodeのQRコード";

    // QR コード生成用のオプション
    final Map<EncodeHintType, Object> hints = new EnumMap<>(EncodeHintType.class);
    hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L);
    hints.put(EncodeHintType.MARGIN, 2);
    hints.put(EncodeHintType.CHARACTER_SET, StandardCharsets.UTF_8);

    try {
      // QR コード用一時画像ファイルの作成
      final Path path = Files.createTempFile("qr", ".png",
          PosixFilePermissions.asFileAttribute(PosixFilePermissions.fromString("rw-------")));

      // QR コードデータの生成
      final BitMatrix matrix =
          new QRCodeWriter().encode(contents, BarcodeFormat.QR_CODE, 1024, 1024, hints);
      // QR コードを画像化
      MatrixToImageWriter.writeToPath(matrix, "PNG", path);

      final HttpResponse response = new FileResponse(path.toFile(), true);
      response.setContentType("image/png");
      return response;
    } catch (WriterException | IOException e) {
      throw new RuntimeException(String.format("converting [%s] to qrcode fails", contents));
    }

QR コード生成用のオプションは、個々に EncodeHintType として表現します。

エラー訂正のレベル

まず、ERROR_CORRECTION はエラー訂正のレベルになります。QR コードは wikipedia:リードソロモン符号 をベースとしており、誤り訂正を行うことができます。

エラー訂正レベルを上げるほど、一部が隠れていたり滲んでいたりしても QR コードとして読み取ることができますが、そのぶんデータ量が多くなります。データ量が多くなれば、クライアント側の読み取り速度にも影響を与えることがあります。 デンソーに依れば、エラー訂正レベル M (15 % まで訂正可能) で使われることが多いようです。

文字コード

また、文字コードのデフォルトは、ISO-8859-1 なので、日本語が表現できません。日本語を QR コードに埋め込みたい場合は、実装例のように CHARACTER_SET に対して UTF-8 等を明示的に指定する必要があります。

バージョン

QR コードにはバージョンがありますが、これは仕様としてのバージョンではなく、その QR コードのサイズによって分類されています。 そのサイズによって当然ながら QR コードに含められる情報量は変化します。ただ、zxing はそのあたりの面倒を自動的に見てくれる (コンテンツのデータサイズによって、自動的にバージョンを判別し、それに応じたサイズの QR コードを出力してくれる) ので、実装上あまり悩むことはないと思います。

全体として

全体として、zxing はすごく使いやすいライブラリだと思います。 最初だけ、どこから手をつけれんば良いんや…という状態でしたが、色々なサンプル実装を見た後で JavaDoc を読み解けば、なるほどこうすれば書けるのかというのが掴めてきます。

個人で実装するのは相当つらそうだったので、有り難く使わせてもらおうと思います。