Java使用ZXing庫生成帶有Logo的二維碼圖片,并去除白邊動態伸縮上傳到阿里云OSS

文章目錄

    • 引言
    • 二維碼基本原理
      • 1、二維碼概述
      • 2、QR Code結構
      • 3、錯誤糾正級別
    • QR Code生成技術
      • 1、ZXing庫
      • 2、生成二維碼的步驟
    • 圖像處理技術
      • 1、嵌入Logo
      • 2. 去除白邊
    • 阿里云OSS基本概念
      • 1、OSS概述
      • 2. 主要功能
      • 3. 基本概念
    • 實戰演示
      • 1、依賴庫
      • 2、類結構
      • 3、生成普通二維碼
      • 4. 去除白邊
      • 5、普通二維碼增加Logo
      • 6. 上傳到阿里云OSS
    • 完整工具類
    • 總結

引言

在現代應用中,二維碼因其高效的信息編碼能力而被廣泛應用。為了提升二維碼的視覺效果和品牌識別度,通常會在二維碼中嵌入Logo。本文將詳細介紹使用ZXing庫生成帶有Logo的二維碼圖片,去除白邊,并將生成的二維碼上傳到阿里云OSS。此外,本文還將介紹二維碼的基本原理、QR Code的結構、圖像處理技術以及阿里云OSS的基本概念。

二維碼基本原理

1、二維碼概述

二維碼(QR Code)是一種二維條碼,可以存儲大量的數據,如URL、文本、數字等。與一維條碼相比,二維碼可以在兩個維度上存儲信息,因此具有更高的信息密度和更強的容錯能力。

2、QR Code結構

QR Code由以下部分組成:
定位圖案:位于二維碼的三個角,用于幫助掃描設備定位二維碼。
校正圖案:用于糾正掃描過程中可能出現的錯誤。
數據區域:存儲實際的數據信息。
格式信息:存儲二維碼的版本、錯誤糾正級別等信息。
版本信息:指示二維碼的版本號,版本號越高,可以存儲的數據量越大。
靜區:二維碼周圍的空白區域,用于防止二維碼與其他圖案混淆。

3、錯誤糾正級別

QR Code支持四種錯誤糾正級別:
L(Low):約7%的錯誤糾正能力。
M(Medium):約15%的錯誤糾正能力。
Q(Quartile):約25%的錯誤糾正能力。
H(High):約30%的錯誤糾正能力。

QR Code生成技術

1、ZXing庫

ZXing(Zebra Crossing)是一個開源的、多格式的1D/2D條碼圖像處理庫。它支持多種條碼格式,包括QR Code、Code 128、EAN-13等。在本文中,我們將使用ZXing庫來生成二維碼。

2、生成二維碼的步驟

創建QRCodeWriter實例:用于生成二維碼。
設置編碼提示:如字符集、錯誤糾正級別等。
生成BitMatrix:將輸入數據編碼為BitMatrix對象。
轉換為BufferedImage:將BitMatrix對象轉換為BufferedImage對象。
去除白邊:去除二維碼周圍的白邊,使二維碼更加緊湊。
嵌入Logo:在二維碼中嵌入Logo圖像。

圖像處理技術

1、嵌入Logo

在二維碼中嵌入Logo圖像可以提升視覺效果。嵌入Logo的步驟如下:
讀取Logo圖像:從指定路徑讀取Logo圖像。
調整Logo大小:根據二維碼的大小調整Logo的尺寸。
繪制Logo:將調整后的Logo繪制到二維碼的中心位置。
添加圓角:為Logo添加圓角,使其更加美觀。

2. 去除白邊

去除二維碼周圍的白邊可以減少圖像的大小,提升視覺效果。去除白邊的步驟如下:
遍歷圖像:遍歷二維碼圖像,找到非白色像素的邊界。
裁剪圖像:根據找到的邊界裁剪圖像,去除白邊。

阿里云OSS基本概念

1、OSS概述

阿里云對象存儲服務(Object Storage Service,簡稱OSS)是阿里云提供的海量、安全、低成本、高可靠的云存儲服務。OSS適合存放任意類型的文件,如圖片、音視頻、日志文件、備份文件等。

2. 主要功能

存儲和分發:提供高可用性和持久性的存儲服務。
權限管理:支持細粒度的訪問控制。
數據處理:提供圖像處理、視頻處理等增值服務。
監控和日志:提供詳細的監控和日志記錄。

