依赖
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.0.0</version>
</dependency>
二维码生成与解析
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 javax.imageio.ImageIO;
import java.awt.*;
import java.awt.font.FontRenderContext;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
public class QrCodeUtil {
//0x,透明度,R,G,B
private static final int BLACK = 0xFF000000;
private static final int WHITE = 0xFFFFFFFF;
/**
* 二维码图片生成
* @param matrix
* @return
*/
public static BufferedImage toBufferedImage(BitMatrix matrix) {
int width = matrix.getWidth();
int height = matrix.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, matrix.get(x, y) ? BLACK : WHITE);
}
}
return image;
}
/**
* 二维码输出为文件
* @param image 二维码图片
* @param format 二维码图片格式
* @param filePath 二维码保存路径
* @throws IOException
*/
public static void writeToFile(BufferedImage image, String format, String filePath) throws IOException {
File outputFile = new File(filePath);
if (!outputFile.exists()) {
outputFile.mkdirs();
}
if (!ImageIO.write(image, format, outputFile)) {
throw new IOException("不能转换成" + format );
}
}
/**
* 二维码添加logo(logo占二维码1/5)
* @param image 二维码图片
* @param logoFilePath logo图片路径
* @return
* @throws IOException
*/
public static BufferedImage addLogo(BufferedImage image, String logoFilePath) throws IOException {
File file = new File(logoFilePath);
if (!file.exists()) {
throw new IOException("logo文件不存在");
}
BufferedImage logo = ImageIO.read(file);
Graphics2D graph = image.createGraphics();
graph.drawImage(logo, image.getWidth() * 2 / 5, image.getHeight() * 2 / 5
, image.getWidth() * 2 / 10, image.getHeight() * 2 / 10, null);
graph.dispose();
return image;
}
/**
* 二维码添加背景
* @param image 二维码图片
* @param bgFilePath 背景图片路径
* @param x 维码左顶点在背景图片的X坐标
* @param y 二维码左顶点在背景图片的Y坐标
* @return
* @throws IOException
*/
public static BufferedImage addBgImg(BufferedImage image, String bgFilePath, int x, int y) throws Exception {
File file = new File(bgFilePath);
if (!file.exists()) {
throw new IOException("背景图片不存在");
}
BufferedImage bgImg = ImageIO.read(file);
if(x < 0) {
x = 0;
}
if(y < 0) {
y = 0;
}
if(bgImg.getWidth() < image.getWidth() || bgImg.getHeight() <image.getHeight()) {
throw new Exception("背景图片小于二维码尺寸");
}
if(bgImg.getWidth() < x + image.getWidth() || bgImg.getHeight() < y + bgImg.getHeight()) {
throw new Exception("以背景的("+x+","+y+")作为二维码左上角不能容下整个二维码");
}
Graphics2D graph = bgImg.createGraphics();
graph.drawImage(image, x, y, image.getWidth(), image.getHeight(), null);
graph.dispose();
return bgImg;
}
/**
* 二维码底部添加文本(只限一行,没有换行)
* @param image 二维码图片
* @param text 文本内容
* @param fontSize 写入文本的字体
* @return
*/
public static BufferedImage addText(BufferedImage image, String text, int fontSize) {
int outImageWidth = image.getWidth();
int outImageHeight = image.getHeight() + fontSize + 10;
BufferedImage outImage = new BufferedImage(outImageWidth, outImageHeight, BufferedImage.TYPE_INT_RGB);
Graphics2D graph = outImage.createGraphics();
//填充为白色背景
graph.setColor(Color.white);
graph.fillRect(0 ,0 , outImageWidth, outImageHeight);
//将二维码画入
graph.drawImage(image, 0, 0, image.getWidth(), image.getHeight(), null);
//添加文本
graph.setColor(Color.black);
Font font = new Font("楷体", Font.BOLD, fontSize);//字体,字型,字号
graph.setFont(font);
//文本水平,垂直居中
FontRenderContext frc =
new FontRenderContext(null, true, true);
Rectangle2D r2D = font.getStringBounds(text, frc);
int rWidth = (int) Math.round(r2D.getWidth());
int a = (outImageWidth - rWidth) / 2;
graph.drawString(text,a, outImageHeight - 5);//x,y为左下角坐标
graph.dispose();
return outImage;
}
/**
* 生成二维码(无logo,无背景)
* 根据内容,生成指定宽高、指定格式的二维码图片
* @param text 内容
* @param width 宽
* @param height 高
* @return
* @throws Exception
*/
public static BufferedImage encodeQrCode(String text, int width, int height) throws WriterException, IOException {
//设置二维码配置
Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
// 设置QR二维码的纠错级别,指定纠错等级,纠错级别(L 7%、M 15%、Q 25%、H 30%)
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
hints.put(EncodeHintType.MARGIN, 0);// 白边
//创建比特矩阵(位矩阵)的QR码编码的字符串
BitMatrix bitMatrix = new MultiFormatWriter().encode(text, BarcodeFormat.QR_CODE, width, height, hints);
//二维码图片生成
BufferedImage qrCodeImg = toBufferedImage(bitMatrix);
return qrCodeImg;
}
/**
* 解析二维码
* @param image 读入的二维码图片
* @return
*/
public static String decodeQrCode(BufferedImage image) {
String qrCodeContent = null;
try {
LuminanceSource source = new BufferedImageLuminanceSource(image);
Binarizer binarizer = new HybridBinarizer(source);
BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer);
Map<DecodeHintType, Object> hints = new HashMap<DecodeHintType, Object>();
hints.put(DecodeHintType.CHARACTER_SET, "UTF-8");
Result result = new MultiFormatReader().decode(binaryBitmap, hints);// 对图像进行解码
qrCodeContent= result.getText();
} catch (Exception e) {
e.printStackTrace();
}
return qrCodeContent;
}
}
测试
import java.awt.image.BufferedImage;
public class QrCodeTest {
public static void main(String[] args) {
String text = "https://www.baidu.com/";//二维码内容
String format = "jpg"; //生成的二维码图片的格式
String logoFilePath = "F:\\test\\CodeTest\\logo.jpg";//二维码logo图片路径
String bgFilePath = "F:\\test\\CodeTest\\bg.jpg";//二维码背景图片路径
String savePath = "F:\\test\\CodeTest\\";
int width = 300; //二维码图片的宽
int height = 300; //二维码图片的高
try {
//生成二维码图片
//无logo,无背景二维码
BufferedImage qrCodeNoLogoNoBg = QrCodeUtil.encodeQrCode(text, width, height);
QrCodeUtil.writeToFile(qrCodeNoLogoNoBg, format, savePath+"qrCodeNoLogoNoBg."+format);
//无logo,无背景二维码添加背景
BufferedImage qrCodeNoLogoWithBg = QrCodeUtil.addBgImg(qrCodeNoLogoNoBg, bgFilePath, 0, 0);
QrCodeUtil.writeToFile(qrCodeNoLogoWithBg, format, savePath+"qrCodeNoLogoWithBg."+format);
//无logo,无背景二维码添加logo
BufferedImage qrCodeWithLogoNoBg = QrCodeUtil.addLogo(qrCodeNoLogoNoBg,logoFilePath);
QrCodeUtil.writeToFile(qrCodeWithLogoNoBg, format, savePath+"qrCodeWithLogoNoBg."+format);
//有logo,无背景二维码添加背景
BufferedImage qrCodeWithLogoWithBg = QrCodeUtil.addBgImg(qrCodeWithLogoNoBg, bgFilePath, 0, 0);
QrCodeUtil.writeToFile(qrCodeWithLogoWithBg, format, savePath+"qrCodeWithLogoWithBg."+format);
//二维码添加文字描述(不带背景,大致实现,只限一行,没有换行)
BufferedImage qrCodeAddText = QrCodeUtil.addText(qrCodeNoLogoNoBg, "123124", 30);
QrCodeUtil.writeToFile(qrCodeAddText, format, savePath+"qrCodeAddText."+format);
//二维码解析
// BufferedImage image = ImageIO.read(new File("F:\\test\\CodeTest\\qrCodeWithLogoWithBg.jpg"));
//无logo
String qrCodeContent = QrCodeUtil.decodeQrCode(qrCodeNoLogoNoBg);
System.out.println("解析无logo,无背景二维码的内容为: " + qrCodeContent);
//有logo
String qrCodeContent2 = QrCodeUtil.decodeQrCode(qrCodeWithLogoNoBg);
System.out.println("解析有logo,无背景二维码的图片的内容为: " + qrCodeContent2);
//有背景,无logo
String qrCodeContent3 = QrCodeUtil.decodeQrCode(qrCodeNoLogoWithBg);
System.out.println("解析无logo,有背景二维码的图片的内容为: " + qrCodeContent3);
//有背景,有logo
String qrCodeContent4 = QrCodeUtil.decodeQrCode(qrCodeWithLogoWithBg);
System.out.println("解析有logo,有背景二维码的图片的内容为: " + qrCodeContent4);
//无背景添加文字描述
String qrCodeContent5 = QrCodeUtil.decodeQrCode(qrCodeAddText);
System.out.println("无背景添加文字描述: " + qrCodeContent5);
} catch (Exception e) {
e.printStackTrace();
}
}
}
解析
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190628112636668.jpg)
生成的二维码
无logo,无背景
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190628113349431.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dhbmd3ZW5qaWUxOTk3,size_16,color_FFFFFF,t_70)
有logo,无背景
![在这里插入图片描述](https://img-blog.csdnimg.cn/201906281133408.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dhbmd3ZW5qaWUxOTk3,size_16,color_FFFFFF,t_70)
无logo,有背景
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190628113403596.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dhbmd3ZW5qaWUxOTk3,size_16,color_FFFFFF,t_70)
有logo,有背景
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190628113424309.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dhbmd3ZW5qaWUxOTk3,size_16,color_FFFFFF,t_70)
带文本
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190628113444873.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dhbmd3ZW5qaWUxOTk3,size_16,color_FFFFFF,t_70)