package com.hualala.shop.mall.useric.utils;
import com.google.zxing.*;
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;
import org.apache.commons.lang.StringUtils;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.OutputStream;
import java.net.URL;
import java.util.Hashtable;
/**
- @ClassName: QRCodeUtil
- @Description: 二维码编码
- @author wchj
- @date 2018年7月26日
*/
public class QRCodeUtil {
// 设置二维码编码格式
private static final String CHARSET = “utf-8”;
// 保存的二维码格式
public static final String DEFAULT_FORMAT_NAME = “JPG”;
// 二维码尺寸
private static final int DEFAULT_QRCODE_SIZE = 200;
// LOGO宽度
private static final int DEFAULT_LOGO_WIDTH = 80;
// LOGO高度
private static final int DEFAULT_LOGO_HEIGHT = 80;
private static final boolean DEFAULT_NEED_COMPRESS= true;
/**
* @Title: encode
* @Description: 生成二维码
* @param content 二维码内容
* @param destPath 目标保存地址
* @throws Exception 参数说明
* @return void 返回类型
* @throws
*/
public static String encode(QRCodeContent content, String destPath) throws Exception {
BufferedImage image = QRCodeUtil.createImage(content);
if (StringUtils.isBlank(content.getFormatName())){
content.setFormatName(DEFAULT_FORMAT_NAME);
}
if (mkdirs(destPath)) {
String file = content.getReferralCode() +"."+ content.getFormatName();
ImageIO.write(image,content.getFormatName(), new File(destPath + "/" + file));
return file;
}
return "";
}
/**
* @Title: encode
* @Description: 生成二维码
* @param content 二维码内容
* @param output 输出流
* @throws Exception 参数说明
* @return void 返回类型
* @throws
*/
public static void encode(QRCodeContent content, OutputStream output) throws Exception {
BufferedImage image = QRCodeUtil.createImage(content);
if (StringUtils.isBlank(content.getFormatName())){
content.setFormatName(DEFAULT_FORMAT_NAME);
}
ImageIO.write(image, content.getFormatName(), output);
}
/**
* @Title: encode
* @Description: 生成二维码
* @param content 二维码内容
* @param output 输出流
* @throws Exception 参数说明
* @return void 返回类型
* @throws
*/
public static void encode(String content, OutputStream output) throws Exception {
QRCodeContent req = new QRCodeContent();
req.setContent(content);
req.setLogoPath(null);
req.setQrCodeSize(DEFAULT_QRCODE_SIZE);
req.setFormatName(DEFAULT_FORMAT_NAME);
QRCodeUtil.encode(req, output);
}
/**
* @Title: decode
* @Description: 对二维码解码
* @param path 文件路径
* @return
* @throws Exception 参数说明
* @return String 返回类型
* @throws
*/
public static String decode(String path) throws Exception {
return QRCodeUtil.decode(new File(path));
}
/**
* @Title: createImage
* @Description: 将二维码内容创建到Image流
* @param req 生成二维码请求
* @return
* @throws Exception 参数说明
* @return BufferedImage 返回类型
* @throws
*/
private static BufferedImage createImage(QRCodeContent req) throws Exception {
//设置二维码纠错级别MAP
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);
if (req.getQrCodeSize() == null || req.getQrCodeSize()<=0){
req.setQrCodeSize(DEFAULT_QRCODE_SIZE);
}
//创建比特矩阵(位矩阵)的QR码编码的字符串
BitMatrix bitMatrix = new MultiFormatWriter().encode(req.getContent(), BarcodeFormat.QR_CODE, req.getQrCodeSize(), req.getQrCodeSize(), hints);
int width = bitMatrix.getWidth();
int height = bitMatrix.getHeight();
// 使BufferedImage勾画QRCode (matrixWidth 是行二维码像素点)
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 (req.getLogoPath()== null || "".equals(req.getLogoPath())) {
return image;
}
// 插入logo
QRCodeUtil.insertImage(image, req);
return image;
}
/**
* @Title: insertImage
* @Description: 将logo插入到二维码中
* @param source 二维码Image流
* @param req 二维码内容
* @throws Exception 参数说明
* @return void 返回类型
* @throws
*/
private static void insertImage(BufferedImage source, QRCodeContent req) throws Exception {
if (req.getLogoWidth() == null || req.getLogoWidth()<=0){
req.setLogoWidth(DEFAULT_LOGO_WIDTH);
}
if (req.getLogoHeight() == null || req.getLogoHeight()<=0){
req.setLogoHeight(DEFAULT_LOGO_HEIGHT);
}
Image src = ImageIO.read(new URL(req.getLogoPath()));
int width = src.getWidth(null);
int height = src.getHeight(null);
if(req.getNeedCompress()==null){
req.setNeedCompress(DEFAULT_NEED_COMPRESS);
}
if (req.getNeedCompress()) { // 压缩LOGO
if (width > req.getLogoWidth()) {
width = req.getLogoWidth();
}
if (height > req.getLogoHeight()) {
height = req.getLogoHeight();
}
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 = (req.getQrCodeSize() - width) / 2;
int y = (req.getQrCodeSize() - 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();
}
/**
* @Title: mkdirs
* @Description: 创建文件夹
* @param destPath 文件夹地址
* @return void 返回类型
* @throws
*/
private static boolean mkdirs(String destPath) {
File file = new File(destPath);
// 当文件夹不存在时,mkdirs会自动创建多层目录,区别于mkdir.(mkdir如果父目录不存在则会抛出异常)
if (!file.exists() && !file.isDirectory()) {
file.mkdirs();
return true;
}
return true;
}
/**
* @Title: decode
* @Description: 对二维码解码
* @param file 文件对象
* @return 解码后的二维码内容字符串
* @throws Exception 参数说明
* @return String 返回类型
* @throws
*/
private 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));
Hashtable<DecodeHintType, String> hints = new Hashtable<DecodeHintType, String>();
hints.put(DecodeHintType.CHARACTER_SET, CHARSET);
return new MultiFormatReader().decode(bitmap, hints).getText();
}
}
com.google.zxing core 3.3.3 com.google.zxing javase 3.3.3