基于 Java 编程生成二维码图片
0x01 准备
(1)软件版本
- IntelliJ IDEA 2023.1.3
- JDK 18
- Tomcat 10.1.11
- Maven 3.8.6
(2)技术栈
- servlet
- zxing
- 谷歌项目
- 生成黑白二维码并可以附上 logo
- qrcode
- github 开源项目
- 基于并拓展 zxing
(3)创建项目
创建空项目
在 菜单栏-文件-项目结构 中设置 JDK 及语言级别
在 菜单栏-文件-设置-构建-构建工具-Maven 中配置 Maven 路径与用户设置文件 \apache-maven-3.8.6\conf\settings.xml
在项目中创建新模块
在新模块中通过“添加框架支持”添加 Web Application 4.0
- 取消“创建 web.xml ”的选中
- 在项目结构中选择 模块-[模块名称]-Web-Web 资源目录,修改资源目录为项目中 web 的路径,如 [project_name]\[module_name]\web
修改 pom.xml
<!-- 打包方式 -->
<packaging>war</packaging> <!-- 添加依赖 -->
<dependencies>
<!-- https://mvnrepository.com/artifact/jakarta.servlet/jakarta.servlet-api -->
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>6.0.0</version>
<scope>provided</scope>
</dependency>
<!-- zxing 依赖 -->
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.1.0</version>
</dependency>
<!-- zxing 需要 commons-lang 依赖 -->
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
</dependencies>
在 菜单栏-运行-编辑配置 中配置 Tomcat 服务器
添加新配置,选择 Tomcat 本地服务器
在 部署栏 中选择添加工件,选择 [module_name]:war exploded
修改 应用上下文 为 /[module_name]
修改 Tomcat 目录下 /conf/logging.properties 文件的内容以避免调试日志乱码
java.util.logging.ConsoleHandler.encoding = GBK
0x02 zxing
(1)创建基础二维码图片
在 web/index.jsp 中编辑前端页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>QRCode</title>
</head>
<body>
<p>输入文本:<input type="text" id="url" /><button onclick="generateQRCode()">生成二维码</button></p>
<img id="qrcodeImg" />
<script type="text/javascript">
function generateQRCode() {
document.getElementById("qrcodeImg").src = "/myqrcode/generate?url=" + document.getElementById("url").value
}
</script>
</body>
</html>
新建 src/main/java/com.qrcode.servlets 包并新建 GenerateQRCode.java
package com.qrcode.servlets; public class GenerateQRCode extends HttpServlet {
}
在类中继承 HttpServlet 类并重写
doGet()
方法@WebServlet("/generate")
public class GenerateQRCode extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// super.doGet(req, resp);
}
}
在方法中创建 Map 集合来储存二维码相关属性
Map map = new HashMap();
// 设置二维码的误差校正级别
map.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
// 设置二维码的字符集
map.put(EncodeHintType.CHARACTER_SET, "utf-8");
// 设置二维码四周的留白
map.put(EncodeHintType.MARGIN, 1);
校正级别(二维码中最大坏像素点占比):
L - 7% M - 15% Q - 25% H - 30%
获取文本对象
String url = req.getParameter("url");
创建 zxing 的核心对象
MultiFormatWriter writer = new MultiFormatWriter();
- MultiFormatWriter(多格式写入器)是一个便捷的二维码生成类,可以根据传入的 BarcodeFormat 参数,生成对应的二维码
传入二维码参数并获取宽高
BitMatrix bitMatrix = writer.encode(url, BarcodeFormat.QR_CODE, 300, 300, map);
int height = bitMatrix.getHeight();
int width = bitMatrix.getWidth();
- BarcodeFormat(码格式)是枚举类,用来指定二维码格式
- QR_CODE:最常见二维码格式之一
- AZTEC:高密度高可靠二维码格式
- PDF_417:储存大量信息的二维码格式
- DATA_MATRIX:一种小巧的二维码格/式
- BitMatrix(位矩阵对象)是表示二维码矩阵的数据结构,实际上是一个紧凑型的布尔型二维数组,常用于将编码后的信息转化为矩阵类型,具有以下方法
getHeight()
:获取矩阵高度getWidth()
:获取矩阵宽度get(x, y)
:获取指定位置的坐标值,值为true
(黑色块)或false
(白色块)
- BarcodeFormat(码格式)是枚举类,用来指定二维码格式
生成二维码
// 创建图片对象
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, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);
}
}
将图片返回到浏览器
ServletOutputStream servletOutputStream = resp.getOutputStream();
ImageIO.write(image, "png", servletOutputStream);
servletOutputStream.flush();
servletOutputStream.close();
完整代码:
package com.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.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("/generate")
public class GenerateQRCode extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
try {
String url = req.getParameter("url");
Map map = new HashMap();
map.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
map.put(EncodeHintType.CHARACTER_SET, "utf-8");
map.put(EncodeHintType.MARGIN, 1);
MultiFormatWriter writer = new MultiFormatWriter();
BitMatrix bitMatrix = writer.encode(url, BarcodeFormat.QR_CODE, 300, 300, map);
int height = bitMatrix.getHeight();
int width = bitMatrix.getWidth();
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, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);
}
}
ServletOutputStream servletOutputStream = resp.getOutputStream();
ImageIO.write(image, "png", servletOutputStream);
servletOutputStream.flush();
servletOutputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
(2)带 logo 的二维码生成
修改前端页面 index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>QRCode</title>
</head>
<body>
<form action="/myqrcode/generate" method="post" enctype="multipart/form-data">
输入文本:<input type="text" name="url" /><br />
logo:<input type="file" name="logo" /><br />
<input type="submit" value="生成二维码">
</form>
</body>
</html>
添加文件上传注释
@MultipartConfig(fileSizeThreshold = 1024 * 1024 * 2, maxFileSize = 1024 * 1024 * 10, maxRequestSize = 1024 * 1024 * 100)
在 GenerateQRCode.java 中获取上传的 Logo
Part logoPart = req.getPart("logo");
InputStream inputStream = logoPart.getInputStream();
Image logoImage = ImageIO.read(inputStream);
使用平滑缩放算法进行缩放
int logoWidth = logoImage.getWidth(null);
int logoHeight = logoImage.getHeight(null);
logoWidth = logoWidth > 60 ? 60 : logoWidth;
logoHeight = logoHeight > 60 ? 60 : logoHeight;
Image logoImageScaledInstance = logoImage.getScaledInstance(logoWidth, logoHeight, Image.SCALE_SMOOTH);
获取 2D 画笔
Graphics2D graphics2D = image.createGraphics();
指定开始作画的坐标
int x = (300 - logoWidth) / 2;
int y = (300 - logoHeight) / 2;
绘制 Logo
graphics2D.drawImage(logoImageScaledInstance, x, y, null);
绘制圆角矩形
Shape shape = new RoundRectangle2D.Float(x, y, logoWidth, logoHeight, 10, 10);
graphics2D.setStroke(new BasicStroke(4f));
graphics2D.draw(shape);
释放画笔
graphics2D.dispose();
完整代码:
package com.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("/generate")
@MultipartConfig(fileSizeThreshold = 1024 * 1024 * 2, maxFileSize = 1024 * 1024 * 10, maxRequestSize = 1024 * 1024 * 100)
public class GenerateQRCode extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
try {
String url = req.getParameter("url");
Map map = new HashMap();
map.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
map.put(EncodeHintType.CHARACTER_SET, "utf-8");
map.put(EncodeHintType.MARGIN, 1);
MultiFormatWriter writer = new MultiFormatWriter();
BitMatrix bitMatrix = writer.encode(url, BarcodeFormat.QR_CODE, 300, 300, map);
int height = bitMatrix.getHeight();
int width = bitMatrix.getWidth();
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, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);
}
}
Part logoPart = req.getPart("logo");
InputStream inputStream = logoPart.getInputStream();
Image logoImage = ImageIO.read(inputStream);
int logoWidth = logoImage.getWidth(null);
int logoHeight = logoImage.getHeight(null);
logoWidth = Math.min(logoWidth, 60);
logoHeight = Math.min(logoHeight, 60);
Image logoImageScaledInstance = logoImage.getScaledInstance(logoWidth, logoHeight, Image.SCALE_SMOOTH);
Graphics2D graphics2D = image.createGraphics();
int x = (300 - logoWidth) / 2;
int y = (300 - logoHeight) / 2;
graphics2D.drawImage(logoImageScaledInstance, x, y, null);
Shape shape = new RoundRectangle2D.Float(x, y, logoWidth, logoHeight, 10, 10);
graphics2D.setStroke(new BasicStroke(4f));
graphics2D.draw(shape);
graphics2D.dispose();
ImageIO.write(image, "png", resp.getOutputStream());
} catch (Exception e) {
e.printStackTrace();
}
}
}
0x03 qrcode
在 pom.xml 中添加依赖
<dependency>
<groupId>com.github.liuyueyi.media</groupId>
<artifactId>qrcode-plugin</artifactId>
<version>2.5.2</version>
</dependency>
(1)黑白二维码
package com.qrcode.servlets;
import com.github.hui.quick.plugin.qrcode.wrapper.QrCodeGenWrapper;
import jakarta.servlet.ServletException;
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;
@WebServlet("/generate")
public class GenerateQRCode extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
try {
String url = req.getParameter("url");
BufferedImage image = QrCodeGenWrapper.of(url).asBufferedImage();
ImageIO.write(image, "png", resp.getOutputStream());
} catch (Exception e) {
e.printStackTrace();
}
}
}
of()
:设置二维码内容asBufferedImage()
:生成二维码图片
(2)logo 二维码
package com.qrcode.servlets;
import com.github.hui.quick.plugin.qrcode.wrapper.QrCodeGenWrapper;
import com.github.hui.quick.plugin.qrcode.wrapper.QrCodeOptions;
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 javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.IOException;
@WebServlet("/generate")
@MultipartConfig(fileSizeThreshold = 1024 * 1024 * 2, maxFileSize = 1024 * 1024 * 10, maxRequestSize = 1024 * 1024 * 100)
public class GenerateQRCode extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
try {
String url = req.getParameter("url");
BufferedImage image = QrCodeGenWrapper.of(url)
.setLogo(req.getPart("logo").getInputStream())
.setLogoRate(7)
.setLogoStyle(QrCodeOptions.LogoStyle.ROUND)
.asBufferedImage();
ImageIO.write(image, "png", resp.getOutputStream());
} catch (Exception e) {
e.printStackTrace();
}
}
}
setLogo()
:设置 Logo 文件setLogoRate(x)
:设置 Logo 缩放比,logo 宽高占二维码宽高的 x 分之一setLogoStyle()
:设置 Logo 样式
(3)彩色二维码
BufferedImage image = QrCodeGenWrapper.of(url)
.setDrawPreColor(Color.BLUE)
.asBufferedImage();
setDrawPreColor()
:设置前景色
(4)背景图二维码
BufferedImage image = QrCodeGenWrapper.of(url)
.setBgImg(req.getPart("logo").getInputStream())
.setBgOpacity(0.7F)
.asBufferedImage();
setBgImg()
:设置背景图setBgOpacity()
:设置背景图透明度
(5)特殊形状二维码
BufferedImage image = QrCodeGenWrapper.of(url)
.setDrawEnableScale(true)
.setDrawStyle(QrCodeOptions.DrawStyle.DIAMOND)
.asBufferedImage();
setDrawEnableScale(true)
:启用二维码绘制时的缩放功能setDrawStyle()
:设置绘制样式
(6)图片填充二维码
BufferedImage image = QrCodeGenWrapper.of(url)
.setErrorCorrection(ErrorCorrectionLevel.H)
.setDrawStyle(QrCodeOptions.DrawStyle.IMAGE)
.addImg(1, 1, req.getPart("logo").getInputStream())
.asBufferedImage();
setErrorCorrection()
:设置二维码的错误校正级别setDrawStyle()
:绘制二维码时采用图片填充addImg()
:添加图片
-End-
基于 Java 编程生成二维码图片的更多相关文章
- JAVA生成二维码图片代码
首先需要导入 QRCode.jar 包 下载地址看这里 http://pan.baidu.com/s/1o6qRFqM import java.awt.Color;import java.awt. ...
- java生成二维码图片
1.POM文件引入 <dependency> <groupId>com.google.zxing</groupId> <artifactId>core& ...
- JAVA根据URL生成二维码图片、根据路径生成二维码图片
引入jar包 zxing-2.3.0.jar.IKAnalyzer2012_u6.jar 下载地址:https://yvioo.lanzous.com/b00nlbp6h ...
- 在java中生成二维码,并直接输出到jsp页面
在java中生成的二维码不存到磁盘里要直接输出到页面上,这就需要把生成的二维码直接以流的形式输出到页面上,我用的是myeclipse 和 tomcat 它的原理是:在加载页面时,根据img的src(c ...
- 使用python调用zxing库生成二维码图片
(1) 安装Jpype 用python调用jar包须要安装jpype扩展,在Ubuntu上能够直接使用apt-get安装jpype扩展 $ sudo apt-get install pytho ...
- 使用google zxing生成二维码图片
生成二维码工具类: 1 import java.awt.geom.AffineTransform; 2 import java.awt.image.AffineTransformOp; 3 impor ...
- C# 利用QRCode生成二维码图片
网上生成二维码的组件是真多,可是真正好用的,并且生成速度很快的没几个,QRCode就是我在众多中找到的,它的生成速度快.但是网上关于它的使用说明,真的太少了,大都是千篇一律的复制粘贴.这是本要用它做了 ...
- Node.js在指定的图片模板上生成二维码图片并附带底部文字说明
在Node.js中,我们可以通过qr-image包直接在后台生成二维码图片,使用方法很简单: var qr = require('qr-image'); exports.createQRImage = ...
- js 生成二维码图片
1.用纯JavaScript实现的微信二维码图片生成器 QRCode.js是javascript实现二维码(QRCode)制作生成库. QRCode.js有着良好的跨浏览器兼容性(高版本使用HTML5 ...
- 基于ASP.NET生成二维码详细源码
详细链接:https://shop499704308.taobao.com/?spm=a1z38n.10677092.card.11.594c1debsAGeakusing System; using ...
随机推荐
- 导入Excel文件的时候公式为【#Ref!】应该怎么解决?
前言 在我们使用Excel时,经常会遇到一个问题,就是导入Excel时公式显示为[#Ref!]的情况.这通常是因为公式中引用的单元格已被删除或对应的工作表被删除,导致原公式无法识别对应的参数而显示为[ ...
- Android Handler实现子线程与子线程、主线程之间通信
一.子线程向主线程传值: 首选在主线程里创建一个Handler 1 Handler mHandler = new Handler(){ 2 @Override 3 public void handle ...
- Android---Android 开发四大组件
Android 应用程序组件 应用程序组件是一个Android应用程序的基本构建块.这些组件由应用清单文件松耦合的组织.AndroidManifest.xml描述了应用程序的每个组件,以及他们如何交互 ...
- 第142篇:原生js实现响应式原理
好家伙,狠狠地补一下代码量 本篇我们来尝试使用原生js实现vue的响应式 使用原生js,即代表没有v-bind,v-on,也没有v-model,所有语法糖我们都用原生实现 1.给输入框绑个变量 & ...
- 一文学会JDBC实现java和mySQL的数据连接(尚硅谷学习课程代码+笔记+思路总结)
JDBC是指数据库连接技术,用于java连接mySQL等数据库.本文详细介绍了尚硅谷课程中JDBC的学习内容和补充知识. 概述 java语言只提供规范接口,存在于java.sql.javax.sql包 ...
- arch安装xfce4的时候,出现无法设置开机启动的问题
sudo systemctl enable lightdm Failed to enable unit: File /etc/systemd/system/display-manager.serv ...
- Android7.0以上的分享图片文件错误及解决方法
原文地址: Android7.0以上的分享图片文件错误及解决方法 - Stars-One的杂货小窝 在Android7.0以上版本,分享图片文件出现了exposed beyond app throug ...
- URL URI URN
总结如下: 1.简写: URI (uniform resource identifier)统一资源标志符: URL(uniform resource location )统一资源定位符(或统一资源定位 ...
- 自动化瓦力多渠道打包python脚本
自动化瓦力多渠道打包python脚本 目录介绍 1.本库优势亮点 2.使用介绍 3.注意要点 4.效果展示 5.其他介绍 0.首先看看我录制的案例演示 如下所示,这段python代码很简单,工具十分强 ...
- Failed to start component [StandardEngine[Catalina].StandardHost[localhost]] 记录
jar包冲突 解决: <dependency> <groupId>org.springframework.cloud</groupId> <a ...