?? 本文代碼已放置 github:Mr-Write/SpringbootDemo: 各種demo案例 (github.com)
1.ZXing
1.1 概念
ZXing(Zebra Crossing)是一個(gè)開(kāi)源的條碼掃描和生成庫(kù),用于讀取和生成各種類(lèi)型的條碼和二維碼。它由 Google 開(kāi)發(fā)并發(fā)布,目前由一群開(kāi)源社區(qū)維護(hù)。
ZXing 支持多種常見(jiàn)的條碼格式,包括一維條碼(如EAN-13、Code 39、Code 128等)和二維碼(如QR碼、Data Matrix等)。它提供了各種編程接口和工具,可輕松地將條碼掃描和生成功能集成到各種應(yīng)用程序中。
主要特點(diǎn)包括:
- 讀取條碼:ZXing 庫(kù)提供了實(shí)現(xiàn)條碼掃描的功能,可以從各種圖像源(如攝像頭、圖像文件等)中讀取條碼數(shù)據(jù)。它可以自動(dòng)檢測(cè)和解碼各種類(lèi)型的條碼,提供了靈活的接口和配置選項(xiàng),以滿(mǎn)足不同應(yīng)用場(chǎng)景的需求。
- 生成條碼:ZXing 庫(kù)還支持生成各種類(lèi)型的條碼和二維碼??梢愿鶕?jù)需求指定生成的條碼類(lèi)型、內(nèi)容、尺寸、顏色等參數(shù),并將生成的條碼保存為圖像文件或直接在應(yīng)用程序中顯示。
- 跨平臺(tái)支持:ZXing 是用 Java 語(yǔ)言開(kāi)發(fā)的,因此可以在多個(gè)平臺(tái)上使用,包括 Java SE、Java EE、Android 等。它提供了 Java 編程接口,可以輕松地集成到 Java 應(yīng)用程序中。此外,它還提供了其他語(yǔ)言的接口和端口,如 .NET、Python、Ruby、Objective-C 等,以便在其他平臺(tái)上使用。
- 開(kāi)源和活躍的社區(qū)支持:ZXing 是一個(gè)開(kāi)源項(xiàng)目,其源代碼可在 GitHub 上獲得。它有一個(gè)活躍的開(kāi)源社區(qū),定期發(fā)布新的版本和更新,修復(fù)漏洞和改進(jìn)功能。用戶(hù)可以通過(guò)社區(qū)獲得支持、提交問(wèn)題或貢獻(xiàn)代碼。
ZXing 被廣泛應(yīng)用于各種領(lǐng)域,包括商業(yè)應(yīng)用、物流管理、移動(dòng)支付、票務(wù)系統(tǒng)等,它提供了方便易用的條碼掃描和生成功能,為開(kāi)發(fā)人員提供了一種簡(jiǎn)單而強(qiáng)大的工具來(lái)處理?xiàng)l碼相關(guān)的需求。
1.2 ZXing 相關(guān)依賴(lài)
<!--zxing依賴(lài)-->
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.1.0</version>
</dependency>
<!--commons-lang依賴(lài)-->
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
1.3 zxing常用API
?? EncodeHintType(編碼提示類(lèi)型)
EncodeHintType 是用來(lái)設(shè)置二維碼編碼時(shí)的一些額外參數(shù)的枚舉類(lèi)型,常用枚舉值如下:
-
ERROR_CORRECTION
:- 誤差校正級(jí)別。對(duì)于黑白二維碼,可選值為 L(7%)、M(15%)、Q(25%)、H(30%),表示二維碼允許破損的最大容錯(cuò)率。在二維碼出現(xiàn)破損時(shí),根據(jù)設(shè)置的容錯(cuò)率級(jí)別,可以嘗試修復(fù)二維碼中的一些數(shù)據(jù)。
- 二維碼在生成過(guò)程中,可能會(huì)出現(xiàn)一些損壞或者缺失的情況,例如打印時(shí)墨水耗盡、圖像壓縮、攝像頭拍攝角度不對(duì)等。這些問(wèn)題可能導(dǎo)致二維碼無(wú)法完全識(shí)別,或者識(shí)別出來(lái)的數(shù)據(jù)不準(zhǔn)確,而誤差校正碼就是為了解決這些問(wèn)題而產(chǎn)生的。
- 例如,選擇 L 級(jí)別的容錯(cuò)率,相當(dāng)于允許在二維碼的整體顏色區(qū)域中,最多可有約 7% 的壞像素點(diǎn);而選擇 H 級(jí)別的容錯(cuò)率時(shí),最多可有約 30% 的壞像素點(diǎn)。
- 注意:誤差校正級(jí)別的具體值需要通過(guò) ErrorCorrectionLevel 的枚舉值來(lái)獲取。
-
CHARACTER_SET
:- 編碼字符集??梢栽O(shè)置使用的字符編碼,例如 utf-8、gb2312 等等。
-
MARGIN
:- 二維碼的空白區(qū)域大小??梢栽O(shè)置二維碼周?chē)牧舭状笮。员阌谠诓煌那度雸?chǎng)景中使用二維碼。
?? MultiFormatWriter(多格式寫(xiě)入程序)
MultiFormatWriter 是一個(gè)便捷的二維碼生成類(lèi),可以根據(jù)傳入的 BarcodeFormat 參數(shù),生成對(duì)應(yīng)類(lèi)型的二維碼。
MultiFormatWriter 封裝了一系列的二維碼生成方法,可以生成多種格式的二維碼,包括 QR Code、Aztec Code、PDF417、Data Matrix 等。
?? BarcodeFormat(碼格式)
BarcodeFormat 是枚舉類(lèi),通過(guò)它來(lái)制定二維碼格式:
- QR Code:QR Code 是最常見(jiàn)的二維碼格式之一,廣泛應(yīng)用于商品包裝、票務(wù)、掃碼支付等領(lǐng)域。QR Code 矩陣有黑白兩種顏色,其中黑色部分表示信息的編碼,白色部分則用于襯托和辨識(shí)。
- Aztec Code:Aztec Code 是一種高密度、可靠性很高的二維碼格式。相比于其他二維碼格式,它具有更低的容錯(cuò)率、更小的尺寸和更高的解碼效率。因此,它適合用于儲(chǔ)存一些核心信息,例如個(gè)人信息、證件信息、賬戶(hù)密碼等。
- PDF417:是一種可以?xún)?chǔ)存大量信息的二維碼格式,它具有數(shù)據(jù)密度高、可靠性強(qiáng)等優(yōu)點(diǎn),可以應(yīng)用于許多場(chǎng)景,例如航空機(jī)票,運(yùn)輸和配送標(biāo)簽,法律文件等。
- Data Matrix:是一種小巧的二維碼格式,它的編碼方式類(lèi)似于 QR Code,但是其可靠性、識(shí)別率、掃描速度和牢固度都比 QR Code 更優(yōu)秀。由于尺寸較小、可靠性較高,因此 Data Matrix 適合嵌入簡(jiǎn)單的產(chǎn)品標(biāo)簽、醫(yī)療圖像、檢測(cè)數(shù)據(jù)等領(lǐng)域。
?? BitMatrix(位矩陣)
BitMatrix 是 ZXing 庫(kù)中表示二維碼矩陣的數(shù)據(jù)結(jié)構(gòu),它是由 0 和 1 構(gòu)成的二維數(shù)組,用于存儲(chǔ)二維碼的編碼信息。在二維碼生成過(guò)程中,我們通過(guò)對(duì)BitMatrix 對(duì)象的構(gòu)建和操作,最終生成一個(gè)可被掃描解碼的二維碼圖像。
BitMatrix 實(shí)際上是一個(gè) 緊湊型的布爾型二維數(shù)組,往往只需要占用一個(gè)字節(jié)即可表示 8 位二進(jìn)制。在使用 BitMatrix 時(shí),我們可以通過(guò)其不同的方法,例如get()、set() 等,來(lái)獲取、設(shè)置矩陣中每個(gè)位置的值。
在 ZXing 中,BitMatrix 常用于將編碼后的信息轉(zhuǎn)化為矩陣形式,并進(jìn)行圖像的生成和輸出。在使用 ZXing 生成二維碼時(shí),我們首先需要使用MultiFormatWriter.encode() 方法來(lái)生成一個(gè) BitMatrix;然后,在對(duì) BitMatrix 進(jìn)行各種處理和操作后,就可以在 UI 中顯示和輸出二維碼。
總的來(lái)說(shuō),BitMatrix 是 ZXing 庫(kù)中非常重要的數(shù)據(jù)結(jié)構(gòu)之一,它負(fù)責(zé)存儲(chǔ)和處理生成二維碼圖像所需的二進(jìn)制信息,是實(shí)現(xiàn)二維碼生成功能的關(guān)鍵。
BitMatrix 常用 API:
- getHeight():獲取矩陣高度;
- getWidth():獲取矩陣寬度;
- get(x, y):根據(jù)x,y的坐標(biāo)獲取矩陣中該坐標(biāo)的值。結(jié)果是true(黑色)或者false(白色)。
1.4 生成普通黑白二維碼
?? 環(huán)境配置
- JDK17
- SpringBoot 3.1.2
- maven 3.9.3
?? maven 依賴(lài)
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.1.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--zxing依賴(lài)-->
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.1.0</version>
</dependency>
<!--commons-lang依賴(lài)-->
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
</dependencies>
?? axios.js 文件
下載地址:https://unpkg.com/axios/dist/axios.min.js
將頁(yè)面內(nèi)容另存為 axios.js 文件,保存到 resources/static/js 下即可。
?? 靜態(tài)頁(yè)面
在 resources/static/html/zxing 下新建 CommonBlackWhite.html:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>生成普通黑白二維碼</title>
</head>
<body>
<input type="text" id="myContent">
<button id="myBtn">生成二維碼</button>
<hr>
<img id="myImg">
<script src="/js/axios.js"></script>
<script>
const myContent = document.querySelector("#myContent");
const myImg = document.querySelector("#myImg")
document.querySelector("#myBtn").addEventListener("click", () => {
if (myContent.value.trim() === '') {
return
}
axios.get(`http://127.0.0.1:8080/zxing/getCommonBlackWhite?content=${myContent.value.trim()}`).then(response => {
// data 就是后端傳給前端的數(shù)據(jù)
myImg.src = "data:image/png;base64," + response.data.imgEncode;
}).catch(error => {
// 當(dāng)請(qǐng)求出現(xiàn)錯(cuò)誤時(shí)的回調(diào)函數(shù)
console.log(error);
})
})
</script>
</body>
</html>
?? ZXingUtils 工具類(lèi)
/**
* @author 狐貍半面添
* @create 2023-08-28 21:35
*/
public class ZXingUtils {
public static String generateBlackWhiteCode(String content) throws WriterException, IOException {
// 使用 Google 提供的 zxing 開(kāi)源庫(kù),生成普通的黑白二維碼
// 需要?jiǎng)?chuàng)建一個(gè) Map 集合,使用這個(gè) Map 集合存儲(chǔ)二維碼相關(guān)的屬性(參數(shù))
Map<EncodeHintType, Object> map = new HashMap<>(3);
// 設(shè)置二維碼的誤差校正級(jí)別
map.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
// 設(shè)置二維碼的字符集
map.put(EncodeHintType.CHARACTER_SET, "utf-8");
// 設(shè)置二維碼四周的留白,單位為 px
map.put(EncodeHintType.MARGIN, 1);
// 創(chuàng)建 zxing 的核心對(duì)象,MultiFormatWriter(多格式寫(xiě)入器)
// 通過(guò) MultiFormatWriter 對(duì)象來(lái)生成二維碼
MultiFormatWriter writer = new MultiFormatWriter();
// writer.encode(內(nèi)容, 什么格式的二維碼, 二維碼寬度, 二維碼高度, 二維碼參數(shù))
// 位矩陣對(duì)象(位矩陣對(duì)象內(nèi)部實(shí)際上是一個(gè)二維數(shù)組,二維數(shù)組中每一個(gè)元素是 boolean 類(lèi)型,true 代表黑色,false 代表白色)
BitMatrix bitMatrix = writer.encode(content, BarcodeFormat.QR_CODE, 300, 300, map);
// 獲取矩陣的寬度
int width = bitMatrix.getWidth();
// 獲取矩陣的高度
int height = bitMatrix.getHeight();
// 生成二維碼圖片
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
// 編寫(xiě)一個(gè)嵌套循環(huán),遍歷二維數(shù)組的一個(gè)循環(huán),遍歷位矩陣對(duì)象
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
image.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);
}
}
FastByteArrayOutputStream fos = new FastByteArrayOutputStream();
ImageIO.write(image, "png", fos);
// 獲取二維碼圖片的 base64 編碼
String imgEncode = Base64.encodeBase64String(fos.toByteArray());
fos.flush();
// 返回 base64 編碼
return imgEncode;
}
}
?? Controller 類(lèi)
/**
* @author 狐貍半面添
* @create 2023-08-28 21:35
*/
@CrossOrigin // 允許跨域
@RestController
@RequestMapping("/zxing")
public class ZXingController {
@GetMapping("/getCommonBlackWhite")
public Map<String, String> getCommonBlackWhite(@RequestParam("content") String content) throws IOException, WriterException {
Map<String, String> map = new HashMap<>(1);
map.put("imgEncode", ZXingUtils.generateBlackWhiteCode(content));
return map;
}
}
?? 測(cè)試
啟動(dòng) SpringBoot 應(yīng)用,訪問(wèn)靜態(tài)頁(yè)面:http://localhost:8080/html/zxing/CommonBlackWhite.html
1.5 生成帶 logo 的黑白二維碼
在 1.4 節(jié)代碼基礎(chǔ)上進(jìn)行補(bǔ)充即可。
?? 靜態(tài)頁(yè)面
在 resources/static/html/zxing 下新建 ZXingLogo.html:
<%@page contentType="text/html;charset=UTF-8" pageEncoding="UTF-8" %>
<!doctype html>
<html>
<head>
<title>生成帶有l(wèi)ogo的黑白二維碼</title>
<meta charset="UTF-8">
</head>
<body>
<form action="/myqrcode/generateWithLogo" method="post" enctype="multipart/form-data">
請(qǐng)輸入文本內(nèi)容:<input type="text" name="url"><br>
請(qǐng)選擇圖片:<input type="file" name="logo"><br>
<input type="submit" value="生成帶有l(wèi)ogo的二維碼"/>
</form>
</body>
</html>
?? ZXingUtils 工具類(lèi)方法
public static String generateLogoCode(String content, MultipartFile logo) throws WriterException, IOException {
// 使用 Google 提供的 zxing 開(kāi)源庫(kù),生成普通的黑白二維碼
// 需要?jiǎng)?chuàng)建一個(gè) Map 集合,使用這個(gè) Map 集合存儲(chǔ)二維碼相關(guān)的屬性(參數(shù))
Map<EncodeHintType, Object> map = new HashMap<>(3);
// 設(shè)置二維碼的誤差校正級(jí)別
map.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
// 設(shè)置二維碼的字符集
map.put(EncodeHintType.CHARACTER_SET, "utf-8");
// 設(shè)置二維碼四周的留白,單位為 px
map.put(EncodeHintType.MARGIN, 1);
// 創(chuàng)建 zxing 的核心對(duì)象,MultiFormatWriter(多格式寫(xiě)入器)
// 通過(guò) MultiFormatWriter 對(duì)象來(lái)生成二維碼
MultiFormatWriter writer = new MultiFormatWriter();
// writer.encode(內(nèi)容, 什么格式的二維碼, 二維碼寬度, 二維碼高度, 二維碼參數(shù))
// 位矩陣對(duì)象(位矩陣對(duì)象內(nèi)部實(shí)際上是一個(gè)二維數(shù)組,二維數(shù)組中每一個(gè)元素是 boolean 類(lèi)型,true 代表黑色,false 代表白色)
BitMatrix bitMatrix = writer.encode(content, BarcodeFormat.QR_CODE, 300, 300, map);
// 獲取矩陣的寬度
int width = bitMatrix.getWidth();
// 獲取矩陣的高度
int height = bitMatrix.getHeight();
// 生成二維碼圖片
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
// 編寫(xiě)一個(gè)嵌套循環(huán),遍歷二維數(shù)組的一個(gè)循環(huán),遍歷位矩陣對(duì)象
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
image.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);
}
}
// 給二維碼添加 Logo
// 1.獲取 logo 圖片:通過(guò) ImageIO 的read方法,從輸入流中讀取,從而獲得 logo 圖片
BufferedImage logoImage = ImageIO.read(logo.getInputStream());
// 2.設(shè)置 logo 的寬度和高度
int logoWidth = Math.min(logoImage.getWidth(), 60);
int logoHeight = Math.min(logoImage.getHeight(), 60);
// 3.將 logo 縮放:使用平滑縮放算法對(duì)原 logo 圖像進(jìn)行縮放得到一個(gè)全新的圖像
Image scaledLogo = logoImage.getScaledInstance(logoWidth, logoHeight, Image.SCALE_SMOOTH);
// 4.將縮放后的 logo 畫(huà)到黑白二維碼上
// 4.1 獲取一個(gè) 2D 的畫(huà)筆
Graphics2D graphics2D = image.createGraphics();
// 4.2 指定開(kāi)始的坐標(biāo) x,y
int x = (300 - logoWidth) / 2;
int y = (300 - logoHeight) / 2;
// 4.3 將縮放后的 logo 畫(huà)上去
graphics2D.drawImage(scaledLogo,x,y,null);
// 4.4 創(chuàng)建一個(gè)具有指定位置、寬度、高度和圓角半徑的圓角矩形,這個(gè)圓角矩形是用來(lái)繪制邊框的
Shape shape = new RoundRectangle2D.Float(x,y,logoWidth,logoHeight,10,10);
// 4.5 使用一個(gè)寬度為 4px 的基本筆觸
graphics2D.setStroke(new BasicStroke(4f));
// 4.6 給 logo 畫(huà)圓角矩形
graphics2D.draw(shape);
// 4.7 釋放畫(huà)筆
graphics2D.dispose();
FastByteArrayOutputStream fos = new FastByteArrayOutputStream();
ImageIO.write(image, "png", fos);
// 獲取二維碼圖片的 base64 編碼
String imgEncode = Base64.encodeBase64String(fos.toByteArray());
fos.flush();
// 返回 base64 編碼
return imgEncode;
}
?? Controller 類(lèi)方法
@PostMapping("/getLogo")
public Map<String, String> getLogo(@RequestParam("content") String content, @RequestParam("logo") MultipartFile logo) throws IOException, WriterException {
Map<String, String> map = new HashMap<>(1);
map.put("imgEncode", ZXingUtils.generateLogoCode(content, logo));
return map;
}
?? 測(cè)試
啟動(dòng) SpringBoot 應(yīng)用,訪問(wèn)靜態(tài)頁(yè)面:http://localhost:8080/html/zxing/ZXingLogo.html
2.qrcode-plugin
2.1 基本說(shuō)明
- 使用的是 github 上基于 ZXing 封裝的 qrcode 開(kāi)源插件,github 地址:https://github.com/liuyueyi/quick-media
- 使用文檔:
- https://github.com/liuyueyi/quick-media/blob/master/plugins/qrcode-plugin/readme.md
- https://liuyueyi.github.io/quick-media/#/%E6%8F%92%E4%BB%B6/%E4%BA%8C%E7%BB%B4%E7%A0%81/%E4%BA%8C%E7%BB%B4%E7%A0%81%E6%8F%92%E4%BB%B6%E4%BD%BF%E7%94%A8%E6%89%8B%E5%86%8C
- maven 倉(cāng)庫(kù):https://mvnrepository.com/artifact/com.github.liuyueyi.media/qrcode-plugin
2.2 相關(guān)依賴(lài)
<dependency>
<groupId>com.github.liuyueyi.media</groupId>
<artifactId>qrcode-plugin</artifactId>
<version>3.0.0</version>
</dependency>
2.3 基本使用
靜態(tài)文件均在 resources/static/html/qrcodePlugin 下
?? 靜態(tài)頁(yè)面
?? 生成普通黑白二維碼靜態(tài)頁(yè)面
?? http://localhost:8080/html/qrcodePlugin/CommonBlackWhiteCode.html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>生成普通黑白二維碼</title>
</head>
<body>
<input type="text" id="myContent">
<button id="myBtn">生成普通黑白二維碼</button>
<hr>
<img id="myImg">
<script src="/js/axios.js"></script>
<script>
const myContent = document.querySelector("#myContent");
const myImg = document.querySelector("#myImg")
document.querySelector("#myBtn").addEventListener("click", () => {
if (myContent.value.trim() === '') {
return
}
axios.get(`http://127.0.0.1:8080/qrcode-plugin/getCommonBlackWhiteCode?content=${myContent.value.trim()}`).then(response => {
// data 就是后端傳給前端的數(shù)據(jù)
myImg.src = "data:image/png;base64," + response.data.imgEncode;
}).catch(error => {
// 當(dāng)請(qǐng)求出現(xiàn)錯(cuò)誤時(shí)的回調(diào)函數(shù)
console.log(error);
})
})
</script>
</body>
</html>
?? 生成帶 logo 二維碼靜態(tài)頁(yè)面
?? http://localhost:8080/html/qrcodePlugin/LogoBlackWhiteCode.html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>生成帶 logo 的二維碼</title>
</head>
<body>
請(qǐng)輸入文本內(nèi)容: <input type="text" name="content" id="myContent"><br>
請(qǐng)選擇圖片: <input type="file" name="logo" id="myLogo"><br>
<button id="myBtn" id="myBtn">生成帶 logo 二維碼</button>
<hr>
<img id="myImg">
<script src="/js/axios.js"></script>
<script>
const myContent = document.querySelector("#myContent");
const myLogo = document.querySelector("#myLogo")
const myImg = document.querySelector("#myImg")
document.querySelector("#myBtn").addEventListener("click", () => {
if (myContent.value.trim() === '' || myLogo.files.length === 0) {
return
}
axios.post('http://127.0.0.1:8080/qrcode-plugin/getLogoBlackWhiteCode', {
logo: myLogo.files[0],
content: myContent.value
}, {
headers: {
"Content-Type": "multipart/form-data",
},
}).then(response => {
// data 就是后端傳給前端的數(shù)據(jù)
myImg.src = "data:image/png;base64," + response.data.imgEncode;
}).catch(error => {
// 當(dāng)請(qǐng)求出現(xiàn)錯(cuò)誤時(shí)的回調(diào)函數(shù)
console.log(error);
})
})
</script>
</body>
</html>
?? 生成彩色二維碼靜態(tài)頁(yè)面
?? http://localhost:8080/html/qrcodePlugin/ColorCode.html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>生成彩色二維碼</title>
</head>
<body>
<input type="text" id="myContent">
<button id="myBtn">生成彩色二維碼</button>
<hr>
<img id="myImg">
<script src="/js/axios.js"></script>
<script>
const myContent = document.querySelector("#myContent");
const myImg = document.querySelector("#myImg")
document.querySelector("#myBtn").addEventListener("click", () => {
if (myContent.value.trim() === '') {
return
}
axios.get(`http://127.0.0.1:8080/qrcode-plugin/getColorCode?content=${myContent.value.trim()}`).then(response => {
// data 就是后端傳給前端的數(shù)據(jù)
myImg.src = "data:image/png;base64," + response.data.imgEncode;
}).catch(error => {
// 當(dāng)請(qǐng)求出現(xiàn)錯(cuò)誤時(shí)的回調(diào)函數(shù)
console.log(error);
})
})
</script>
</body>
</html>
?? 生成帶背景圖的黑白二維碼靜態(tài)頁(yè)面
?? http://localhost:8080/html/qrcodePlugin/BgBlackWhiteCode.html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>生成帶背景圖的黑白二維碼</title>
</head>
<body>
請(qǐng)輸入文本內(nèi)容: <input type="text" name="content" id="myContent"><br>
請(qǐng)選擇圖片: <input type="file" name="logo" id="myBgImg"><br>
<button id="myBtn" id="myBtn">生成帶背景圖的黑白二維碼</button>
<hr>
<img id="myImg">
<script src="/js/axios.js"></script>
<script>
const myContent = document.querySelector("#myContent");
const myBgImg = document.querySelector("#myBgImg")
const myImg = document.querySelector("#myImg")
document.querySelector("#myBtn").addEventListener("click", () => {
if (myContent.value.trim() === '' || myBgImg.files.length === 0) {
return
}
axios.post('http://127.0.0.1:8080/qrcode-plugin/getBgBlackWhiteCode', {
backgroundImage: myBgImg.files[0],
content: myContent.value
}, {
headers: {
"Content-Type": "multipart/form-data",
},
}).then(response => {
// data 就是后端傳給前端的數(shù)據(jù)
myImg.src = "data:image/png;base64," + response.data.imgEncode;
}).catch(error => {
// 當(dāng)請(qǐng)求出現(xiàn)錯(cuò)誤時(shí)的回調(diào)函數(shù)
console.log(error);
})
})
</script>
</body>
</html>
?? 生成特殊形狀的二維碼靜態(tài)頁(yè)面
?? http://localhost:8080/html/qrcodePlugin/ShapeCode.html文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-684527.html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>生成特殊形狀的二維碼</title>
</head>
<body>
<input type="text" id="myContent">
<button id="myBtn">生成特殊形狀的二維碼</button>
<hr>
<img id="myImg">
<script src="/js/axios.js"></script>
<script>
const myContent = document.querySelector("#myContent");
const myImg = document.querySelector("#myImg")
document.querySelector("#myBtn").addEventListener("click", () => {
if (myContent.value.trim() === '') {
return
}
axios.get(`http://127.0.0.1:8080/qrcode-plugin/getShapeCode?content=${myContent.value.trim()}`).then(response => {
// data 就是后端傳給前端的數(shù)據(jù)
myImg.src = "data:image/png;base64," + response.data.imgEncode;
}).catch(error => {
// 當(dāng)請(qǐng)求出現(xiàn)錯(cuò)誤時(shí)的回調(diào)函數(shù)
console.log(error);
})
})
</script>
</body>
</html>
?? 生成圖片填充二維碼靜態(tài)頁(yè)面
?? http://localhost:8080/html/qrcodePlugin/ImgFillCode.html文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-684527.html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>生成圖片填充二維碼</title>
</head>
<body>
請(qǐng)輸入文本內(nèi)容: <input type="text" name="content" id="myContent"><br>
請(qǐng)選擇圖片: <input type="file" name="logo" id="myFillImg"><br>
<button id="myBtn" id="myBtn">生成圖片填充二維碼</button>
<hr>
<img id="myImg">
<script src="/js/axios.js"></script>
<script>
const myContent = document.querySelector("#myContent");
const myFillImg = document.querySelector("#myFillImg")
const myImg = document.querySelector("#myImg")
document.querySelector("#myBtn").addEventListener("click", () => {
if (myContent.value.trim() === '' || myFillImg.files.length === 0) {
return
}
axios.post('http://127.0.0.1:8080/qrcode-plugin/getImgFillCode', {
fillImg: myFillImg.files[0],
content: myContent.value
}, {
headers: {
"Content-Type": "multipart/form-data",
},
}).then(response => {
// data 就是后端傳給前端的數(shù)據(jù)
myImg.src = "data:image/png;base64," + response.data.imgEncode;
}).catch(error => {
// 當(dāng)請(qǐng)求出現(xiàn)錯(cuò)誤時(shí)的回調(diào)函數(shù)
console.log(error);
})
})
</script>
</body>
</html>
?? QrCodePluginUtils 工具類(lèi)
/**
* @author 狐貍半面添
* @create 2023-08-29 21:41
*/
public class QrCodePluginUtils {
private static String imageParseBase64(BufferedImage image) throws IOException {
FastByteArrayOutputStream fos = new FastByteArrayOutputStream();
ImageIO.write(image, "png", fos);
// 獲取二維碼圖片的 base64 編碼
String imgEncode = Base64.encodeBase64String(fos.toByteArray());
fos.flush();
return imgEncode;
}
/**
* 生成普通黑白二維碼
*
* @param content 文本內(nèi)容
* @return 圖片base64編碼
*/
public static String generateBlackWhiteCode(String content) throws IOException, WriterException {
return imageParseBase64(QrCodeGenWrapper.of(content).asBufferedImage());
}
/**
* 生成帶 logo 的黑白二維碼
*
* @param content 文本內(nèi)容
* @param logo logo文件
* @return 圖片base64編碼
*/
public static String generateLogoBlackWhiteCode(String content, MultipartFile logo) throws IOException, WriterException {
BufferedImage image = QrCodeGenWrapper.of(content)
.setLogo(logo.getInputStream())
// 設(shè)置 logo 圖片與二維碼之間的比例,10 表示 logo 的寬度等于二維碼的 1/10
.setLogoRate(10)
// 設(shè)置 logo 圖片的樣式,將 logo 的邊框形狀設(shè)置為圓形
.setLogoStyle(QrCodeOptions.LogoStyle.ROUND)
.asBufferedImage();
return imageParseBase64(image);
}
/**
* 生成彩色二維碼
*
* @param content 文本內(nèi)容
* @param color 顏色
* @return 圖片base64編碼
*/
public static String generateColorCode(String content, Color color) throws IOException, WriterException {
BufferedImage image = QrCodeGenWrapper.of(content)
// 指定畫(huà)筆顏色
.setDrawPreColor(color)
.asBufferedImage();
return imageParseBase64(image);
}
/**
* 生成帶背景圖片的黑白二維碼
*
* @param content 文本內(nèi)容
* @param backgroundImage 背景圖文件
* @return 圖片base64編碼
*/
public static String generateBgBlackWhiteCode(String content, MultipartFile backgroundImage) throws IOException, WriterException {
BufferedImage image = QrCodeGenWrapper.of(content)
// 設(shè)置背景圖
.setBgImg(backgroundImage.getInputStream())
// 設(shè)置背景圖透明度
.setBgOpacity(0.7F)
.asBufferedImage();
return imageParseBase64(image);
}
/**
* 生成帶特殊形狀的二維碼
*
* @param content 文本內(nèi)容
* @param drawStyle 繪制樣式
* @return 圖片base64編碼
*/
public static String generateShapeCode(String content, QrCodeOptions.DrawStyle drawStyle) throws IOException, WriterException {
BufferedImage image = QrCodeGenWrapper.of(content)
// 啟用二維碼繪制時(shí)的縮放功能
.setDrawEnableScale(true)
// 指定繪制樣式
.setDrawStyle(drawStyle)
.asBufferedImage();
return imageParseBase64(image);
}
/**
* 生成圖片填充二維碼
*
* @param content 文本內(nèi)容
* @param fillImg 填充圖片
* @return 圖片base64編碼
*/
public static String generateImgFillCode(String content, MultipartFile fillImg) throws IOException, WriterException {
BufferedImage image = QrCodeGenWrapper.of(content)
// 設(shè)置二維碼的錯(cuò)誤糾正級(jí)別
.setErrorCorrection(ErrorCorrectionLevel.H)
// 繪制二維碼時(shí)采用圖片填充
.setDrawStyle(QrCodeOptions.DrawStyle.IMAGE)
// 設(shè)置填充的圖片
.addImg(1, 1, fillImg.getInputStream())
.asBufferedImage();
return imageParseBase64(image);
}
}
?? QrCodePluginController 控制類(lèi)
/**
* @author 狐貍半面添
* @create 2023-08-29 21:37
*/
@CrossOrigin
@RestController
@RequestMapping("/qrcode-plugin")
public class QrCodePluginController {
/**
* 生成普通黑白二維碼
*
* @param content 文本內(nèi)容
* @return 圖片base64編碼
*/
@GetMapping("/getCommonBlackWhiteCode")
public Map<String, String> getCommonBlackWhiteCode(@RequestParam("content") String content) throws IOException, WriterException {
Map<String, String> map = new HashMap<>(1);
map.put("imgEncode", QrCodePluginUtils.generateBlackWhiteCode(content));
return map;
}
/**
* 生成帶 logo 的黑白二維碼
*
* @param content 文本內(nèi)容
* @param logo logo文件
* @return 圖片base64編碼
*/
@PostMapping("/getLogoBlackWhiteCode")
public Map<String, String> getLogoBlackWhiteCode(@RequestParam("content") String content, @RequestParam("logo") MultipartFile logo) throws IOException, WriterException {
Map<String, String> map = new HashMap<>(1);
map.put("imgEncode", QrCodePluginUtils.generateLogoBlackWhiteCode(content, logo));
return map;
}
/**
* 生成彩色二維碼
*
* @param content 文本內(nèi)容
* @return 圖片base64編碼
*/
@GetMapping("/getColorCode")
public Map<String, String> getColorCode(@RequestParam("content") String content) throws IOException, WriterException {
Map<String, String> map = new HashMap<>(1);
// 二維碼顏色可以由前端傳過(guò)來(lái)進(jìn)行指定
map.put("imgEncode", QrCodePluginUtils.generateColorCode(content, Color.BLUE));
return map;
}
/**
* 生成帶背景圖片的黑白二維碼
*
* @param content 文本內(nèi)容
* @param backgroundImage 背景圖文件
* @return 圖片base64編碼
*/
@PostMapping("/getBgBlackWhiteCode")
public Map<String, String> getBgBlackWhiteCode(@RequestParam("content") String content, @RequestParam("backgroundImage") MultipartFile backgroundImage) throws IOException, WriterException {
Map<String, String> map = new HashMap<>(1);
map.put("imgEncode", QrCodePluginUtils.generateBgBlackWhiteCode(content, backgroundImage));
return map;
}
/**
* 生成帶特殊形狀的二維碼
*
* @param content 文本內(nèi)容
* @return 圖片base64編碼
*/
@GetMapping("/getShapeCode")
public Map<String, String> getShapeCode(@RequestParam("content") String content) throws IOException, WriterException {
Map<String, String> map = new HashMap<>(1);
// 繪制樣式可以由前端傳過(guò)來(lái)進(jìn)行指定,這里設(shè)定為 鉆石
map.put("imgEncode", QrCodePluginUtils.generateShapeCode(content, QrCodeOptions.DrawStyle.DIAMOND));
return map;
}
/**
* 生成圖片填充二維碼
*
* @param content 文本內(nèi)容
* @param fillImg 填充圖片
* @return 圖片base64編碼
*/
@PostMapping("/getImgFillCode")
public Map<String, String> getImgFillCode(@RequestParam("content") String content, @RequestParam("fillImg") MultipartFile fillImg) throws IOException, WriterException {
Map<String, String> map = new HashMap<>(1);
map.put("imgEncode", QrCodePluginUtils.generateImgFillCode(content, fillImg));
return map;
}
}
到了這里,關(guān)于Java生成二維碼(前后端分離項(xiàng)目實(shí)戰(zhàn))的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!