文章目錄
- 引言
- 二維碼基本原理
- 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的基本概念。這個工具類可以廣泛應用于各種需要生成二維碼的場景,提升用戶體驗和品牌識別度。