3. 基本概念

Bucket:存儲空間,用于存放文件。
Object:存儲在Bucket中的文件。
Endpoint:訪問OSS的域名。
Access Key ID 和 Access Key Secret:用于身份驗證的密鑰對。

實戰演示

1、依賴庫

為了實現二維碼生成和圖像處理功能,QRCodeWithLogoUtil 使用了以下依賴庫:
ZXing (Zebra Crossing):一個開源的、多格式的1D/2D條碼圖像處理庫。
Apache Commons Imaging:用于圖像處理和操作。
阿里云OSS SDK:用于上傳文件到阿里云OSS。
在 pom.xml 中添加以下依賴:

<!--安裝OSS SDK-->
<dependency><groupId>com.aliyun.oss</groupId><artifactId>aliyun-sdk-oss</artifactId><version>3.16.3</version>
</dependency>
<!-- ZXing core -->
<dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.3</version>
</dependency>
<!-- ZXing javase -->
<dependency><groupId>com.google.zxing</groupId><artifactId>javase</artifactId><version>3.5.3</version>
</dependency>

2、類結構

在這里插入圖片描述

3、生成普通二維碼

generateQRCodeImage(String text, int width, int height) 方法用于生成帶有Logo的二維碼。
在這里插入圖片描述

4. 去除白邊

deleteWhite(BitMatrix matrix,int qrWidth,int qrHeight)
方法用于去除二維碼周圍的白邊,使二維碼更加緊湊,去除白邊后對二維碼圖片進行拉伸滿足業務要求。
在這里插入圖片描述

5、普通二維碼增加Logo

addLogoToQrCode(BufferedImage qrCodeImage, BufferedImage logoImage,int loginWidth,int loginHeight) 方法在原始的 二維碼基礎上增加logo。
在這里插入圖片描述

6. 上傳到阿里云OSS

generateQrCodeImageAndUploadToOss(String qrText, int width, int height,String logoName,int loginWidth,int loginHeight,String objectName) 方法作為調用入口,將二維碼創建完成后并將生成的二維碼上傳到阿里云OS。
在這里插入圖片描述

完整工具類

