忍者ブログ

軽Lab

 Javaを中心とした、プログラミング関係のナレッジベース

Home > > JavaFXでQRコードの作成・読込(ZXingライブラリ)

JavaFXでQRコードの作成・読込(ZXingライブラリ)

×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

Home > > JavaFXでQRコードの作成・読込(ZXingライブラリ)

- ランダム記事 -

コメント

ただいまコメントを受けつけておりません。

Home > JavaFX入門 > JavaFXでQRコードの作成・読込(ZXingライブラリ)

JavaFXでQRコードの作成・読込(ZXingライブラリ)

JavaFXと銘打ってはいるが、Zxingライブラリ自体はwebアプリケーションでもスマートフォン(Android)でもJava環境上であれば動作する。


■ Zxingライブラリ

 ZxingライブラリはGoogleが公開しているバーコード作成・読取ライブラリである。ライセンスは『Apache License 2.0』であるため、商用利用も可能である。ライブラリは以下で公開されている。

表:ライブラリの公開場所
場所 URL
ソースコード GitHub 「Zxing」
コンパイル済みjarファイル Nexus Repository Manager 「Zxing」

 JavaFXで利用する場合に必要となるライブラリ・ファイルは以下の2つである。利用する際にはクラスパスを通すことを忘れてはいけない(別記事『クラスパスの通し方』)。

  1. core-○○.jar
  2. javase-○○.jar

 バーコードにもいろいろな規格が存在し、zxingではよく使われるバーコードの作成・読込が可能となっている(*1)。スーパーなどで利用されている規格「EAN-13(JAN-13)」やQRコードにも対応している。

■ サンプル・プログラム(バーコード作成)

 以下にEAN-13バーコードとQRコードを生成するサンプルプログラムを示す。

◇サンプルコード
package application;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.oned.EAN13Writer;
import com.google.zxing.qrcode.QRCodeWriter;

import javafx.application.Application;
import javafx.embed.swing.SwingFXUtils;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class TestZxing extends Application
{

    public static void main(String[] args)
    {
        launch(args);
    }
    
    @Override
    public void start(Stage primaryStage) throws Exception
    {
        // フォント色がおかしくなることへの対処
        System.setProperty( "prism.lcdtext" , "false" );
        
        // シーングラフの作成
        VBox                root        = new VBox();
        root.getChildren().add( createBarcode( "1234567890128" , 200 , 40 ) );                  // 1次元バーコードの作成
        root.getChildren().add( createQRcode( "http://krr.blog.shinobi.jp/" , 100 , 100) );     // QRコード(2次元バーコード)の作成
        
        // シーンの作成
        Scene   scene       = new Scene( root , 250 , 200 );
        
        // ウィンドウ表示
        primaryStage.setScene( scene );
        primaryStage.show();
    }

    /**
     * 1次元バーコードの作成
     * 
     * @param str QRコード化する文字列
     * @param width QRコードの横幅
     * @param height QRコードの高さ
     * @return QRコードイメージ
     * @throws Exception
     */
    protected Node createBarcode( String str, int width , int height ) throws Exception
    {
        // ルートノードの作成
        VBox            root    = new VBox();
        
        // バーコード作成
        EAN13Writer     writer  = new EAN13Writer();
        BitMatrix       mat     = writer.encode( str , BarcodeFormat.EAN_13, width, height);
        
        // ビット情報からJavaFXのImageクラスに変換
        Image           img     = SwingFXUtils.toFXImage( MatrixToImageWriter.toBufferedImage( mat ) , null );
        
        // シーングラフ用ノードに登録
        ImageView       view    = new ImageView( img );
        Label           label   = new Label( str );
        root.getChildren().addAll( view , label );
        
        return root;
    }

    /**
     * QRコードの作成
     * 
     * @param str QRコード化する文字列
     * @param width QRコードの横幅
     * @param height QRコードの高さ
     * @return QRコードイメージ
     * @throws Exception
     */
    protected Node createQRcode( String str , int width , int height ) throws Exception
    {
        // QRコード作成
        QRCodeWriter    writer  = new QRCodeWriter();
        BitMatrix       mat     = writer.encode( str ,  BarcodeFormat.QR_CODE , width , height );
        
        // ビット情報からJavaFXのImageクラスに変換
        Image           img     = SwingFXUtils.toFXImage( MatrixToImageWriter.toBufferedImage( mat ) , null );
        
        // シーングラフ用ノードに登録
        ImageView       view    = new ImageView( img );
        
        return view;
    }

}

◇実行結果

◇解説
 EAN-13バーコードの作成はcreateBarcode関数(37行目)、QRコードの作成はcreateQRcode関数(38行目)で行っている。バーコードの生成は作成したい規格のWriterを作成し、Writer::encode関数を呼び出せばよい(65行目~66行目、91行目~92行目)。zxingライブラリはSwing時代に作られたものなので、作成された画像はSwingのImageクラスである。このため、画像イメージはSwingFXUtils::toFXImage関数で変換する必要がある(69行目、95行目)。

 注意が必要な点としては、EAN-13バーコードの13桁目の数字はチェック・ディジットになっている点である。適当な13桁の数字を入力とするとエラーになるため、チェック・ディジット計算用のサイト(*5)などで値を計算する必要がある。


■ サンプル・プログラム(バーコード読取)

 以下にEAN-13バーコードとQRコードを読み込むサンプルプログラムを示す。サンプルでは、読取に成功するもの「multiple1.png」「ean13.pn」と失敗するもの「multiple2.png」の例を確認している。バーコード画像は手元にあるものを利用しても問題ないが、バーコード画像はバーコードの周辺がある程度の余白で囲まれている必要がある(*8)。

