JavaでQRCodeを作成してみる。
QRコードを作成するためのJavaのライブラリに,ZXing(ゼブラ・クロッシング)というライブラリがある。
ZXingはGoogleで開発されていて,様々な一次元/二次元のバーコードの生成/読み取りが出来るオープンソースライブラリ。Apache License 2.0で無償で利用出来ます。
サポートされているフォーマット形式は,
1D product | 1D industrial | 2D |
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の画像を作成する方法は,以下のようなプログラムを作成。
QRCodeEncoder.java
- | | ! - | - - ! - ! - ! - ! | - ! - ! - ! - ! | | | | | - ! ! ! |
|
コンパイルして,動作確認してみる。
$ javac -encoding UTF-8 QRCodeEncoder.java $ java QRCodeEncoder
qrcode.pngのファイル名で画像が作成されている。
画像の色を変更したい場合には,MatrixToImageWriter.toBufferedImage()の第2引数に,MatrixToImageConfigを指定することで可能。
// 青と白で表示 MatrixToImageConfig config = new MatrixToImageConfig(0xff0000ff, 0xffffffff); BufferedImage bufferedImage = MatrixToImageWriter.toBufferedImage(matrix, config);
画像ではなく,文字列でもよければBitMatrix.toString()が使える。
QRCodeを作る際に,いくつかヒント情報を指定することが出来る。
ヒント情報は,Mapで指定する。
キーは,列挙型のEncodeHintTypeを使用するが,キーによって値の型が異なるためMap<EncodeHintType, Object>で定義する。
また,キーが列挙型なのでEnumMapが使用出来る。
誤り訂正レベルは,以下のように指定する。
キー : EncodeHintType.ERROR_CORRECTION 値 : 列挙型の ErrorCorrectionLevel で指定する ErrorCorrectionLevel.L : 7%まで訂正可能(デフォルト) ErrorCorrectionLevel.M : 15%まで訂正可能 ErrorCorrectionLevel.Q : 25%まで訂正可能 ErrorCorrectionLevel.H : 30%まで訂正可能
ちなみに,QRCodeにイラストなどを載せても読み取れるのは,この誤り訂正能力のおかげ。
文字セットは,以下のように指定します。
キー : EncodeHintType.CHARACTER_SET 値 : 文字列( String )で文字セット名を指定 デフォルトは "ISO-8859-1"
デフォルトは,上記のように"ISO-8859-1"(いわゆる ISO-Latin-1)なので,日本語が使えない。
必要であれば日本語が扱える文字セットを指定する必要がある。
後述のように,"Shift_JIS"の文字セット名は特別な対応があります(詳細は「モード」を参照)。
マージンは,以下のように指定する。
キー : EncodeHintType.MARGIN 値 : 上下左右のマージンをセル数( Integer )で指定 デフォルトは 4
QRCodeには,周囲に4セル以上のマージンを必要とする。 普通は,デフォルトのままで十分だと思う。 もし,表示する際に画像の周りに余白を別途用意するなら,マージンには0を指定しても大丈夫。
QRCodeには,「モード」や「バージョン」といった情報がありますが,基本的に自動的に判定される。 上記の方法では,実際に適用された「モード」や「バージョン」は取得出来ない。
もしなんらかの理由で,「モード」や「バージョン」が必要な場合(例えば,「バージョン」によって画像のサイズを 変えるなど)は,Encoderを使用する。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
| - | | - | | | - - ! ! | | | | | | ! ! |
|
注意: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 を使えばいいのだが)
バージョンとは,QRCodeのセル数の大きさを表す。
一番小さい「バージョン1」は,21セルx21セル。
バージョンが1つ増える毎に,縦横ともに4セルずつ増えていく。
最大の「バージョン40」は,177セルx177セルになる。
バージョン | 縦横のセル数 |
バージョン1 | 21セル×21セル |
バージョン2 | 25セル×25セル |
… | … |
バージョンn | (17+4*n)セル×(17+4*n)セル |
… | … |
バージョン40 | 177セル×177セル |
QRCodeモード( com.google.zxing.qrcode.decoder.Mode )には,以下のものがある。
モード | 許容される文字 |
数字(NUMERIC) | 数字のみ (0~9) |
英数字(ALPHANUMERIC) | 数字,英大文字と一部の記号 (0~9, A~Z, スペース, '$', '%', '*', '+', '-', '.', '/', ':') |
漢字(KANJI) | Shift_JISの2バイトコードのみ |
バイト(BYTE) | 8bitのデータすべて |
他にも「混在モード」があるが,どうもZXing 3.3.2ではサポートされていないみたい。
モードについては,ちょっと変わった判定方法になっている。
指定した文字セットが,"Shift_JIS"かそうでないかで判定方法が異なる。
文字セットが"Shift_JIS"でない場合には,以下のようになっている。
対象のデータが数字のみの場合 ⇒ 数字モード 対象のデータが英数字と一部の記号のみの場合 ⇒ 英数字モード それ以外のデータが含まれる ⇒ バイトモード
英数字モードでの英字は英大文字のみ。 英小文字があるとバイトモードになってしまう。
文字セットが"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
つまり,文字セットとして"Shift_JIS"を指定した場合には,対象データが数字だけであってもバイトモードになるようだ。
うーむ,この動作はおかしい気がする・・・
3.3.2では,"Shift_JIS"でもNUMERIC/ALPHANUMERICに判定されるように修正されているっぽい。
ZXingは,読み取りにも対応している。
QRCodeの画像を読み取るために,以下のようなプログラムを作成。
QRCodeReader.java
- | | ! - | - | - ! | - ! | | | | | - ! - ! ! ! |
|
コンパイルして,動作確認してみる。
> javac -encoding UTF-8 QRCodeReader.java > java QRCodeReader 読み取り結果=上野雄二
となって,作成したときの文字列が読めた。
新しくコメントをつける