营销级二维码生成术:Java如何打造专属标识

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

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 码、需要轻量集成的场景

看了这两款的开源二维码技术,你更喜欢那一种呢?

相关推荐
字节跳动数据库12 分钟前
文章分享——相似函数处理方法
人工智能·后端·程序员
云技纵横12 分钟前
@Transactional 失效的 7 种场景:第 5 种最难排查
后端
用户67570498850230 分钟前
你知道 Go 结构体和结构体指针调用的区别吗?一文带你彻底搞懂!
后端·go
程序员cxuan1 小时前
读懂 Claude Code 架构分析系列,第一篇,开始!
人工智能·后端·架构
用户6757049885021 小时前
面试官问“装饰器模式”,这样回答薪资多要 3000!
后端
tntxia1 小时前
Geo Scene域名修改引起的一些问题
后端
用户298698530141 小时前
Java 实现 Word 文档加密与权限解除
java·后端
AskHarries1 小时前
多 Agent 与任务队列:什么时候需要拆分任务
程序员
vanuan1 小时前
给你的A2A-Agent加把锁-认证鉴权实战指南
后端
Yeats_Liao1 小时前
14:Servlet中的页面跳转-Java Web
java·后端·架构