ZXing付属のバーコード読み取りプログラム

オープンソースのバーコード処理ライブラリである「ZXing」を利用すれば、JavaやAndroidのアプリケーションにおいて手軽にバーコードの生成や読み取りができるようになる。前回はZXingを使ってJavaプログラムからQRコードを生成する方法を紹介したので、今回は画像データとして保存されているQRコードを読み込んで中に格納されている情報を取得する方法を解説する。

その前に、ZXingのJavaSE用ライブラリにはコマンドラインで利用するバーコードリーダのサンプルプログラムが付属しているので、まずはこれを使ってQRコードの情報を取得してみよう。このコマンドラインプログラムの本体はcom.google.zxing.client.j2se.CommandLineRunnerというクラスである。使用するには、core.jarとjavase.jarをクラスパスに含めた上でjavaコマンドで該当のクラスを実行し、引数にバーコードが記載された画像ファイルを指定する。たとえば前回のサンプルプログラムで作成したmycode.png(図1)の情報を読み取らせるにはプロンプト1のようにすればよい。

図1 「マイコミジャーナル: http://journal.mycom.co.jp/」というテキストを格納したQRコード「mycode.png」

プロンプト1

> java -cp core.jar;javase.jar com.google.zxing.client.j2se.CommandLineRunner mycode.png
file:/C:/work/zxing-1.6/mycode.png (format: QR_CODE, type: TEXT):
Raw result:
マイコミジャーナル: http://journal.mycom.co.jp/
Parsed result:
マイコミジャーナル: http://journal.mycom.co.jp/
Also, there were 4 result points.
  Point 0: (31.5,97.5)
  Point 1: (31.5,31.5)
  Point 2: (97.5,31.5)
  Point 3: (88.5,88.5)

このように、mycode.pngに記載されたバーコードはQRコードであり、内容はテキストで「マイコミジャーナル: http://journal.mycom.co.jp/」だということがわかる。4つの座標は位置検出パターン(3つの大きい四角)およびアラインメントパターン(右下の小さい四角)の座標である。

JavaプログラムでQRコードを読み取る

続いて、自分でQRコードに格納された情報を読み取るプログラムを作ってみよう。ZXingには、バーコードデータをデコードするためのcom.google.zxing.Readerインタフェースが用意されている。このインタフェースの実装クラスを利用すればさまざまなフォーマットのバーコードをデコードし、そこに格納された情報を取得することができる。ただし、デコードするにはバーコードデータをcom.google.zxing.BinaryBitmapオブジェクトとして保持しておく必要がある。

BinaryBitmapオブジェクトは、バーコードのソースを表すcom.google.zxing.LuminanceSourceオブジェクトより、com.google.zxing.Binarizerクラス経由で生成できる。LuminanceSourceオブジェクトは、その実装クラスであるBufferedImageLuminanceSourceクラスのコンストラクタにjava.awt.image.BufferefImageオブジェクトを渡すことで生成できる。したがって、元となるバーコードの画像をBufferefImageとして取得することができれば、それをデコードすることが可能になるというわけだ。

Java SEの場合にはjavax.imageio.ImageIOクラスの各種メソッドを利用すれば、ファイルや入力ストリームからさまざまな形で画像データを取り込むことができるようになっている。今回はQRコードが記載された画像ファイルをBufferefImageオブジェクトとして取得したいわけなので、ImageIOのread()メソッドが利用できる。以上とまとめて、画像ファイルからBinaryBitmapオブジェクトを生成するコード例は以下のようになる。

リスト1

BufferedImage image = ImageIO.read(new File("mycode.png"));
LuminanceSource source = new BufferedImageLuminanceSource(image);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));

BinaryBitmapとして取得したバーコードデータをデコードするには、Readerクラスのdecode()メソッドを利用する。次のコードは、Readerを実装したMultiFormatReaderクラスを利用してデコードを行う例。com.google.zxing.MultiFormatReaderはさまざまなバーコードの読み込みをサポートしたクラスで、QRコード以外のバーコードもデコードすることが可能。もしバーコードのフォーマットがあらかじめ判明しているならば、代わりにcom.google.zxing.qrcode.QRCodeReaderクラスのように特定のフォーマット向けのReaderクラスを利用してもよい。

リスト2

Reader reader = new MultiFormatReader();
Result result = reader.decode(bitmap);

decode()メソッドはデコード結果をcom.google.zxing.Resultクラスのインスタンスに格納して返す。あとはこのクラスのメソッドを利用して、デコードされた情報を取得すればよい。以下に、前述の画像ファイル「mycode.png」のQRコードから情報を読み取るプログラムの例を示す。

リスト3

/* import宣言は省略 */

public class BarcodeReadSample {
    public static void main(String[] args) {
        // マルチフォーマット対応の入力ストリームを生成
        Reader reader = new MultiFormatReader();

        try {
            // 画像を読み込んでビットマップデータを生成
            BufferedImage image = ImageIO.read(new File("mycode.png"));
            LuminanceSource source = new BufferedImageLuminanceSource(image);
            BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));

            // デコードを実行
            Result result = reader.decode(bitmap);

            // フォーマットを取得
            BarcodeFormat format = result.getBarcodeFormat();
            System.out.println("フォ-マット: " + format);
            // コンテンツを取得
            String text = result.getText();
            System.out.println("テキスト: " + text);

            // 位置検出パターンおよびアラインメントパターンの座標を取得
            ResultPoint[] points = result.getResultPoints();
            System.out.println("位置検出パターン/アライメントパターンの座標: ");
            for (int i=0; i < points.length; i++) {
                System.out.println("    Point[" + i + "] = " + points[i]);
            }
        } catch (NotFoundException ex) {
            ex.printStackTrace();
        } catch (ChecksumException ex) {
            ex.printStackTrace();
        } catch (FormatException ex) {
            ex.printStackTrace();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
}

ResultクラスのgetBarcodeFormat()メソッドは、バーコードのフォーマットを表すcom.google.zxing.BarcodeFormatオブジェクトを返す。これによってそのバーコードがどのフォーマットでエンコードされたものなのかがわかる。肝心のコンテンツを取得するのはgetText()メソッドである。または、生のバイトデータとして取得するgetRowBytes()メソッドなどもある。

com.google.zxing.ResultPointは2次元バーコードに含まれる位置検出パターンやアラインメントパターンなどのの座標を表すクラスである。getResultPoints()メソッドはこのクラスの配列を返すので、そこから画像内のバーコードの位置情報を取得することができるようになっている。

このBarcodeReadSampleクラスをコンパイルして実行すると以下のような結果が出力される。前述のコマンドラインツールの結果と比べれば、正しく情報が読み取れていることがわかる。

プロンプト2

フォ-マット: QR_CODE
テキスト: マイコミジャーナル: http://journal.mycom.co.jp/
位置検出パターン/アライメントパターンの座標:
    Point[0] = (31.5,97.5)
    Point[1] = (31.5,31.5)
    Point[2] = (97.5,31.5)
    Point[3] = (88.5,88.5)

ところで、以上はJava SEでZXingを利用する例である。これがAndroidになると、肝心のBufferedImageクラスが標準APIには含まれていないため同じコードを使うことはできない。次回はAndroidでZXingによるバーコードの読み取りを行う方法を紹介する。