关注我的公众号:【编程朝花夕拾】,可获取首发内容。

01 引言
二维码技术已经非常成熟了,应用非常广泛,如收付款、交友、旅游等。作为技术人,如此好用的二维码是如何生成的呢?
二维码的生成有很多小工具已经实现的非常好了,如草料二维码、掘金插件的快捷工具等。要集成在项目中的话,这些小工具用起来就没有那么方便了,我们就需要定制属于自家的二维码。
02 二维码
要生成二维码我们需要依赖一些优秀的开源框架,本章将介绍两种:
2.1 ZXing

ZXing
是谷歌开源的一款功能强大、多格式的条形码(1D
)和二维码(2D
)的图像处理库。它的主要强项在于 解码(读取/识别),但也包含基本的编码(生成)功能。
Github地址:github.com/zxing/zxing
2.2 QR-Code-generator

QR-Code-generator
是一款通用的库, 专注于生成 QR Code 二维码的开源库。它的目标是提供简单、轻量级、高效且可移植的 QR 码生成解决方案。代码库非常小巧(核心 C 实现只有两个源文件),编译后体积小,运行时内存占用低,生成速度快。
Github地址:github.com/nayuki/QR-C...
03 ZXing实战
需要的依赖
xml
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.3.3</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.3.3</version>
</dependency>
3.1 普通的二维码
java
@Test
void test01() throws Exception {
String content = "编程朝花夕拾";
int width = 300, height = 300;
// 创建矩阵
BitMatrix matrix = new MultiFormatWriter().encode(
content,
BarcodeFormat.QR_CODE,
width,
height,
// 设置边框和编码
Map.of(EncodeHintType.MARGIN, 1, EncodeHintType.CHARACTER_SET, "utf-8")
);
MatrixToImageWriter.writeToPath(matrix, "PNG", Paths.get("qrcode.png"));
}
结果

3.2 带logo
的二维码
java
@Test
void test02() throws Exception {
// 读取二维码
BufferedImage qrImage = ImageIO.read(new File("qrcode.png"));
Graphics2D graphics = qrImage.createGraphics();
// 读取Logo并缩放
BufferedImage logo = ImageIO.read(new File("src/main/resources/bgimages/logo.png"));
int logoSize = qrImage.getWidth() / 5; // Logo大小为二维码1/5
int x = (qrImage.getWidth() - logoSize) / 2;
int y = (qrImage.getHeight() - logoSize) / 2;
// 绘制Logo
graphics.drawImage(logo, x, y, logoSize, logoSize, null);
graphics.dispose();
// 保存带Logo的二维码
ImageIO.write(qrImage, "PNG", new File("qrcode_logo.png"));
}
结果

3.3 带文案的二维码
java
@Test
void test03() throws Exception {
String text = "测试文案";
// 读取二维码
BufferedImage qrImage = ImageIO.read(new File("qrcode.png"));
int textHeight = 30; // 文字区域高度
// 创建新画布(二维码高度 + 文字区域)
BufferedImage combined = new BufferedImage(
qrImage.getWidth(),
qrImage.getHeight() + textHeight,
BufferedImage.TYPE_INT_RGB
);
Graphics2D g = combined.createGraphics();
g.setBackground(Color.WHITE);
g.clearRect(0, 0, combined.getWidth(), combined.getHeight());
// 绘制二维码
g.drawImage(qrImage, 0, 0, null);
// 绘制文字(居中)
g.setColor(Color.BLACK);
g.setFont(new Font("微软雅黑", Font.PLAIN, 20));
int textWidth = g.getFontMetrics().stringWidth(text);
int textX = (combined.getWidth() - textWidth) / 2;
int textY = qrImage.getHeight() + 25;
g.drawString(text, textX, textY);
g.dispose();
ImageIO.write(combined, "PNG", new File("qrcode_text.png"));
}
结果

