原文地址:https://blog.csdn.net/xm526489770/article/details/83651555
- 1.首先引入谷歌開源項(xiàng)目依賴:
<!-- 二維碼支持包 -->
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>net.glxn</groupId>
<artifactId>qrgen</artifactId>
<version>1.4</version>
</dependency>
- 2.二維碼生成解析工具類:
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.*;
import javax.imageio.ImageIO;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.Binarizer;
import com.google.zxing.BinaryBitmap;
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.Result;
import com.google.zxing.WriterException;
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;
/**
* 二維碼生成解析工具類
*
* @data 2018-11-2 10:23:14
*/
public class QRCodeUtil {
// 二維碼顏色==黑色
private static final int BLACK = 0xFF000000;
// 二維碼顏色==白色
private static final int WHITE = 0xFFFFFFFF;
// 二維碼圖片格式==jpg和png兩種
private static final List<String> IMAGE_TYPE = new ArrayList<>();
static {
IMAGE_TYPE.add("jpg");
IMAGE_TYPE.add("png");
}
/**
* zxing方式生成二維碼
* 注意:
* 1,文本生成二維碼的方法獨(dú)立出來,返回image流的形式,可以輸出到頁面
* 2,設(shè)置容錯率為最高,一般容錯率越高,圖片越不清晰, 但是只有將容錯率設(shè)置高一點(diǎn)才能兼容logo圖片
* 3,logo圖片默認(rèn)占二維碼圖片的20%,設(shè)置太大會導(dǎo)致無法解析
*
* @param content 二維碼包含的內(nèi)容渗蟹,文本或網(wǎng)址
* @param path 生成的二維碼圖片存放位置
* @param size 生成的二維碼圖片尺寸 可以自定義或者默認(rèn)(250)
* @param logoPath logo的存放位置
*/
public static boolean zxingCodeCreate(String content, String path, Integer size, String logoPath) {
try {
//圖片類型
String imageType = "jpg";
//獲取二維碼流的形式,寫入到目錄文件中
BufferedImage image = getBufferedImage(content, size, logoPath);
//獲得隨機(jī)數(shù)
Random random = new Random();
//生成二維碼存放文件
File file = new File(path+random.nextInt(1000)+".jpg");
if (!file.exists()) {
file.mkdirs();
}
ImageIO.write(image, imageType, file);
return true;
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
/**
* 二維碼流的形式吱窝,包含文本內(nèi)容
*
* @param content 二維碼文本內(nèi)容
* @param size 二維碼尺寸
* @param logoPath logo的存放位置
* @return
*/
public static BufferedImage getBufferedImage(String content, Integer size, String logoPath) {
if (size == null || size <= 0) {
size = 250;
}
BufferedImage image = null;
try {
// 設(shè)置編碼字符集
Map<EncodeHintType, Object> hints = new HashMap<>();
//設(shè)置編碼
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
//設(shè)置容錯率最高
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
hints.put(EncodeHintType.MARGIN, 1);
// 1兴枯、生成二維碼
MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
BitMatrix bitMatrix = multiFormatWriter.encode(content, BarcodeFormat.QR_CODE, size, size, hints);
// 2嘹害、獲取二維碼寬高
int codeWidth = bitMatrix.getWidth();
int codeHeight = bitMatrix.getHeight();
// 3、將二維碼放入緩沖流
image = new BufferedImage(codeWidth, codeHeight, BufferedImage.TYPE_INT_RGB);
for (int i = 0; i < codeWidth; i++) {
for (int j = 0; j < codeHeight; j++) {
// 4丰泊、循環(huán)將二維碼內(nèi)容定入圖片
image.setRGB(i, j, bitMatrix.get(i, j) ? BLACK : WHITE);
}
}
//判斷是否寫入logo圖片
if (logoPath != null && !"".equals(logoPath)) {
File logoPic = new File(logoPath);
if (logoPic.exists()) {
Graphics2D g = image.createGraphics();
BufferedImage logo = ImageIO.read(logoPic);
int widthLogo = logo.getWidth(null) > image.getWidth() * 2 / 10 ? (image.getWidth() * 2 / 10) : logo.getWidth(null);
int heightLogo = logo.getHeight(null) > image.getHeight() * 2 / 10 ? (image.getHeight() * 2 / 10) : logo.getHeight(null);
int x = (image.getWidth() - widthLogo) / 2;
int y = (image.getHeight() - heightLogo) / 2;
// 開始繪制圖片
g.drawImage(logo, x, y, widthLogo, heightLogo, null);
g.drawRoundRect(x, y, widthLogo, heightLogo, 15, 15);
//邊框?qū)挾? g.setStroke(new BasicStroke(2));
//邊框顏色
g.setColor(Color.WHITE);
g.drawRect(x, y, widthLogo, heightLogo);
g.dispose();
logo.flush();
image.flush();
}
}
} catch (WriterException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return image;
}
/**
* 給二維碼圖片添加Logo
*
* @param qrPic 二維碼圖片
* @param logoPic logo圖片
* @param path 合成后的圖片存儲目錄
*/
public static boolean zxingCodeCreate(File qrPic, File logoPic, String path) {
try {
String imageType = path.substring(path.lastIndexOf(".") + 1).toLowerCase();
if (!IMAGE_TYPE.contains(imageType)) {
return false;
}
if (!qrPic.isFile() && !logoPic.isFile()) {
return false;
}
//讀取二維碼圖片汇恤,并構(gòu)建繪圖對象
BufferedImage image = ImageIO.read(qrPic);
Graphics2D g = image.createGraphics();
//讀取Logo圖片
BufferedImage logo = ImageIO.read(logoPic);
//設(shè)置logo的大小,最多20%0
int widthLogo = logo.getWidth(null) > image.getWidth() * 2 / 10 ? (image.getWidth() * 2 / 10) : logo.getWidth(null);
int heightLogo = logo.getHeight(null) > image.getHeight() * 2 / 10 ? (image.getHeight() * 2 / 10) : logo.getHeight(null);
// 計(jì)算圖片放置位置,默認(rèn)在中間
int x = (image.getWidth() - widthLogo) / 2;
int y = (image.getHeight() - heightLogo) / 2;
// 開始繪制圖片
g.drawImage(logo, x, y, widthLogo, heightLogo, null);
g.drawRoundRect(x, y, widthLogo, heightLogo, 15, 15);
//邊框?qū)挾? g.setStroke(new BasicStroke(2));
//邊框顏色
g.setColor(Color.WHITE);
g.drawRect(x, y, widthLogo, heightLogo);
g.dispose();
logo.flush();
image.flush();
File newFile = new File(path);
if (!newFile.exists()) {
newFile.mkdirs();
}
ImageIO.write(image, imageType, newFile);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 二維碼的解析方法
*
* @param path 二維碼圖片目錄
* @return
*/
public static Result zxingCodeAnalyze(String path) {
try {
MultiFormatReader formatReader = new MultiFormatReader();
File file = new File(path);
if (file.exists()) {
BufferedImage image = ImageIO.read(file);
LuminanceSource source = new BufferedImageLuminanceSource(image);
Binarizer binarizer = new HybridBinarizer(source);
BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer);
Map hints = new HashMap();
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
Result result = formatReader.decode(binaryBitmap, hints);
return result;
}
} catch (IOException e) {
e.printStackTrace();
} catch (NotFoundException e) {
e.printStackTrace();
}
return null;
}
}
- 3.前端控制器調(diào)用測試:
import com.google.zxing.Result;
import com.zenithink.demo.utils.QRCodeUtil;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 二維碼調(diào)用前端控制器
*/
@RequestMapping("/Qrcode")
@RestController
public class QrcodeController {
/**
* 生成二維碼
*/
@GetMapping
public void productcode() {
QRCodeUtil.zxingCodeCreate("http://www.baidu.com", "D:/voice/picture/2018/",500,"D:/voice/picture/2018/5.jpg");
}
/**
* 解析二維碼
*/
@GetMapping("/test")
public void analysiscode() {
Result result = QRCodeUtil.zxingCodeAnalyze("D:/voice/picture/2018/759.jpg");
System.err.println("二維碼解析內(nèi)容:"+result.toString());
}
}
-
4.預(yù)覽生成結(jié)果(若是網(wǎng)址,直接可以掃碼訪問)
圖片.png