ZXing 生成、讀取二維碼(帶logo)
前言
ZXing,一個支援在影象中解碼和生成條形碼(如二維碼、PDF 417、EAN、UPC、Aztec、Data Matrix、Codabar)的庫。ZXing(“zebra crossing”)是一個開源的、多格式的、用Java實現的一維/二維條碼影象處理庫,具有到其他語言的埠。
GitHub地址,猛戳:https://github.com/zxing/zxing
API文件,猛戳:https://zxing.github.io/zxing/apidocs/index.html
介紹文件,猛戳:https://zxing.github.io/zxing/
程式碼編寫
部分程式碼參考:https://blog.csdn.net/weixin_39494923/article/details/79058799
maven
我們是java端,所以需要引這兩個
<!-- ZXing -->
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.3.3</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.3.3</version>
</dependency>
Test.java
public class Test{
public static void main(String[] args) {
try {
QREncode();
QRReader(new File("D:\\zxing1.gif"));
} catch (WriterException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (NotFoundException e) {
e.printStackTrace();
}
}
/**
* 生成二維碼
*/
public static void QREncode() throws WriterException, IOException {
String content = "個人部落格:https://www.cnblogs.com/huanzi-qch/";//二維碼內容
int width = 200; // 影象寬度
int height = 200; // 影象高度
String format = "gif";// 影象型別
Map<EncodeHintType, Object> hints = new HashMap<>();
//內容編碼格式
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
// 指定糾錯等級
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
//設定二維碼邊的空度,非負數
hints.put(EncodeHintType.MARGIN, 1);
BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints);
MatrixToImageWriter.writeToPath(bitMatrix, format, new File("D:\\zxing.gif").toPath());// 輸出原圖片
MatrixToImageConfig matrixToImageConfig = new MatrixToImageConfig(0xFF000001, 0xFFFFFFFF);
/*
問題:生成二維碼正常,生成帶logo的二維碼logo變成黑白
原因:MatrixToImageConfig預設黑白,需要設定BLACK、WHITE
解決:https://ququjioulai.iteye.com/blog/2254382
*/
BufferedImage bufferedImage = LogoMatrix(MatrixToImageWriter.toBufferedImage(bitMatrix,matrixToImageConfig), new File("D:\\logo.png"));
// BufferedImage bufferedImage = LogoMatrix(toBufferedImage(bitMatrix), new File("D:\\logo.png"));
ImageIO.write(bufferedImage, "gif", new File("D:\\zxing1.gif"));//輸出帶logo圖片
System.out.println("輸出成功.");
}
/**
* 識別二維碼
*/
public static void QRReader(File file) throws IOException, NotFoundException {
MultiFormatReader formatReader = new MultiFormatReader();
//讀取指定的二維碼檔案
BufferedImage bufferedImage =ImageIO.read(file);
BinaryBitmap binaryBitmap= new BinaryBitmap(new HybridBinarizer(new BufferedImageLuminanceSource(bufferedImage)));
//定義二維碼引數
Map hints= new HashMap<>();
hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
com.google.zxing.Result result = formatReader.decode(binaryBitmap, hints);
//輸出相關的二維碼資訊
System.out.println("解析結果:"+result.toString());
System.out.println("二維碼格式型別:"+result.getBarcodeFormat());
System.out.println("二維碼文字內容:"+result.getText());
bufferedImage.flush();
}
/**
* 二維碼新增logo
* @param matrixImage 源二維碼圖片
* @param logoFile logo圖片
* @return 返回帶有logo的二維碼圖片
* 參考:https://blog.csdn.net/weixin_39494923/article/details/79058799
*/
public static BufferedImage LogoMatrix(BufferedImage matrixImage, File logoFile) throws IOException{
/**
* 讀取二維碼圖片,並構建繪圖物件
*/
Graphics2D g2 = matrixImage.createGraphics();
int matrixWidth = matrixImage.getWidth();
int matrixHeigh = matrixImage.getHeight();
/**
* 讀取Logo圖片
*/
BufferedImage logo = ImageIO.read(logoFile);
//開始繪製圖片
g2.drawImage(logo,matrixWidth/5*2,matrixHeigh/5*2, matrixWidth/5, matrixHeigh/5, null);//繪製
BasicStroke stroke = new BasicStroke(5,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND);
g2.setStroke(stroke);// 設定筆畫物件
//指定弧度的圓角矩形
RoundRectangle2D.Float round = new RoundRectangle2D.Float(matrixWidth/5*2, matrixHeigh/5*2, matrixWidth/5, matrixHeigh/5,20,20);
g2.setColor(Color.white);
g2.draw(round);// 繪製圓弧矩形
//設定logo 有一道灰色邊框
BasicStroke stroke2 = new BasicStroke(1,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND);
g2.setStroke(stroke2);// 設定筆畫物件
RoundRectangle2D.Float round2 = new RoundRectangle2D.Float(matrixWidth/5*2+2, matrixHeigh/5*2+2, matrixWidth/5-4, matrixHeigh/5-4,20,20);
g2.setColor(new Color(128,128,128));
g2.draw(round2);// 繪製圓弧矩形
g2.dispose();
matrixImage.flush() ;
return matrixImage ;
}
}
效果演示
D盤檔案
檢視圖片
後臺識別、微信掃描結果
後記
後端生成我們可以用ZXing框架,那麼前端js又應該如何生成、識別二維碼呢?QRCode.js,QRCode.js 是一個用於生成二維碼的 JavaScript 庫。主要是通過獲取 DOM 的標籤,再通過 HTML5 Canvas 繪製而成,不依賴任何庫。菜鳥教程,猛戳:http://www.runoob.com/w3cnote/javascript-qrcodejs-library.html
但是qrcode預設不支援自定義logo,怎麼辦呢?兩種方法:
1、建立一個img標籤,調整樣式,讓logo在二維碼區域上居中顯示
2、建立一個canvas畫布,將二維碼跟logo重新繪製,讓logo在二維碼區域上居中顯示
補充
2020-02-25補充:實現二維碼輸出到瀏覽器功能
1、生成二維碼時,不是直接儲存成圖片,而是返回BufferedImage
/**
* 生成二維碼
*/
public static BufferedImage QREncode(String content){
int width = 250; // 影象寬度
int height = 250; // 影象高度
Map<EncodeHintType, Object> hints = new HashMap<>();
//內容編碼格式
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
// 指定糾錯等級
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
//設定二維碼邊的空度,非負數
hints.put(EncodeHintType.MARGIN, 1);
BitMatrix bitMatrix = null;
BufferedImage bufferedImage = null;
try {
bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints);
MatrixToImageConfig matrixToImageConfig = new MatrixToImageConfig(0xFF000001, 0xFFFFFFFF);
bufferedImage = MatrixToImageWriter.toBufferedImage(bitMatrix,matrixToImageConfig);
} catch (WriterException e) {
e.printStackTrace();
}
//無logo
//return bufferedImage;
//帶logo,System.getProperty("user.dir")是專案工程根路徑
assert bufferedImage != null;
return LogoMatrix(bufferedImage,new File(System.getProperty("user.dir") + "\\src\\main\\resources\\static\\img\\logo.png"));
}
2、新增controller,供web呼叫
//獲取二維碼圖片
@GetMapping("getBarCodeImage/{id}")
public void getBarCodeImage(@PathVariable("id") String id) throws IOException {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getResponse();
//設定頁面不快取
assert response != null;
response.setHeader("Pragma", "no-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
response.getOutputStream();
//設定輸出的內容的型別為JPEG影象
response.setContentType("image/jpeg");
//通過id查詢資料設定二維碼內容
String text = "{\"id\":\""+ id +"\"}"
BufferedImage bufferedImage = QREncode(text);
//寫給瀏覽器
ImageIO.write(bufferedImage, "JPEG", response.getOutputStream());
}
3、web頁面呼叫,thymeleaf語法
<img id="barCodeImage" th:src="@{'/getBarCodeImage/' + ${id}}"/>
<br/><br/>
<button th:onclick="${'document.getElementById(''barCodeImage'').src = ctx + ''/getBarCodeImage/'+ id +'?time='' + new Date().getTime()'}">
重新整理二維碼
</button>
轉自:https://www.cnblogs.com/huanzi-qch/p/10097791.html