1.首先在maven中导入zxing的工具包
<!-- https://mvnrepository.com/artifact/com.google.zxing/core -->
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.3.0</version>
</dependency>
2.具体工具类
package com.business.util;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.Map;
import javax.imageio.ImageIO;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Charsets;
import com.google.common.collect.Maps;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.Binarizer;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.EncodeHintType;
import com.google.zxing.LuminanceSource;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.NotFoundException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
/**
* 二维码工具类
*
* @author zhanghao 2017年10月1日
*
*/
public class QrcodeUtils {
private static final int DEFAULT_LENGTH = 400;// 生成二维码的默认边长,因为是正方形的,所以高度和宽度一致
private static final String FORMAT = "png";// 生成二维码的格式
public static final int BLACK = 0xFF000000;
public static final int WHITE = 0xFFFFFFFF;
private static Logger logger = LoggerFactory.getLogger(QrcodeUtils.class);
/**
* 根据指定边长创建生成的二维码
*
* @param content 二维码内容
* @param length 二维码的高度和宽度
* @param logoFile logo 文件对象,可以为空
* @return 二维码图片的字节数组
*/
public static byte[] createQrcode(String content, int length, File logoFile) {
//logoFile为二维码中间的logo图片
if (logoFile != null && !logoFile.exists()) {
throw new IllegalArgumentException("请提供正确的logo文件!");
}
Map<EncodeHintType, Object> hints = Maps.newEnumMap(EncodeHintType.class);
// 设置字符编码
hints.put(EncodeHintType.CHARACTER_SET, Charsets.UTF_8.name());
// 指定纠错等级
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L);
hints.put(EncodeHintType.MARGIN, 1);
try {
BitMatrix bitMatrix = new MultiFormatWriter().encode(content,BarcodeFormat.QR_CODE, length, length, hints);
int width = bitMatrix.getWidth();
int height = bitMatrix.getHeight();
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
image.setRGB(x, y, bitMatrix.get(x, y) ? BLACK : WHITE);
}
}
if (logoFile != null) {
// 添加logo图片到二维码, 此处一定需要重新进行读取,而不能直接使用二维码的BufferedImage 对象
overlapImage(image,logoFile, new MatrixToLogoImageConfig());
}
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ImageIO.write(image, FORMAT, outputStream);
return outputStream.toByteArray();
} catch (Exception e) {
logger.warn("内容为:【" + content + "】的二维码生成失败!", e);
return null;
}
}
/**
* 创建生成默认高度(400)的二维码图片 可以指定是否加logo
*
* @param content 二维码内容
* @param logoFile logo 文件对象,可以为空
* @return 二维码图片的字节数组
*/
public static byte[] createQrcode(String content,File logoFile) {
return createQrcode(content, DEFAULT_LENGTH, logoFile);
}
/**
* 将logo添加到二维码中间
*
* @param image 生成的二维码图片对象
* @param logoFile logo文件对象
*/
private static void overlapImage(BufferedImage image, File logoFile,MatrixToLogoImageConfig logoConfig) throws IOException {
try {
BufferedImage logo = ImageIO.read(logoFile);
// 考虑到logo图片贴到二维码中,建议大小不要超过二维码的1/5;
int width = image.getWidth() / logoConfig.getLogoPart();
int height = image.getHeight() / logoConfig.getLogoPart();
// logo起始位置,此目的是为logo居中显示
int x = (image.getWidth() - width) / 2;
int y = (image.getHeight() - height) / 2;
Graphics2D g = image.createGraphics();
// 绘制图
g.drawImage(logo, x, y, width, height, null);
// 给logo画边框
// 构造一个具有指定线条宽度以及 cap 和 join 风格的默认值的实心 BasicStroke
g.setStroke(new BasicStroke(logoConfig.getBorder()));
g.setColor(logoConfig.getBorderColor());
g.drawRect(x, y, width, height);
g.dispose();
} catch (Exception e) {
throw new IOException("二维码添加logo时发生异常!", e);
}
}
/**
* 解析二维码
*
* @param file 二维码文件内容
* @return 二维码的内容
*/
public static String decodeQrcode(File file) throws IOException, NotFoundException {
BufferedImage image = ImageIO.read(file);
LuminanceSource source = new BufferedImageLuminanceSource(image);
Binarizer binarizer = new HybridBinarizer(source);
BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer);
Map<DecodeHintType, Object> hints = Maps.newEnumMap(DecodeHintType.class);
hints.put(DecodeHintType.CHARACTER_SET, Charsets.UTF_8.name());
hints.put(DecodeHintType.PURE_BARCODE, Boolean.TRUE);
hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
return new MultiFormatReader().decode(binaryBitmap, hints).getText();
}
protected static class MatrixToLogoImageConfig {
// logo默认边框颜色
public static final Color DEFAULT_BORDERCOLOR = Color.WHITE;
// logo默认边框宽度
public static final int DEFAULT_BORDER = 2;
// logo大小默认为照片的1/5
public static final int DEFAULT_LOGOPART = 5;
private final int border = DEFAULT_BORDER;
private final Color borderColor;
private final int logoPart;
public MatrixToLogoImageConfig() {
this(DEFAULT_BORDERCOLOR, DEFAULT_LOGOPART);
}
public MatrixToLogoImageConfig(Color borderColor, int logoPart) {
this.borderColor = borderColor;
this.logoPart = logoPart;
}
public Color getBorderColor() {
return this.borderColor;
}
public int getBorder() {
return this.border;
}
public int getLogoPart() {
return this.logoPart;
}
}
protected static final class BufferedImageLuminanceSource extends LuminanceSource {
private final BufferedImage image;
private final int left;
private final int top;
public BufferedImageLuminanceSource(BufferedImage image) {
this(image, 0, 0, image.getWidth(), image.getHeight());
}
public BufferedImageLuminanceSource(BufferedImage image, int left, int top,
int width, int height) {
super(width, height);
int sourceWidth = image.getWidth();
int sourceHeight = image.getHeight();
if (left + width > sourceWidth || top + height > sourceHeight) {
throw new IllegalArgumentException(
"Crop rectangle does not fit within image data.");
}
for (int y = top; y < top + height; y++) {
for (int x = left; x < left + width; x++) {
if ((image.getRGB(x, y) & 0xFF000000) == 0) {
image.setRGB(x, y, 0xFFFFFFFF);// = white
}
}
}
this.image = new BufferedImage(sourceWidth, sourceHeight,
BufferedImage.TYPE_BYTE_GRAY);
this.image.getGraphics().drawImage(image, 0, 0, null);
this.left = left;
this.top = top;
}
@Override
public byte[] getRow(int y, byte[] row) {
if (y < 0 || y >= getHeight()) {
throw new IllegalArgumentException(
"Requested row is outside the image: " + y);
}
int width = getWidth();
if (row == null || row.length < width) {
row = new byte[width];
}
this.image.getRaster().getDataElements(this.left, this.top + y, width,
1, row);
return row;
}
@Override
public byte[] getMatrix() {
int width = getWidth();
int height = getHeight();
int area = width * height;
byte[] matrix = new byte[area];
this.image.getRaster().getDataElements(this.left, this.top, width,
height, matrix);
return matrix;
}
@Override
public boolean isCropSupported() {
return true;
}
@Override
public LuminanceSource crop(int left, int top, int width, int height) {
return new BufferedImageLuminanceSource(this.image, this.left + left,
this.top + top, width, height);
}
@Override
public boolean isRotateSupported() {
return true;
}
@Override
public LuminanceSource rotateCounterClockwise() {
int sourceWidth = this.image.getWidth();
int sourceHeight = this.image.getHeight();
AffineTransform transform = new AffineTransform(0.0, -1.0, 1.0, 0.0,
0.0, sourceWidth);
BufferedImage rotatedImage = new BufferedImage(sourceHeight,
sourceWidth, BufferedImage.TYPE_BYTE_GRAY);
Graphics2D g = rotatedImage.createGraphics();
g.drawImage(this.image, transform, null);
g.dispose();
int width = getWidth();
return new BufferedImageLuminanceSource(rotatedImage, this.top,
sourceWidth - (this.left + width), getHeight(), width);
}
}
public static void main(String[] args) throws IOException, NotFoundException {
String outpath = "F:/qrcode.png";
File logoFile = new File("F:\\timg.jpg");
byte[] bytes = QrcodeUtils.createQrcode("https://www.baidu.com", logoFile);
FileUtils.writeByteArrayToFile(new File(outpath), bytes);
//System.out.println(QrcodeUtils.decodeQrcode(new File(outpath)));
}
}