Java生成、解析二维码
0
今天研究了一下二维码生成和解析,不过这个解析的方法不好,解析会出现错误。
使用QRCode:
package com.test;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import jp.sourceforge.qrcode.QRCodeDecoder;
import jp.sourceforge.qrcode.data.QRCodeImage;
import com.swetake.util.Qrcode;
public class Code {
public static void main(String[] args) {
encode("http://www.acgist.com", "D:\\code.png", "E:\\workspace\\acgist\\WebRoot\\img\\logo\\logo.png");
System.out.println(decode("D:\\code.png"));
}
private final static int PADDING = 10; // 设置边框
private final static int LINE_WIDTH = 4; // 二维码线条宽度
private final static int CODE_WH = 184; // 图片高宽,公式:(21 + 4 * (CODE_VERSION - 1)) * LINE_WIDTH + 2 * PADDING
private final static int LOGO_MAX_WH = 30; // LOGO最大高宽
private final static int CODE_VERSION = 6; // 数值越大,容纳的信息越多,但是注意适合就好,太大加上LOGO后容易这里的解析方法抛错误,但是其他的二维码软件可以识别
private final static int CODE_VERSION_MAX_BYTES = 108; // 最大字节大小
/**
* 生成二维码
*
* @param msg 二维码图片的内容
* @param codePath 生成二维码图片完整的路径
* @param logoPath 二维码图片中间的logo路径
*/
public static void encode(String msg, String codePath, String logoPath) {
Graphics2D graphics2d = null;
BufferedImage logoImage = null;
BufferedImage codeImage = null;
try {
Qrcode qrcode = new Qrcode();
qrcode.setQrcodeEncodeMode('B'); // 编码方式
qrcode.setQrcodeErrorCorrect('M'); // 容错级别
qrcode.setQrcodeVersion(CODE_VERSION);
byte[] msgBytes = msg.getBytes("UTF-8");
codeImage = new BufferedImage(CODE_WH, CODE_WH, BufferedImage.TYPE_INT_RGB);
graphics2d = codeImage.createGraphics();
graphics2d.setBackground(Color.WHITE);
graphics2d.clearRect(0, 0, CODE_WH, CODE_WH);
graphics2d.setColor(Color.BLACK);
if (msgBytes.length > 0 && msgBytes.length < CODE_VERSION_MAX_BYTES) {
boolean[][] codeOut = qrcode.calQrcode(msgBytes);
for (int i = 0; i < codeOut.length; i++) {
for (int j = 0; j < codeOut.length; j++) {
if (codeOut[j][i]) {
graphics2d.fillRect(j * LINE_WIDTH + PADDING, i * LINE_WIDTH + PADDING, LINE_WIDTH, LINE_WIDTH);
}
}
}
} else {
throw new RuntimeException("内容太长:" + msg);
}
if (logoPath != null) {
logoImage = ImageIO.read(new File(logoPath)); // 实例化一个Image对象。
int w = logoImage.getWidth() > LOGO_MAX_WH ? LOGO_MAX_WH : logoImage.getWidth();
int h = logoImage.getHeight() > LOGO_MAX_WH ? LOGO_MAX_WH : logoImage.getHeight();
int pw = (CODE_WH - w) / 2;
int ph = (CODE_WH - h) / 2;
graphics2d.drawImage(logoImage.getScaledInstance(w, h, Image.SCALE_SMOOTH), pw, ph, null);
}
codeImage.flush();
ImageIO.write(codeImage, "png", new File(codePath));
} catch (IOException e) {
e.printStackTrace();
} finally {
if (graphics2d != null)
graphics2d.dispose();
}
}
/**
* 解析二维码
*
* @param codePath 解析二维码文件路径
* @return 内容
*/
public static String decode(String codePath) {
File codeFile = new File(codePath);
String msg = null;
try {
final BufferedImage codeImage = ImageIO.read(codeFile);
QRCodeDecoder decoder = new QRCodeDecoder();
msg = new String(decoder.decode(new QRCodeImage() {
@Override
public int getWidth() {
return codeImage.getWidth();
}
@Override
public int getHeight() {
return codeImage.getHeight();
}
@Override
public int getPixel(int x, int y) {
return codeImage.getRGB(x, y);
}
}));
} catch (IOException e) {
e.printStackTrace();
}
return msg;
}
}
效果:
注意:一定要注意设置
CODE_VERSION
这个参数,如果设置不恰当很容易导致上面的解析方法抛出异常或者解析乱码。
Exception in thread "main" java.lang.IllegalStateException: This method must be called after QRCodeImageReader.getQRCodeSymbol() called
at jp.sourceforge.qrcode.reader.QRCodeImageReader.getQRCodeSymbolWithAdjustedGrid(QRCodeImageReader.java:239)
at jp.sourceforge.qrcode.QRCodeDecoder.decode(QRCodeDecoder.java:140)
at jp.sourceforge.qrcode.QRCodeDecoder.decode(QRCodeDecoder.java:68)
参考文章:http://blog.csdn.net/wangpeng047/article/details/7181217