以前看到二維碼,總覺得這是一個神奇的東西,也沒有去深入的瞭解過,最近一個偶然的機會接觸到了二維碼,真實的體會了它的奧妙之處,然後就從中汲取了一些養分與大家分享,希望對大家有用,代碼如下:
工具類(QRCodeUtil )
import java.awt.BasicStroke;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Shape;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.OutputStream;
import java.util.Hashtable;
import javax.imageio.ImageIO;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.Result;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
public class QRCodeUtil {
private static final String CHARSET = "utf-8";
private static final String FORMAT = "JPG";
private static final int QRCODE_SIZE = 300; // 二維碼尺寸
private static final int LOGO_WIDTH = 60; // LOGO高度
private static final int LOGO_HEIGHT = 60;// LOGO寬度
/**
* 生成二維碼
*
* @param content
* 內容
* @param logoPath
* LOGO地址
* @param destPath
* 存放目錄
* @param needCompress
* 是否壓縮LOGO
* @throws Exception
*/
public static String encode(String content, String logoPath, String destPath, boolean needCompress,String fileName)
throws Exception {
BufferedImage image = QRCodeUtil.createImage(content, logoPath, needCompress);
mkdirs(destPath);
ImageIO.write(image, FORMAT, new File(destPath + "/" + fileName+".jpg"));
return destPath + "/" + fileName+".jpg";
}
/**
* 當文件夾不存在時,mkdirs會自動創建多層目錄,區別於mkdir.
* (mkdir如果父目錄不存在則會拋出異常)
* @param destPath
* 存放目錄
*/
public static void mkdirs(String destPath) {
File file = new File(destPath);
if (!file.exists() && !file.isDirectory()) {
file.mkdirs();
}
}
/**
* 生成二維碼(內嵌LOGO)
*
* @param content
* 內容
* @param logoPath
* LOGO地址
* @param destPath
* 存儲地址
* @throws Exception
*/
public static void encode(String content, String destPath, boolean needCompress,String fileName) throws Exception {
QRCodeUtil.encode(content, null, destPath, needCompress,fileName);
}
/* 生成二維碼
*
* @param content
* 內容
* @param destPath
* 存儲地址
* @throws Exception
*/
public static void encode(String content, String destPath,String fileName) throws Exception {
QRCodeUtil.encode(content, null, destPath, false, fileName);
}
/**
* 生成二維碼(內嵌LOGO)
*
* @param content
* 內容
* @param logoPath
* LOGO地址
* @param output
* 輸出流
* @param needCompress
* 是否壓縮LOGO
* @throws Exception
*/
public static void encode(String content, String logoPath, OutputStream output, boolean needCompress)
throws Exception {
BufferedImage image = QRCodeUtil.createImage(content, logoPath, needCompress);
ImageIO.write(image, FORMAT, output);
}
/**
* 生成二維碼
*
* @param content
* 內容
* @param output
* 輸出流
* @throws Exception
*/
public static void encode(String content, OutputStream output) throws Exception {
QRCodeUtil.encode(content, null, output, false);
}
/**
* 解析二維碼
*
* @param file
* 二維碼圖片
* @return
* @throws Exception
*/
public static String decode(File file) throws Exception {
BufferedImage image;
image = ImageIO.read(file);
if (image == null) {
return null;
}
BufferedImageLuminanceSource source = new BufferedImageLuminanceSource(image);
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
Result result;
Hashtable<DecodeHintType, Object> hints = new Hashtable<DecodeHintType, Object>();
hints.put(DecodeHintType.CHARACTER_SET, CHARSET);
result = new MultiFormatReader().decode(bitmap, hints);
String resultStr = result.getText();
return resultStr;
}
/**
* 解析二維碼
*
* @param path
* 二維碼圖片地址
* @return
* @throws Exception
*/
public static String decode(String path) throws Exception {
return QRCodeUtil.decode(new File(path));
}
private static BufferedImage createImage(String content, String logoPath, boolean needCompress) throws Exception {
Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
hints.put(EncodeHintType.CHARACTER_SET, CHARSET);
hints.put(EncodeHintType.MARGIN, 1);
BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE, hints);
int width = bitMatrix.getWidth(); int height = bitMatrix.getHeight();
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
for (int x = 0; x < width; x++){
for (int y = 0; y < height; y++) {
image.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);
}
} if (logoPath == null || "".equals(logoPath)) {
return image; } // 插入圖片
QRCodeUtil.insertImage(image, logoPath, needCompress);
return image;
}
/**
* 插入LOGO
*
* @param source
* 二維碼圖片
* @param logoPath
* LOGO圖片地址
* @param needCompress
* 是否壓縮
* @throws Exception
*/
private static void insertImage(BufferedImage source, String logoPath, boolean needCompress) throws Exception {
File file = new File(logoPath);
if (!file.exists()) {
throw new Exception("logo file not found.");
}
Image src = ImageIO.read(new File(logoPath));
int width = src.getWidth(null);
int height = src.getHeight(null);
if (needCompress) { // 壓縮LOGO
if (width > LOGO_WIDTH) {
width = LOGO_WIDTH;
}
if (height > LOGO_HEIGHT) {
height = LOGO_HEIGHT;
}
Image image = src.getScaledInstance(width, height, Image.SCALE_SMOOTH);
BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics g = tag.getGraphics();
g.drawImage(image, 0, 0, null); // 繪製縮小後的圖
g.dispose();
src = image;
} // 插入LOGO
Graphics2D graph = source.createGraphics();
int x = (QRCODE_SIZE - width) / 2;
int y = (QRCODE_SIZE - height) / 2;
graph.drawImage(src, x, y, width, height, null);
Shape shape = new RoundRectangle2D.Float(x, y, width, width, 6, 6);
graph.setStroke(new BasicStroke(3f));
graph.draw(shape);
graph.dispose();
}
}
在pom.xml中注入依賴:
<!-- zxing實現二維碼生成和解析 -->
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.0.0</version>
</dependency>
<!-- json依賴 -->
<!-- 第一種 -->
<dependency>
<groupId>net.sf.json-lib</groupId>
<artifactId>json-lib</artifactId>
<version>2.4</version>
<classifier>jdk15</classifier>
</dependency>
<!-- 第二種 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
測試類Test(第一種json依賴)
import com.alibaba.fastjson.JSONObject;
public class Test {
public static void main(String[] args) throws Exception {
JSONObject json = new JSONObject();
json.put(
"zxing",
"https://github.com/zxing/zxing/tree/zxing-3.0.0/javase/src/main/java/com/google/zxing");
json.put("author", "jo");
String content = json.toJSONString();// 內容
//生成不帶logo 的二維碼
String encode = QRCodeUtil.encode(content,null,"D://home", false,"555");
System.out.println(encode);
}
}
測試類Test2(第二種json依賴)
import net.sf.json.JSONObject;
public class Test2 {
public static void main(String[] args) throws Exception {
JSONObject json = new JSONObject();
json.put(
"zxing",
"https://github.com/zxing/zxing/tree/zxing-3.0.0/javase/src/main/java/com/google/zxing");
json.put("author", "jo");
String content = json.toString();// 內容
//生成不帶logo 的二維碼
//QRCodeUtil.encode(content,"D://home","2222");
String encode = QRCodeUtil.encode(content,null,"D://home", false,"555");
System.out.println(encode);
}
}