3.4 解析二维码
java
@Test
void test04() throws Exception {
BufferedImage image = ImageIO.read(new File("qrcode.png"));
LuminanceSource source = new BufferedImageLuminanceSource(image);
Result result = new MultiFormatReader().decode(new BinaryBitmap(new HybridBinarizer(source)));
System.out.println("解码内容: " + result.getText());
// 解码内容: 编程朝花夕拾
}
3.5 使用技巧
ZXing
提供了丰富的功能,熟练使用需要了解其API
,门槛稍高。尤其需要对Graphics2D
了解,才能绘制准确的二维码。Hutool
这款国产的工具包,为了我们封装了更加方便的API
,无需关心内部实现,之间输入关键参数即可。
需要引入Hutool
的依赖:
xml
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>${latest.version}</version>
</dependency>
案例:
java
@Test
void test03() throws IOException {
QrConfig qrConfig = new QrConfig();
qrConfig.setImg(new File("src/main/resources/bgimages/watermark.png"));
BufferedImage generate = QrCodeUtil.generate("编程朝花夕拾!", qrConfig);
ImageIO.write(generate, "png", new File("qr-code3.png"));
}
结果:

生成一个带logo
的二维码,比ZXing
简单多了。Hutool
对二维码的封装是基于ZXing
的,所以使用时也需要引入ZXing
的依赖。
04 QR-Code-generator实战
QR-Code-generator
没有Maven
依赖,但是有jar
,我们可以通过将jar
导入项目或者上传到自己的私服使用。
java
@Test
void test01() throws IOException {
QrCode qrCode = QrCode.encodeText("编程朝花夕拾", Ecc.LOW);
System.out.println(qrCode.size);
BufferedImage image = toImage(qrCode, 2, 2);
ImageIO.write(image, "png", new File("qr-code.png"));
}
其中toImage
也是官方提供的:

摘录方法:
java
private BufferedImage toImage(QrCode qr, int scale, int border) {
return toImage(qr, scale, border, 0xFFFFFF, 0x000000);
}
private BufferedImage toImage(QrCode qr, int scale, int border, int lightColor, int darkColor) {
Objects.requireNonNull(qr);
if (scale <= 0 || border < 0)
throw new IllegalArgumentException("Value out of range");
if (border > Integer.MAX_VALUE / 2 || qr.size + border * 2L > Integer.MAX_VALUE / scale)
throw new IllegalArgumentException("Scale or border too large");
BufferedImage result = new BufferedImage((qr.size + border * 2) * scale, (qr.size + border * 2) * scale, BufferedImage.TYPE_INT_RGB);
for (int y = 0; y < result.getHeight(); y++) {
for (int x = 0; x < result.getWidth(); x++) {
boolean color = qr.getModule(x / scale - border, y / scale - border);
result.setRGB(x, y, color ? darkColor : lightColor);
}
}
return result;
}
如果需要添加logo
或者文案时,需要和上面的ZXing
的案例,自行添加即可。
结果

05 小结
特性 | ZXing | QR-Code-generator |
---|---|---|
核心功能 | 强大的多格式条码解码 + 基础编码 | 专注高效的 QR Code 生成 |
支持的条码类型 | 极其广泛 (QR, Data Matrix, PDF417, 各种1D码等) | 仅 QR Code 和 Micro QR Code |
解码能力 | 非常强大 (是其核心优势) | 无 (纯生成库) |
生成能力 | 支持多种格式生成,但定制性通常不如专用库 | 优秀 (专注于 QR 生成,轻量高效) |
跨平台/语言支持 | 广泛 (Java 核心 + 多语言/平台端口) | 极佳 (C 核心 + 众多轻量级语言包装器) |
库大小/依赖 | 相对较大 (尤其 Java 核心),可能有较多依赖 | 非常轻量 (核心 C 仅两文件,无依赖) |
资源消耗 | 相对较高 | 非常低 (适合嵌入式/资源受限环境) |
主要优势 | 全能解码,多格式支持,移动端集成成熟 | 轻量,高效,易移植,专注 QR 生成 |
典型应用场景 | 扫码 App、需要识别多种条码的系统 | Web/App/嵌入式中生成 QR 码、需要轻量集成的场景 |
看了这两款的开源二维码技术,你更喜欢那一种呢?