◇リソース
ファイル名 リソース
multiple1.png
multiple2.png
ean13.png

◇サンプルコード
package application;

import java.awt.image.BufferedImage;
import java.io.File;
import java.util.Hashtable;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.LuminanceSource;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.Reader;
import com.google.zxing.Result;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.multi.GenericMultipleBarcodeReader;

import javafx.application.Application;
import javafx.embed.swing.SwingFXUtils;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class TestZxingDecode extends Application
{

    public static void main(String[] args)
    {
        launch(args);
    }
    
    @Override
    public void start(Stage primaryStage) throws Exception
    {
        // フォント色がおかしくなることへの対処
        System.setProperty( "prism.lcdtext" , "false" );
        
        // シーングラフの作成
        VBox                root        = new VBox();
        
        // バーコードを取り込み、結果を画面に表示
        // 正常に読み込める場合1
        File        file1   = new File( "img/multiple1.png" );
        Image       img1    = new Image( file1.toURI().toString() );
        root.getChildren().add( readBarcode( img1 ) );

        // 正常に読み込める場合2
        File        file2   = new File( "img/ean13.png" );
        Image       img2    = new Image( file2.toURI().toString() );
        root.getChildren().add( readBarcode( img2 ) );
        
        // 失敗する場合
        File        file3   = new File( "img/multiple2.png" );
        Image       img3    = new Image( file3.toURI().toString() );
        root.getChildren().add( readBarcode( img3 ) );
        
        // シーンの作成
        Scene   scene       = new Scene( root , 500 , 300 );
        
        // ウィンドウ表示
        primaryStage.setScene( scene );
        primaryStage.show();
        
        
    }

    /**
     * バーコードの取込
     * @param img
     * @return
     * @throws Exception
     */
    protected Node readBarcode( Image fxImg ) throws Exception
    {
        // ルートノードの作成
        HBox            root    = new HBox();

        // 画像フォーマット変換
        // JavaFXのImageクラス→SwingのImageクラス→Zxing用の画像クラス
        BufferedImage   swImg   = SwingFXUtils.fromFXImage( fxImg , null );
        LuminanceSource source  = new BufferedImageLuminanceSource( swImg );
        BinaryBitmap    bitmap  = new BinaryBitmap( new HybridBinarizer( source ) );
        
        // バーコード読込
        String  str     = "";
        try {
            // デコード準備
            Reader                              reader      = new MultiFormatReader();
            GenericMultipleBarcodeReader        mr          = new GenericMultipleBarcodeReader( reader );
            Hashtable<DecodeHintType, Object>   decodeHints = new Hashtable<DecodeHintType, Object>();
            decodeHints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
            
            // デコード
            Result[]                        result  = mr.decodeMultiple( bitmap , decodeHints );
            if( result == null ){ throw new Exception( "バーコードを認識できませんでした" ); }
            
            // 結果取得
            for( Result r : result )
            {
                // 文字列を取得
                BarcodeFormat   format  =  r.getBarcodeFormat();
                                str     += format.name() + " : " + r.getText() + ";\n";
                
            }
        } catch (Exception e1) {
            e1.printStackTrace();
            str = "失敗";
        }
        
        // シーングラフ用ノードに登録
        ImageView       view    = new ImageView( fxImg );
        Label           label   = new Label( str );
        root.getChildren().addAll( view , label );
        
        return root;
    }

}

◇実行結果


◇解説
  実行結果を見るとバーコードの回転には対応していない模様である。コードを見てみると、バーコードの読取はreadBarcode関数で行っている(50行目、55行目、60行目)。

 readBarcode関数内(78行目~121行目)では、画像フォーマットの変換(85行目~87行目)の後にデコードを行っている。デコードにはMultiFormatReaderクラスを利用する(93行目)MultiFormat::decode関数でもバーコードの読み込みはできるが、複数のバーコードにも対応するためにGenericMultipleBarcodeReaderクラスを利用している。GenericMultipleBarcodeReader::decodeMultiple関数で読取を実行し、バーコードが読み取れない場合はNotFoundExceptionが発生する(99行目)。

 注意点として、読取画像内にバーコードが複数存在する場合に、zxingがバーコードと認識したオブジェクトが1つでも読み込めなかった場合にはNotFoundExceptionが発生することがあげられる。このため、3つ目の実行結果では読み込みに成功する2つのバーコード情報の取得もできなくなっている。

■ 参照

  1. バーコード講座 「JAN/EAN/UPC」
  2. 承認これくしょん 「Nashorn + JavaFXでQRコードを表示する」
  3. JavaDoc 「Class EAN13Writer」
  4. JavaDoc 「Class QRCodeWriter」
  5. 一般財団法人 流通システム開発センター 「JANコード、集合包装用商品コード(ITF)コードのチェックデジット計算方法」
  6. JavaDoc 「Class MultiFormatReader」
  7. JavaDoc 「Class GenericMultipleBarcodeReader」
  8. Stack Overflow 「ZXing 2.1: com.google.zxing.NotFoundException」
- PR -
Home > JavaFX入門 > JavaFXでQRコードの作成・読込(ZXingライブラリ)

- ランダム記事 -

コメント

ただいまコメントを受けつけておりません。

QRコード

プロフィール

管理者:
連絡はContactよりお願いします。

PR