/*** QRCodeWithLogoUtil* @author senfel* @version 1.0* @date 2025/2/25 14:31*/
@Component
@Slf4j
public class QRCodeWithLogoUtil {private static final String ENDPOINT = "https://oss-cn-shanghai.aliyuncs.com";private static final String ACCESS_KEY_ID = "LTAI5tB91wtXft75XXXX";private static final String ACCESS_KEY_SECRET = "ecgR2ZCAb9uXXXXXX";private static final String BUCKET_NAME = "cn-sh-dev-csa-oss-01";private static OSS OSS_CLIENT = null;static {// 創建OSSClient實例。OSS_CLIENT = new OSSClientBuilder().build(ENDPOINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET);}public static void main(String[] args) throws Exception {// 二維碼內容String qrText = "https://XXXXX/code/mp?scene=dp&dpsource=scancode&b=fdzInN0FwUuL4a5E";// logo圖片名稱,放置在resourceString logoName = "inchanel-logo.png";String objectName = "moi/fdzInN0FwUuL4a5E222.png";int width = 100;int height = 100;int loginWidth = 26;int loginHeight = 26;String s = generateQrCodeImageAndUploadToOss(qrText, width, height, logoName, loginWidth, loginHeight, objectName);System.err.println(s);}/*** generateQrCodeImageAndUploadToOss* @param qrText* @param width* @param height* @param logoName* @param loginWidth* @param loginHeight* @param objectName* @author senfel* @date 2025/2/26 10:01* @return java.lang.String*/public static String generateQrCodeImageAndUploadToOss(String qrText, int width, int height,String logoName,int loginWidth,int loginHeight,String objectName) throws Exception {try {BufferedImage qrImage = generateQRCodeImage(qrText, width, height);BufferedImage logoImage = ImageIO.read(Objects.requireNonNull(QRCodeWithLogoUtil.class.getClassLoader().getResource(logoName)));BufferedImage finalImage = addLogoToQrCode(qrImage, logoImage,loginWidth,loginHeight);ByteArrayOutputStream os = new ByteArrayOutputStream();ImageIO.write(finalImage, "PNG", os);// 將圖片保存在內存中,imageBytes即為二維碼圖片的字節流byte[] imageBytes = os.toByteArray();//保存本地//ImageIO.write(finalImage, "PNG", new File("D:\\blank\\fdzInN0FwUuL4a5E22.png"));//將圖片上傳到oss//將imageBytes轉為輸入流ByteArrayInputStream inputStream = new ByteArrayInputStream(imageBytes);PutObjectRequest putObjectRequest = new PutObjectRequest(BUCKET_NAME, objectName, inputStream);OSS_CLIENT.putObject(putObjectRequest);VoidResult voidResult = OSS_CLIENT.setObjectAcl(BUCKET_NAME, objectName, CannedAccessControlList.PublicRead);if( 200 != voidResult.getResponse().getStatusCode()){log.error("QRCodeWithLogoUtil上傳圖片到OSS失敗,響應信息為:{}", voidResult.getResponse());throw new RuntimeException("QRCodeWithLogoUtil上傳圖片到OSS失敗");}return voidResult.getResponse().getUri().substring(0,voidResult.getResponse().getUri().indexOf("?"));} catch (Exception e) {log.error("QRCodeWithLogoUtil生成二維碼失敗,異常信息為:{}", e.getMessage(),e);throw new RuntimeException("QRCodeWithLogoUtil生成二維碼失敗");}}/*** generateQRCodeImage* @param text* @param width* @param height* @author senfel* @date 2025/2/25 19:00* @return java.awt.image.BufferedImage*/private static BufferedImage generateQRCodeImage(String text, int width, int height) throws WriterException {Map<EncodeHintType, Object> hints = new HashMap<>();hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);BitMatrix bitMatrix = new MultiFormatWriter().encode(text, BarcodeFormat.QR_CODE, width, height, hints);return deleteWhite(bitMatrix,width,height);}/*** deleteWhite* @param matrix* @param qrWidth* @param qrHeight* @author senfel* @date 2025/2/25 19:00* @return java.awt.image.BufferedImage*/private static BufferedImage deleteWhite(BitMatrix matrix,int qrWidth,int qrHeight) {int[] rec = matrix.getEnclosingRectangle();int resWidth = rec[2];int resHeight = rec[3];BitMatrix resMatrix = new BitMatrix(resWidth, resHeight);resMatrix.clear();for (int i = 0; i < resWidth; i++) {for (int j = 0; j < resHeight; j++) {if (matrix.get(i + rec[0], j + rec[1]))resMatrix.set(i, j);}}int width = resMatrix.getWidth();int height = resMatrix.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, resMatrix.get(x, y) ? 0 : 255);}}//生成二維碼BufferedImage bufferedImage = MatrixToImageWriter.toBufferedImage(resMatrix);// 若二維碼的實際寬高和預期的寬高不一致, 則縮放if (qrWidth != width || qrHeight != height) {BufferedImage tmp = new BufferedImage(qrWidth, qrHeight, BufferedImage.TYPE_INT_RGB);tmp.getGraphics().drawImage(bufferedImage.getScaledInstance(qrWidth, qrHeight,Image.SCALE_SMOOTH), 0, 0, null);bufferedImage = tmp;}return bufferedImage;}/*** addLogoToQrCode* @param qrCodeImage* @param logoImage* @param loginWidth* @param loginHeight* @author senfel* @date 2025/2/26 17:42* @return java.awt.image.BufferedImage*/private static BufferedImage addLogoToQrCode(BufferedImage qrCodeImage, BufferedImage logoImage,int loginWidth,int loginHeight) {Graphics2D graphics = qrCodeImage.createGraphics();// Logo圖片左上角的x坐標,可根據需要調整位置int x = (qrCodeImage.getWidth() - loginWidth) / 2;// Logo圖片左上角的y坐標,可根據需要調整位置int y = (qrCodeImage.getHeight() - loginHeight) / 2;// 設置抗鋸齒graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);// 繪制Logo圖片到二維碼上graphics.drawImage(logoImage, x, y, loginWidth, loginHeight, null);// 釋放資源graphics.dispose();// 返回帶有Logo的二維碼圖片對象return qrCodeImage;}
}

效果展示

在這里插入圖片描述

在這里插入圖片描述

總結

通過本文的介紹,你已經了解了使用ZXing庫生成帶有Logo的二維碼圖片,去除白邊,并將生成的二維碼上傳到阿里云OSS。此外,本文還介紹了二維碼的基本原理、QR Code的結構、圖像處理技術以及阿里云OSS的基本概念。這個工具類可以廣泛應用于各種需要生成二維碼的場景,提升用戶體驗和品牌識別度。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/70902.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/70902.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/70902.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

AI工具箱最新使用教程

先克隆項目 電腦需要先安裝 git &#xff0c;安裝的畫看這個 Git安裝教程&#xff08;超詳細&#xff09;。 git鏡像 git clone https://github.com/Escaflowne1985/MyToolsWebBackendUser.gitgitee鏡像 git clone https://gitee.com/escaflowne/MyToolsWebBackendUser.git…

Android-創建mipmap-anydpi-v26的Logo

利用 Android Studio 自動創建 創建新項目&#xff1a;打開 Android Studio&#xff0c;點擊 “Start a new Android Studio project” 創建新項目。在創建項目的過程中&#xff0c;當設置Target SDK Version為 26 或更高版本時&#xff0c;Android Studio 會在項目的res目錄下…

SEO煉金術(4)| Next.js SEO 全攻略

在上一篇文章 SEO煉金術&#xff08;3&#xff09;| 深入解析 SEO 關鍵要素 中&#xff0c;我們深入解析了 SEO 關鍵要素&#xff0c;包括 meta 標簽、robots.txt、canonical、sitemap.xml 和 hreflang&#xff0c;并探討了它們在搜索引擎優化&#xff08;SEO&#xff09;中的作…

面試葵花寶典之React(持續更新中)

1.談談你對HOC的理解 定義&#xff1a; 高階組件是一個接收組件作為參數并返回新組件的函數&#xff0c;用于復用組件邏輯&#xff0c;遵循純函數特性&#xff08;無副作用&#xff0c;輸出僅依賴輸入&#xff09;。 組合性&#xff1a;可嵌套使用多個 HOC。 HOC&#xff08;…

數據安全管理的AI工具有哪些?

數據安全管理的AI工具在不斷演進&#xff0c;它們憑借強大的算法和學習能力&#xff0c;為企業筑起了一道堅不可摧的數字防線。 在數據安全管理領域&#xff0c;AI工具的應用日益廣泛&#xff0c;以下是一些常見的工具及其功能&#xff1a; AI驅動的數據分類與標記 工具: Micr…

Matplotlib 繪圖標記

Matplotlib 繪圖標記 引言 Matplotlib 是一個功能強大的 Python 繪圖庫&#xff0c;廣泛用于數據可視化。在 Matplotlib 中&#xff0c;繪圖標記&#xff08;markers&#xff09;是數據點在圖表中顯示的方式。正確的使用繪圖標記可以增強圖表的可讀性和美觀性。本文將詳細介紹…

【DeepSeek問答】QProcess::start是異步的嗎?會使UI卡頓嗎?

好的&#xff0c;我現在需要回答用戶關于QProcess::start是否是異步的&#xff0c;以及它是否會導致UI卡頓的問題。用戶之前已經詢問過如何開發一個調用7-Zip的Qt應用&#xff0c;并且我給出了示例代碼。現在用戶可能在使用過程中遇到了問題&#xff0c;或者想更深入了解QProce…

Android 常用命令和工具解析之存儲相關

1 基本概念 2 命令解讀 2.1 adb shell df df 命令主要用于需要檢查文件系統上已使用和可用的磁盤空間的數量。如果沒有指定文件名&#xff0c;則顯示在當前所有掛載的文件系統上可用的空間。其原理是從proc/mounts 或 /etc/mtab 中檢索磁盤信息。 注意&#xff1a;df命令并…

使用ZFile打造屬于自己的私有云系統結合內網穿透實現安全遠程訪問

文章目錄 前言1.關于ZFile2.本地部署ZFile3.ZFile本地訪問測試4.ZFile的配置5.cpolar內網穿透工具安裝6.創建遠程連接公網地址7.固定ZFile公網地址 前言 在數字化的今天&#xff0c;我們每個人都是信息的小能手。無論是職場高手、攝影達人還是學習狂人&#xff0c;每天都在創造…

HarmonyOS 5.0應用開發——鴻蒙接入高德地圖實現POI搜索

【高心星出品】 文章目錄 鴻蒙接入高德地圖實現POI搜索運行結果&#xff1a;準備地圖編寫ArkUI布局來加載HTML地圖 鴻蒙接入高德地圖實現POI搜索 在當今數字化時代&#xff0c;地圖應用已成為移動設備中不可或缺的一部分。隨著鴻蒙系統的日益普及&#xff0c;如何在鴻蒙應用中…

idea + Docker + 阿里鏡像服務打包部署

一、下載docker desktop軟件 官網下載docker desktop&#xff0c;需要結合wsl使用 啟動成功的畫面(如果不是這個畫面例如一直處理start或者是stop需要重新啟動&#xff0c;不行就重啟電腦) 打包成功的鏡像在這里&#xff0c;如果頻繁打包會導致磁盤空間被占滿&#xff0c;需…

IP---網絡類型

這只是IP的其中一塊內容-網絡類型&#xff0c;IP還有更多內容可以查看IP專欄&#xff0c;前一章內容為訪問服務器流程&#xff0c;可通過以下路徑查看IP----訪問服務器流程-CSDN博客&#xff0c;歡迎指正 2.網絡類型 網絡類型---根據二層&#xff08;數據鏈路層&#xff09;所…

【監督學習】ARIMA預測模型步驟及matlab實現

ARIMA預測模型 ARIMA預測模型1.算法步驟2.參數選擇(1)拖尾截尾判斷法(2) AIC 準則(3) BIC 準則 3.MATLAB 實現參考資料 ARIMA預測模型 #mermaid-svg-mDhjwpnuA0YcEGnE {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…

使用git管理uniapp項目

1.本地管理 1. 在項目根目錄中新建 .gitignore 忽略文件&#xff0c;并配置如下&#xff1a; # 忽略 node_modules 目錄 /node_modules /unpackage/dist 2. 打開終端&#xff0c;切換到項目根目錄中&#xff0c;運行如下的命令&#xff0c;初始化本地 Git 倉庫&#xff1…

Unity中動態切換光照貼圖的方法

關鍵代碼&#xff1a;LightmapSettings.lightmaps lightmapDatas; LightmapData中操作三張圖&#xff1a;lightmapColor,lightmapDir,以及一張ShadowMap 這里只操作前兩張&#xff1a; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI;public cl…

C# 運算符

C# 運算符 在C#編程語言中,運算符是用于執行數學或邏輯運算的符號。它們是構建程序邏輯和表達式的基石。C#支持多種類型的運算符,包括算術運算符、關系運算符、邏輯運算符、位運算符、賦值運算符、自增自減運算符以及一些特殊運算符。 算術運算符 算術運算符用于執行基本的…

1.2 Kaggle大白話:Eedi競賽Transformer框架解決方案02-GPT_4o生成訓練集缺失數據

目錄 0. 本欄目競賽匯總表1. 本文主旨2. AI工程架構3. 數據預處理模塊3.1 配置數據路徑和處理參數3.2 配置API參數3.3 配置輸出路徑 4. AI并行處理模塊4.1 定義LLM客戶端類4.2 定義數據處理函數4.3 定義JSON保存函數4.4 定義數據分片函數4.5 定義分片處理函數4.5 定義文件名排序…

pycharm遠程連接服務器運行pytorch

Linux部署pytorch 背景介紹 不同的開源代碼可能需要不同的實驗環境和版本&#xff0c;這時候的確體現出Anaconda管理環境的好處了&#xff0c;分別搞一個獨立環境方便管理。 有的教程建議選擇較舊的版本&#xff0c;但筆者建議在條件允許的情況下安裝最新版&#xff0c;本次…

Python開發 Flask框架面試題及參考答案

目錄 Flask 的核心設計理念是什么?與 Django 相比有哪些顯著差異? 解釋 Flask 框架的核心理念及其作為 “微框架” 的優缺點 Flask 的依賴庫有哪些?簡述 Werkzeug 和 Jinja2 的作用 什么是 WSGI?Flask 如何基于 WSGI 實現服務端與應用的交互 解釋 RESTful API 的設計原…

從“Switch-case“到“智能模式“:C#模式匹配的終極進化指南

當代碼開始"思考" 你是否厭倦了層層嵌套的if-else地獄&#xff1f;是否想過讓代碼像偵探推理一樣優雅地解構數據&#xff1f;C#的模式匹配正是這樣一把瑞士軍刀&#xff0c;從C# 7.0到C# 12&#xff0c;它已悄然進化成改變編程范式的利器。 一、模式匹配的三重境界…