現: 2024-04-09 (火) 13:49:53 yuji ソース
Line 1: Line 1:
 +* JavaでQRCodeを作成 [#i1074d87]
 +** 作成する方法 [#rec9e0a2]
 +JavaでQRCodeを作成してみる。
 +
 +QRコードを作成するためのJavaのライブラリに,ZXing(ゼブラ・クロッシング)というライブラリがある。~
 +ZXingはGoogleで開発されていて,様々な一次元/二次元のバーコードの生成/読み取りが出来るオープンソースライブラリ。Apache License 2.0で無償で利用出来ます。
 +
 +サポートされているフォーマット形式は,
 +|1D product |1D industrial |2D            |h
 +|UPC-A      |Code 39      |QR Code      |
 +|UPC-E      |Code 93      |Data Matrix  |
 +|EAN-8      |Code 128      |Aztec (beta)  |
 +|EAN-13    |Codabar      |PDF 417 (beta)|
 +|          |ITF          |MaxiCode      |
 +|          |RSS-14        |              |
 +|          |RSS-Expanded  |              |
 +です。残念ながら,''MicroQRコードはサポートしていない''ようです。
 +
 +このライブラリを使用して,QRコードを作成してみる。
 +
 +ZXing Core(ZXingの中核となるライブラリ)
 + groupId : com.google.zxing
 + artifactId : core
 + version : 3.3.2
 +ZXing Java SE Extensions(Java SEのプロジェクトで,バーコードを操作する場合のライブラリ)
 + groupId : com.google.zxing
 + artifactId : javase
 + version : 3.3.2
 +
 +Java SEで利用する場合はcoreとjavaseを,Androidの開発で利用する場合はcoreとandroidのコンポネントを利用する。
 +
 +GitHub https://github.com/zxing/zxing からダウンロードする。~
 +もしくは,jarファイルをMaven Repositoryからだと取得しやすい。~
 +https://mvnrepository.com/artifact/com.google.zxing/core/3.3.2~
 +https://mvnrepository.com/artifact/com.google.zxing/javase/3.3.2~
 +
 +ダウンロードした,以下の2つのjarファイルを使用する。
 + core-3.3.2.jar
 + javase-3.3.2.jar
 +参照できるクラスパスにコピーしておく。
 +
 +ソースコードからビルドする場合は,Mavenでビルドする。
 + $ cd work
 + $ git clone https://github.com/zxing/zxing
 + $ cd zxing
 + $ mvn -Dhttps.protocols=TLSv1.2 package
 +java 7の場合は,TSL 1.2を指定してビルドする。使用するのは,coreとjavaseに作成されたjarファイル。
 +
 +** QRCodeの画像をエンコードする [#l17e292a]
 +QRCodeの画像を作成する方法は,以下のようなプログラムを作成。
 +
 +''QRCodeEncoder.java''
 +#code(java,nonumber){{
 +import com.google.zxing.BarcodeFormat;
 +import com.google.zxing.EncodeHintType;
 +import com.google.zxing.WriterException;
 +import com.google.zxing.client.j2se.MatrixToImageWriter;
 +import com.google.zxing.common.BitMatrix;
 +import com.google.zxing.qrcode.QRCodeWriter;
 +import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
 +import java.awt.image.BufferedImage;
 +import java.io.File;
 +import java.io.IOException;
 +import java.util.concurrent.ConcurrentHashMap;
 +import javax.imageio.ImageIO;
 +
 +/**
 + * JavaでQR Codeを作成
 + * @author Yuji Ueno
 + */
 +public class QRCodeEncoder {
 +
 +    public static void main(String[] args) throws WriterException, IOException {
 +     // QRコード生成したい文字列
 +     String source = "上野雄二";
 +     // QRコード生成時のエンコーディング
 +     String encoding = "Shift_JIS";
 +     // サイズ(ピクセル)
 +     int size = 100;
 +     // 画像ファイルの保存先
 +     String filePath = "qrcode.png";
 +    
 +     // 生成処理
 +     ConcurrentHashMap hints = new ConcurrentHashMap();
 +     //エラー訂正レベル指定
 +     hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
 +     //エンコーディング指定
 +     hints.put(EncodeHintType.CHARACTER_SET, encoding);
 +     //マージン指定
 +     hints.put(EncodeHintType.MARGIN, 0);
 +    
 +     QRCodeWriter writer = new QRCodeWriter();
 +     BitMatrix bitMatrix = writer.encode(source, BarcodeFormat.QR_CODE, size, size, hints);
 +     BufferedImage image = MatrixToImageWriter.toBufferedImage(bitMatrix);
 +    
 +     //ファイルへの保存処理
 +     ImageIO.write(image, "png", new File(filePath));
 +    }
 +}
 +}}
 +
 +コンパイルして,動作確認してみる。
 + $ javac -encoding UTF-8 QRCodeEncoder.java
 + $ java QRCodeEncoder
 +qrcode.pngのファイル名で画像が作成されている。
 +#ref(qrcode.png)
 +
 +画像の色を変更したい場合には,MatrixToImageWriter.toBufferedImage()の第2引数に,MatrixToImageConfigを指定することで可能。
 + // 青と白で表示
 + MatrixToImageConfig config = new MatrixToImageConfig(0xff0000ff, 0xffffffff);
 + BufferedImage bufferedImage = MatrixToImageWriter.toBufferedImage(matrix, config);
 +
 +画像ではなく,文字列でもよければBitMatrix.toString()が使える。
 +
 +** ヒント情報(EncodeHintType) [#hc73705d]
 +QRCodeを作る際に,いくつかヒント情報を指定することが出来る。
 +
 +ヒント情報は,Mapで指定する。~
 +キーは,列挙型のEncodeHintTypeを使用するが,キーによって値の型が異なるためMap<EncodeHintType, Object>で定義する。
 +
 +また,キーが列挙型なのでEnumMapが使用出来る。
 +
 +** 誤り訂正レベル [#j7652ff7]
 +誤り訂正レベルは,以下のように指定する。~
 + キー : EncodeHintType.ERROR_CORRECTION
 + 値 : 列挙型の ErrorCorrectionLevel で指定する
 +     ErrorCorrectionLevel.L : 7%まで訂正可能(デフォルト)
 +     ErrorCorrectionLevel.M : 15%まで訂正可能
 +     ErrorCorrectionLevel.Q : 25%まで訂正可能
 +     ErrorCorrectionLevel.H : 30%まで訂正可能
 +
 +ちなみに,QRCodeにイラストなどを載せても読み取れるのは,この誤り訂正能力のおかげ。
 +
 +** 文字セット [#wb0d775a]
 +文字セットは,以下のように指定します。
 + キー : EncodeHintType.CHARACTER_SET
 + 値 : 文字列( String )で文字セット名を指定
 +     デフォルトは "ISO-8859-1"
 +
 +デフォルトは,上記のように"ISO-8859-1"(いわゆる ISO-Latin-1)なので,日本語が使えない。~
 +必要であれば日本語が扱える文字セットを指定する必要がある。
 +
 +後述のように,"Shift_JIS"の文字セット名は特別な対応があります(詳細は「モード」を参照)。
 +
 +** マージン [#we109dc3]
 +マージンは,以下のように指定する。
 + キー : EncodeHintType.MARGIN
 + 値 : 上下左右のマージンをセル数( Integer )で指定
 +     デフォルトは 4
 +
 +QRCodeには,周囲に4セル以上のマージンを必要とする。
 +普通は,デフォルトのままで十分だと思う。
 +もし,表示する際に画像の周りに余白を別途用意するなら,マージンには0を指定しても大丈夫。
 +
 +** モードやバージョンを取得する [#m2860f45]
 +QRCodeには,「モード」や「バージョン」といった情報がありますが,基本的に自動的に判定される。
 +上記の方法では,実際に適用された「モード」や「バージョン」は取得出来ない。
 +
 +もしなんらかの理由で,「モード」や「バージョン」が必要な場合(例えば,「バージョン」によって画像のサイズを
 +変えるなど)は,Encoderを使用する。
 +#code(java){{
 +package net.the_blue_pla.net.qrcode;
 +
 +import java.nio.charset.Charset;
 +import java.util.EnumMap;
 +import java.util.Map;
 +import java.util.Objects;
 +
 +import com.google.zxing.EncodeHintType;
 +import com.google.zxing.WriterException;
 +import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
 +import com.google.zxing.qrcode.encoder.Encoder;
 +import com.google.zxing.qrcode.encoder.QRCode;
 +
 +public class QRCodeUtils {
 +
 +    public static QRCode createQRCode(String contents, ErrorCorrectionLevel level, Charset charset)
 +     throws WriterException {
 +     Objects.requireNonNull(contents);
 +     Objects.requireNonNull(level);
 +     Objects.requireNonNull(charset);
 +     if (!charset.canEncode()) {
 +     // エンコード不可
 +     throw new IllegalArgumentException("cannot encode: " + charset.displayName());
 +     }
 +    
 +     Map<EncodeHintType, Object> hints = new EnumMap<>(EncodeHintType.class);
 +     hints.put(EncodeHintType.CHARACTER_SET, charset.displayName());
 +    
 +     QRCode code = Encoder.encode(contents, level, hints);
 +     return code;
 +    }
 +}
 +}}
 +注意:MatrixToImageWriter を使っていないので,「ZXing Java SE Extensions」は不要。
 +
 +com.google.zxing.qrcode.encoder.QRCode
 +
 +QRCodeは,以下の情報を持っている。
 + QRCode#getVersion() - バージョン
 + QRCode#getECLevel() - 誤り訂正レベル
 + QRCode#getMode() - モード
 + QRCode#getMatrix() - QRコードの白黒情報
 +
 +QRCodeから画像データを直接作るメソッドなどは用意されていないが,QRCode.getMatrix() から必要な情報は取得可能。
 +
 +QRCodeから独自に画像を作るなら,QRCodeWriterとMatrixToImageWriterが参考になる。(面倒なら,かつ性能的に問題なければ QRCodeWriter を使えばいいのだが)
 +
 +** バージョン [#w2e91795]
 +バージョンとは,QRCodeのセル数の大きさを表す。~
 +一番小さい「バージョン1」は,21セルx21セル。~
 +バージョンが1つ増える毎に,縦横ともに4セルずつ増えていく。~
 +最大の「バージョン40」は,177セルx177セルになる。~
 +|バージョン  |縦横のセル数              |h
 +|バージョン1 |21セル×21セル            |
 +|バージョン2 |25セル×25セル            |
 +|…          |…                        |
 +|バージョンn |(17+4*n)セル×(17+4*n)セル|
 +|…          |…                        |
 +|バージョン40|177セル×177セル          |
 +
 +** モード [#ob7ca99e]
 +QRCodeモード( com.google.zxing.qrcode.decoder.Mode )には,以下のものがある。
 +|モード                |許容される文字|h
 +|数字(NUMERIC)        |数字のみ (0~9)|
 +|英数字(ALPHANUMERIC)  |数字,英大文字と一部の記号 (0~9, A~Z, スペース, '$', '%', '*', '+', '-', '.', '/', ':')|
 +|漢字(KANJI)          |Shift_JISの2バイトコードのみ|
 +|バイト(BYTE)          |8bitのデータすべて|
 +
 +他にも「混在モード」があるが,どうもZXing 3.3.2ではサポートされていないみたい。~
 +
 +モードについては,ちょっと変わった判定方法になっている。
 +
 +指定した文字セットが,"Shift_JIS"かそうでないかで判定方法が異なる。
 +
 +*** 文字セットが,"Shift_JIS"以外の場合の判定 [#m9d621ec]
 +文字セットが"Shift_JIS"でない場合には,以下のようになっている。
 + 対象のデータが数字のみの場合 ⇒ 数字モード
 + 対象のデータが英数字と一部の記号のみの場合 ⇒ 英数字モード
 + それ以外のデータが含まれる ⇒ バイトモード
 +
 +英数字モードでの英字は英大文字のみ。
 +英小文字があるとバイトモードになってしまう。
 +
 +*** 文字セットが"Shift_JIS"の場合の判定 [#n922eac0]
 +文字セットが"Shift_JIS"の場合には,以下のようになっている。
 + 対象のデータが"Shift_JIS"の2バイト文字のみの場合 ⇒ 漢字モード
 + それ以外のデータが含まれる ⇒ バイトモード
 +
 +つまり,文字セットとして"Shift_JIS"を指定した場合には,対象データが数字だけであってもバイトモードになるようだ。
 +
 +また,この判定は"Shift_JIS"を指定した場合のみの動作になっている。
 +
 +例えば,別名の"SJIS"や,"shift_jis"のように小文字で指定した場合は,上記「文字コードが"Shift_JIS"以外の場合の判定」が使われる。
 +
 +当然だが,"MS932" や "Windows-31J" についても,上記「文字コードが"Shift_JIS"以外の場合の判定」が使われる。
 +そのため漢字モードでは,「NEC特殊文字」「NEC選定IBM拡張文字」「IBM拡張文字」「ユーザ外字」などは使えない。
 +
 +ちなみに,このあたりの判定は com.google.zxing.qrcode.encoder.Encoder で行っています。
 +
 +''Encoder.java''
 +#code(java,nonumber){{
 +// (略)
 +private static Mode chooseMode(String content, String encoding) {
 +    if ("Shift_JIS".equals(encoding)) {
 +     // Choose Kanji mode if all input are double-byte characters
 +     return isOnlyDoubleByteKanji(content) ? Mode.KANJI : Mode.BYTE;
 +    }
 +// (略)
 +}}
 +つまり,文字セットとして"Shift_JIS"を指定した場合には,対象データが数字だけであってもバイトモードになるようだ。~
 +うーむ,この動作はおかしい気がする・・・~
 +3.3.2では,"Shift_JIS"でもNUMERIC/ALPHANUMERICに判定されるように修正されているっぽい。
 +
 +* QRCodeの画像を読み取る [#lb703bf2]
 +ZXingは,読み取りにも対応している。
 +
 +QRCodeの画像を読み取るために,以下のようなプログラムを作成。~
 +''QRCodeReader.java''
 +#code(java,nonumber){{
 +import com.google.zxing.BinaryBitmap;
 +import com.google.zxing.ChecksumException;
 +import com.google.zxing.FormatException;
 +import com.google.zxing.LuminanceSource;
 +import com.google.zxing.MultiFormatReader;
 +import com.google.zxing.NotFoundException;
 +import com.google.zxing.Reader;
 +import com.google.zxing.Result;
 +import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
 +import com.google.zxing.common.HybridBinarizer;
 +import java.awt.image.BufferedImage;
 +import java.io.File;
 +import java.io.IOException;
 +import javax.imageio.ImageIO;
 +
 +/**
 + *
 + * @author Yuji Ueno
 + */
 +public class QRCodeReader {
 +
 +    public static void main(String[] args) throws IOException, NotFoundException, ChecksumException, FormatException {
 +    
 +     //読み取りたい画像ファイルの保存場所
 +     String filePath = "qr_code.png";
 +    
 +     //読み取り処理
 +     BufferedImage image = ImageIO.read(new File(filePath));
 +     LuminanceSource source = new BufferedImageLuminanceSource(image);
 +     BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
 +     Reader reader = new MultiFormatReader();
 +     Result decodeResult = reader.decode(bitmap);
 +    
 +     //デコード処理
 +     String result = decodeResult.getText();
 +     //標準出力
 +     System.out.format("読み取り結果=%1$s\r\n", result);
 +    }
 +}
 +}}
 +コンパイルして,動作確認してみる。
 + > javac -encoding UTF-8 QRCodeReader.java
 + > java QRCodeReader
 + 読み取り結果=上野雄二
 +となって,作成したときの文字列が読めた。
  

  • 開発/Barcode/QRコード/JavaでQRコードを作成 のバックアップ差分(No. All)
    • 現: 2024-04-09 (火) 13:49:53 yuji

トップ   差分 バックアップ 複製 名前変更 リロード   ページ新規作成 全ページ一覧 単語検索 最新ページの一覧   ヘルプ   最新ページのRSS 1.0 最新ページのRSS 2.0 最新ページのRSS Atom
Counter: 19, today: 1, yesterday: 2