QRコード with ZXing

Facebook にシェア
このエントリーをはてなブックマークに追加
[`livedoor` not found]
Delicious にシェア

ZXing(”Zebra Crossing”)を使用したQRコード生成ツールを作成しました。
ZXingはGoogleがオープンソースで公開しているQRコード生成ライブラリです。
Androidでも使用されていますが、今回はローカル起動までとなります。
以下では、Antを使用してビルドしていますので、Antのセットアップをしておいてください。

1. ZXing セットアップ
まず、Google CodeからZXingをダウンロードします。
任意のディレクトリへ展開します。私は “C:Eclipse_programzxing-1.6” としました。
次に展開済みのフォルダ内にある READ MEファイルを開き、ビルド用のコマンドを確認します。

Please refer to the project page for more information:
http://code.google.com/p/zxing/
in particular:
http://code.google.com/p/zxing/wiki/GettingStarted

To get started, you can try building and running the command-line client;
you will need to have Apache's Ant tool installed to run this:

ant -f core/build.xml
ant -f javase/build.xml
java -cp javase/javase.jar:core/core.jar com.google.zxing.client.j2se.CommandLineRunner [URL]

コマンドプロンプトを開き、展開をしたディレクトリへ移動し、12,13行目のAntコマンドを実行します。

C:Eclipse_programzxing-1.6>ant -f core/build.xml
Buildfile: C:Eclipse_programzxing-1.6corebuild.xml

clean:
   [delete] Deleting directory C:Eclipse_programzxing-1.6corebuild
   [delete] Deleting: C:Eclipse_programzxing-1.6corecore.jar

build:

init:

compile:
    [mkdir] Created dir: C:Eclipse_programzxing-1.6corebuild
    [javac] C:Eclipse_programzxing-1.6corebuild.xml:36: warning: 'includeant
runtime' was not set, defaulting to build.sysclasspath=last; set to false for re
peatable builds
    [javac] Compiling 171 source files to C:Eclipse_programzxing-1.6corebuild
      [jar] Building jar: C:Eclipse_programzxing-1.6corecore.jar

BUILD SUCCESSFUL
Total time: 10 seconds
C:Eclipse_programzxing-1.6>ant -f javase/build.xml
Buildfile: C:Eclipse_programzxing-1.6javasebuild.xml

init:

build:
    [javac] C:Eclipse_programzxing-1.6javasebuild.xml:40: warning: 'includea
ntruntime' was not set, defaulting to build.sysclasspath=last; set to false for
repeatable builds

BUILD SUCCESSFUL
Total time: 0 seconds

最後にEclipseで使用する為に “C:Eclipse_programzxing-1.6corecore.jar” をライブラリ追加すればOKです。

2. 最終的なソースコード
何らかの文字列を入力すると、都度QRコードを生成するようになっています。
また、保存ボタン押下で生成済みのQRコードを保存します。
ちょっと怪しい部分もありますが、、ひとまず動くと思います。

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Hashtable;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

import com.google.zxing.EncodeHintType;
import com.google.zxing.WriterException;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import com.google.zxing.qrcode.encoder.ByteMatrix;
import com.google.zxing.qrcode.encoder.Encoder;
import com.google.zxing.qrcode.encoder.QRCode;

public class Url2QR extends JFrame implements ActionListener {

	private static Url2QR frame;
	private final JTextField textField;
	private final JButton dispButton;
	private final JButton saveButton;
	private final JLabel label;
	private final JPanel panelTop;
	private final JPanel panelBottom;
	private final ImageIcon icon;
	private final BufferedImage bufImg;
	private static int SIZE = 4;

	public Url2QR() throws WriterException {
		super("QRコード生成");

		panelTop = new JPanel();
		panelBottom = new JPanel();

		textField = new JTextField(20);
		dispButton = new JButton("表示");
		saveButton = new JButton("保存");

		bufImg = barcodeWrite();
		icon = new ImageIcon(bufImg);
		label = new JLabel(icon);

		Container container = getContentPane();
		container.setLayout(new BorderLayout());

		container.add(textField, BorderLayout.CENTER);
		container.add(panelTop, BorderLayout.EAST);
		container.add(panelBottom, BorderLayout.SOUTH);
		panelTop.setLayout(new BorderLayout());
		panelTop.add(dispButton, BorderLayout.WEST);
		panelTop.add(saveButton, BorderLayout.EAST);
		panelBottom.setLayout(new BorderLayout());
		panelBottom.add(label, BorderLayout.WEST);

		dispButton.setActionCommand("display");
		dispButton.addActionListener(this);
		saveButton.setActionCommand("save");
		saveButton.addActionListener(this);
		saveButton.setEnabled(false);

		KeyListener keyListener = new KeyListener() {
			public void keyPressed(KeyEvent keyEvent) {
			}

			public void keyReleased(KeyEvent keyEvent) {
				repaintIcon();
			}

			public void keyTyped(KeyEvent keyEvent) {
			}
		};
		textField.addKeyListener(keyListener);
	}

	public void actionPerformed(ActionEvent e) {

		if (e.getActionCommand().equals("display")) {
			repaintIcon();
		} else if (e.getActionCommand().equals("save")) {
			saveQR();
		}

	}

	public void repaintIcon() {

		try {
			if (textField.getText().isEmpty()) {
				saveButton.setEnabled(false);
			} else {
				saveButton.setEnabled(true);
			}
			label.setIcon(new ImageIcon(barcodeWrite()));
		} catch (WriterException e) {
			e.printStackTrace();
		}
		label.setToolTipText(textField.getText());
		frame.pack();

	}

	public void saveQR() {

		JFileChooser filechooser = new JFileChooser();

		int selected = filechooser.showSaveDialog(this);
		if (selected == JFileChooser.APPROVE_OPTION) {
			File file = filechooser.getSelectedFile();
			try {
				ImageIO.write(barcodeWrite(), "png", file);
			} catch (IOException e) {
				System.out.println(e);
			} catch (WriterException e) {
				e.printStackTrace();
			}
		} else if (selected == JFileChooser.CANCEL_OPTION) {
		} else if (selected == JFileChooser.ERROR_OPTION) {
			label.setText("Error");
		}
	}

	public BufferedImage barcodeWrite() throws WriterException {

		Hashtable hints = new Hashtable();
		hints.put(EncodeHintType.CHARACTER_SET, "SHIFT_JIS");
		QRCode qrCode = new QRCode();
		Encoder.encode(textField.getText(), ErrorCorrectionLevel.L, hints,
				qrCode);
		ByteMatrix byteMatrix = qrCode.getMatrix();

		BufferedImage image = new BufferedImage(byteMatrix.getWidth() * SIZE,
				byteMatrix.getHeight() * SIZE, BufferedImage.TYPE_4BYTE_ABGR);

		if (!textField.getText().isEmpty()) {
			Graphics2D g2D = image.createGraphics();
			for (int y = 0; y < byteMatrix.getHeight(); y++) {
				for (int x = 0; x < byteMatrix.getWidth(); x++) {
					if (byteMatrix.get(x, y) == 1) {
						g2D.setColor(Color.black);
					} else {
						g2D.setColor(Color.white);
					}
					g2D.fillRect(x * SIZE, y * SIZE, SIZE, SIZE);
				}
			}
		}

		return image;

	}

	public static void startGUI() throws WriterException {

		frame = new Url2QR();
		frame.pack();
		frame.setLocationRelativeTo(null);
		frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
		frame.setVisible(true);

	}

	public static void main(String[] args) {

		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				try {
					startGUI();
				} catch (WriterException e) {
					e.printStackTrace();
				}
			}
		});
	}

}