# 二维码生成器 **Repository Path**: JKcoding/qr-code-generator ## Basic Information - **Project Name**: 二维码生成器 - **Description**: No description available - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2024-10-06 - **Last Updated**: 2024-10-06 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 最终效果 ![image-20241006232858856](assets/image-20241006232858856.png) # 软件版本 IntelliJ IDEA:2023.2 JDK:17 Tomcat:10.1.11 Maven:3.9.3 # 技术栈 - servlet - 谷歌的:zxing - 生成普通的黑白二维码 - 在二维码中间添加一个小图标 - github开源项目:qrcode - qrcode开源项目的内部是基于zxing实现的,可以让二维码更加酷炫 # 环境搭建 ## 创建Empty Project ![image.png](assets/1690689376749-ecfff645-2b28-4582-94b7-bdadb542b33e.png) ![image.png](assets/1690689408213-b9e459cc-97d8-49d7-ba33-e3202e49908f.png) ![image.png](assets/1690689456171-ad7bb8ef-15dc-409f-b31d-6c05504c7b2f.png) ## 设置SDK ![image.png](assets/1690689498356-a7f049dd-af26-483c-a8ea-d1d8f1513e00.png) ![image.png](assets/1690689526793-dffa9740-1beb-4d7d-9f0a-cffa9042872e.png) ## 设置Maven ![image.png](assets/1690689584553-39c33258-11bf-4bf3-8307-b7007718277b.png) ![image.png](assets/1690689648751-41cc4091-18cc-4aff-861d-90a3c4179980.png) 注意:自己安装的maven中settings配置文件中已经配置了本地仓库的位置: ![image.png](assets/1690689875108-e2aaf1d2-a01c-47b7-91a4-a77a535c3556.png) ![image.png](assets/1690689897425-6c27cf51-90f6-485c-9b3e-b48a280558ae.png) ## 创建module ![image.png](assets/1690690027388-bb604145-9b94-4b94-bffa-db047dae53b9.png) ![image.png](assets/1690690077832-975161e0-c166-4e4d-b18f-b9a1c3e71791.png) ## 添加web支持 选中qrcode模块,如图: ![image.png](assets/1690694648706-e71c42b5-1a80-4009-9b76-8dff9a302dd6.png) 添加框架支持: ![image.png](assets/1690694674968-b79baa9c-0e7f-48f5-8b42-f1677f247fa0.png) 注意:如果File菜单中没有上图的“Add Framework Support...”怎么办? ![image.png](assets/1690696370231-9d04f9b5-ac1f-4abb-9a8c-6eabe7531254.png) ![image.png](assets/1690696404018-9cfa7a75-9058-4658-a378-f46eb4196447.png) 这样File菜单中就有了。 继续添加框架支持:web4.0,不创建web.xml文件 ![image.png](assets/1690695314264-725d3887-a44b-4487-b78a-514a3cfcec99.png) ## pom.xml文件配置 ```xml 4.0.0 com.powernode qrcode 1.0-SNAPSHOT war jakarta.servlet jakarta.servlet-api 6.0.0 provided 17 17 UTF-8 ``` - 打包方式:war - 引入servlet依赖 ## 确认web的根是否正确(重点) ![image.png](assets/1690695539919-b7f2c401-fa48-4bee-8566-a244be1560c5.png) ## 设置tomcat并部署应用 ![image.png](assets/1690691849750-cc7d014f-5c47-4be2-a5a4-a0fa64d9133a.png) ![image.png](assets/1690691870680-9ca78900-f7b0-442e-8af8-6123b09cdfdf.png) ![image.png](assets/1690691908879-f99843b7-9c81-43d4-99df-f90a7f082a84.png) ![image.png](assets/1690691970290-d903d58d-501b-498a-ae36-403154d801a1.png) ## 启动tomcat并访问 ![image.png](assets/1690692003109-07554f13-b458-41fe-a88e-c98d85aa2a1c.png) ![image.png](assets/1690695648145-cbc7e47c-4471-475b-a721-349d090df42e.png) 注意:如果tomcat服务器启动之后控制台有中文乱码,怎么解决?找到tomcat服务器根目录下的config目录,找到logging.properties ![image.png](assets/1690696163641-e6778477-4b23-4d5d-9c84-8782ec5b7cce.png) 修改其中的一段配置为GBK,如下: ![image.png](assets/1690696192883-90bba9f3-b8dd-4e39-9053-1afd2146d0c9.png) # zxing相关依赖 ```xml com.google.zxing core 3.1.0 com.google.zxing javase 3.1.0 commons-lang commons-lang 2.6 ``` # zxing常用API ## EncodeHintType(编码提示类型) EncodeHintType是用来设置二维码编码时的一些额外参数的枚举类型,常用枚举值如下: - `ERROR_CORRECTION`: - 误差校正级别。对于黑白二维码,可选值为`L`(7%)、`M`(15%)、`Q`(25%)、`H`(30%),表示二维码允许破损的最大容错率。在二维码出现破损时,根据设置的容错率级别,可以尝试修复二维码中的一些数据。 - 二维码在生成过程中,可能会出现一些损坏或者缺失的情况,例如打印时墨水耗尽、图像压缩、摄像头拍摄角度不对等。这些问题可能导致二维码无法完全识别,或者识别出来的数据不准确,而误差校正码就是为了解决这些问题而产生的。 - 例如,选择L级别的容错率,相当于允许在二维码的整体颜色区域中,最多可有约7%的坏像素点;而选择H级别的容错率时,最多可有约30%的坏像素点。 - **注意:误差校正级别的具体值需要通过ErrorCorrectionLevel的枚举值来获取。** - `CHARACTER_SET`: - 编码字符集。可以设置使用的字符编码,例如utf-8、gb2312等等。 - `MARGIN`: - 二维码的空白区域大小。可以设置二维码周围的留白大小,以便于在不同的嵌入场景中使用二维码。 ## MultiFormatWriter(多格式写入程序) `MultiFormatWriter`是一个便捷的二维码生成类,可以根据传入的`BarcodeFormat`参数,生成对应类型的二维码。 `MultiFormatWriter`封装了一系列的二维码生成方法,可以生成多种格式的二维码,包括QR Code、Aztec Code、PDF417、Data Matrix等。 ## BarcodeFormat(码格式) BarcodeFormat是枚举类,通过它来制定二维码格式: - QR Code :QR Code是最常见的二维码格式之一,广泛应用于商品包装、票务、扫码支付等领域。QR Code矩阵有黑白两种颜色,其中黑色部分表示信息的编码,白色部分则用于衬托和辨识。 - Aztec Code:Aztec Code是一种高密度、可靠性很高的二维码格式。相比于其他二维码格式,它具有更低的容错率、更小的尺寸和更高的解码效率。因此,它适合用于储存一些核心信息,例如个人信息、证件信息、账户密码等。 - PDF417:是一种可以储存大量信息的二维码格式,它具有数据密度高、可靠性强等优点,可以应用于许多场景,例如航空机票,运输和配送标签,法律文件等。 - Data Matrix:是一种小巧的二维码格式,它的编码方式类似于QR Code,但是其可靠性、识别率、扫描速度和牢固度都比QR Code更优秀。由于尺寸较小、可靠性较高,因此Data Matrix适合嵌入简单的产品标签、医疗图像、检测数据等领域。 ## BitMatrix(位矩阵) `BitMatrix`是ZXing库中表示二维码矩阵的数据结构,它是由0和1构成的二维数组,用于存储二维码的编码信息。在二维码生成过程中,我们通过对`BitMatrix`对象的构建和操作,最终生成一个可被扫描解码的二维码图像。 `BitMatrix`实际上是一个**紧凑型的布尔型二维数组**,往往只需要占用一个字节即可表示8位二进制。在使用`BitMatrix`时,我们可以通过其不同的方法,例如`get()`、`set()`等,来获取、设置矩阵中每个位置的值。 在ZXing中,`BitMatrix`常用于将编码后的信息转化为矩阵形式,并进行图像的生成和输出。在使用ZXing生成二维码时,我们首先需要使用`MultiFormatWriter.encode()`方法来生成一个`BitMatrix`;然后,在对`BitMatrix`进行各种处理和操作后,就可以在UI中显示和输出二维码。 总的来说,`BitMatrix`是ZXing库中非常重要的数据结构之一,它负责存储和处理生成二维码图像所需的二进制信息,是实现二维码生成功能的关键。 BitMatrix常用API: - getHeight():获取矩阵高度 - getWidth():获取矩阵宽度 - get(x, y):根据x,y的坐标获取矩阵中该坐标的值。结果是true(黑色)或者false(白色)。 # 生成普通黑白二维码 前端代码: ```html 生成普通黑白二维码 url:
``` 后端代码: ```java package com.powernode.servlets; import com.google.zxing.BarcodeFormat; import com.google.zxing.EncodeHintType; import com.google.zxing.MultiFormatWriter; import com.google.zxing.common.BitMatrix; import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; import jakarta.servlet.ServletException; import jakarta.servlet.ServletOutputStream; import jakarta.servlet.annotation.WebServlet; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import javax.imageio.ImageIO; import java.awt.image.BufferedImage; import java.io.IOException; import java.util.HashMap; import java.util.Map; @WebServlet("/create") public class CreateQrcodeServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req, resp); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { // 准备一个Map集合,用来存储二维码图片的相关属性 Map map = new HashMap(); // 设置误差校验级别 map.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); // 设置字符编码(因为文本内容要转换成二维码,需要指定转换时采用的字符集) map.put(EncodeHintType.CHARACTER_SET, "utf-8"); // 设置二维码的外边距 map.put(EncodeHintType.MARGIN, 1); // 获取要生成二维码的文本内容 String url = request.getParameter("url"); // 创建MultiFormatWriter对象 MultiFormatWriter writer = new MultiFormatWriter(); // 传入:内容、码的格式、宽度、高度、二维码参数。返回位矩阵对象。 BitMatrix bitMatrix = writer.encode(url, BarcodeFormat.QR_CODE, 300, 300, map); // 获取位矩阵的宽度和高度 int width = bitMatrix.getWidth(); int height = bitMatrix.getHeight(); // 创建BufferedImage对象 BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); // 遍历位矩阵 for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { // 0xFF000000 黑色 // 0xFFFFFFFF 白色 image.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF); } } // 响应 ServletOutputStream out = response.getOutputStream(); ImageIO.write(image, "png", out); out.flush(); out.close(); } catch(Exception e){ e.printStackTrace(); } } } ``` 运行效果: ![image.png](assets/1690702266044-c20dbbfc-27d0-4f48-b589-b4b335071a81.png) # 生成一个带logo的黑白二维码 ```html <%@page contentType="text/html;charset=UTF-8" pageEncoding="UTF-8" %> 生成带有logo的黑白二维码
请输入文本内容:
请选择图片:
``` ```java package com.powernode.qrcode.servlets; import com.google.zxing.BarcodeFormat; import com.google.zxing.EncodeHintType; import com.google.zxing.MultiFormatWriter; import com.google.zxing.common.BitMatrix; import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; import jakarta.servlet.ServletException; import jakarta.servlet.annotation.MultipartConfig; import jakarta.servlet.annotation.WebServlet; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.Part; import javax.imageio.ImageIO; import java.awt.*; import java.awt.geom.RoundRectangle2D; import java.awt.image.BufferedImage; import java.io.IOException; import java.io.InputStream; import java.util.HashMap; import java.util.Map; @WebServlet("/generateWithLogo") @MultipartConfig(fileSizeThreshold = 1024 * 1024 * 2, maxFileSize = 1024 * 1024 * 10, maxRequestSize = 1024 * 1024 * 100) public class GenerateQrCodeWithLogo extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { // 准备一个Map集合,用来存放二维码的属性 Map map = new HashMap(); map.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); map.put(EncodeHintType.CHARACTER_SET, "UTF-8"); map.put(EncodeHintType.MARGIN, 1); // 获取文本内容 String url = request.getParameter("url"); // 创建zxing核心对象 MultiFormatWriter writer = new MultiFormatWriter(); BitMatrix bitMatrix = writer.encode(url, BarcodeFormat.QR_CODE, 300, 300, map); int width = bitMatrix.getWidth(); int height = bitMatrix.getHeight(); // 生成二维码 BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { bufferedImage.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF); } } // 给二维码添加logo // 第一部分:将logo缩放。 // 获取上传的logo Part对象 Part logo = request.getPart("logo"); // 通过Part对象获取输入流 InputStream inputStream = logo.getInputStream(); // 通过ImageIO的read方法,从输入流中读取,从而获得logo图片 Image logoImage = ImageIO.read(inputStream); // 获取logo图片的宽度 int logoWidth = logoImage.getWidth(null); // 获取logo图片的高度 int logoHeight = logoImage.getHeight(null); // 如果logo的宽度或者高度大于100,则重新赋值100 if (logoWidth > 60) { logoWidth = 60; } if (logoHeight > 60) { logoHeight = 60; } // 使用平滑缩放算法对原logo图像进行缩放得到一个全新的图像。 Image scaledLogo = logoImage.getScaledInstance(logoWidth, logoHeight, Image.SCALE_SMOOTH); // 第二部分:将缩放后的logo画到黑白二维码上 // 获取2D画笔 Graphics2D graphics2D = bufferedImage.createGraphics(); // 开始画的x和y坐标 int x = (300 - logoWidth) / 2; int y = (300 - logoHeight) / 2; // 将缩放后的logo画上去 graphics2D.drawImage(scaledLogo, x, y, null); // 创建一个具有指定位置、宽度、高度和圆角半径的圆角矩形。这个圆角矩形是用来绘制边框的。 Shape shape = new RoundRectangle2D.Float(x, y, logoWidth, logoHeight, 10, 10); // 使用一个宽度为4像素的基本笔触 graphics2D.setStroke(new BasicStroke(4f)); // 给logo画圆角矩形 graphics2D.draw(shape); // 释放画笔 graphics2D.dispose(); // 响应 ImageIO.write(bufferedImage, "png", response.getOutputStream()); } catch (Exception e) { e.printStackTrace(); } } } ``` 运行效果: ![image.png](assets/1691319830505-31d5e59e-6a18-459d-92fb-b1ba1882a220.png) ![image.png](assets/1691319843412-ed88e888-66a6-478b-b260-e4b9c8194098.png) # 使用github开源项目qrcode ```xml com.github.liuyueyi.media qrcode-plugin 2.5.2 ``` ## 生成黑白二维码 ```java String url = request.getParameter("url"); BufferedImage image = QrCodeGenWrapper.of(url).asBufferedImage(); ImageIO.write(image, "png", response.getOutputStream()); ``` ## 生成带有logo的二维码 ```java String url = request.getParameter("url"); BufferedImage image = QrCodeGenWrapper.of(url) .setLogo(request.getPart("logo").getInputStream()) .setLogoRate(7) // 设置 logo 图片与二维码之间的比例。在这个例子中,它设置为 7,表示 logo 的宽度等于二维码的 1/7。 .setLogoStyle(QrCodeOptions.LogoStyle.ROUND) // 设置 logo 图片的样式。设置为 ROUND,表示将 logo 的边框形状设置为圆形。 .asBufferedImage(); ImageIO.write(image, "png", response.getOutputStream()); ``` ## 生成彩色二维码 ```java String url = request.getParameter("url"); BufferedImage image = QrCodeGenWrapper.of(url) .setDrawPreColor(Color.BLUE) .asBufferedImage(); ImageIO.write(image, "png", response.getOutputStream()); ``` ## 生成背景图二维码 ```java String url = request.getParameter("url"); BufferedImage image = QrCodeGenWrapper.of(url) .setBgImg(request.getPart("logo").getInputStream()) .setBgOpacity(0.7F) .asBufferedImage(); ImageIO.write(image, "png", response.getOutputStream()); ``` ## 特殊形状二维码 ```java String url = request.getParameter("url"); BufferedImage image = QrCodeGenWrapper.of(url) .setDrawEnableScale(true) // 启用二维码绘制时的缩放功能 .setDrawStyle(QrCodeOptions.DrawStyle.DIAMOND) // 指定绘制样式 .asBufferedImage(); ImageIO.write(image, "png", response.getOutputStream()); ``` ## 图片填充二维码 ```java String url = request.getParameter("url"); BufferedImage image = QrCodeGenWrapper.of(url) .setErrorCorrection(ErrorCorrectionLevel.H) // 设置二维码的错误纠正级别 .setDrawStyle(QrCodeOptions.DrawStyle.IMAGE) // 绘制样式采用图片填充 .addImg(1, 1, request.getPart("logo").getInputStream()) // 添加图片 .asBufferedImage(); ImageIO.write(image, "png", response.getOutputStream()); ``` ## 生成gif动图二维码 ```java String url = request.getParameter("url"); BufferedImage image = QrCodeGenWrapper.of(url) .setW(500) .setH(500) .setBgImg(request.getPart("logo").getInputStream()) .setBgOpacity(0.6f) .setPicType("gif") .asBufferedImage(); ImageIO.write(image, "gif", response.getOutputStream()); ```