当前位置: 首页 > article >正文

后端绘制二维码图片(支持带Logo)

需要的依赖

<!-- 生成二维码 -->
<dependency>
    <groupId>com.google.zxing</groupId>
    <artifactId>core</artifactId>
    <version>3.4.1</version>
</dependency>
import com.github.binarywang.utils.qrcode.MatrixToImageWriter;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import sun.misc.BASE64Encoder;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URL;
import java.util.Base64;
import java.util.HashMap;

@Slf4j
@Component
public class QRCodeGenerator {

    private static final int QRCODE_SIZE = 500; // 二维码尺寸
    private static final int QRCODE_LOGO_SIZE = 100; // 二维码插入的LOGO尺寸
    private static final String FORMAT_TYPE = "png"; // 二维码图片类型

    public String generateQRCodeImage(String text) throws WriterException, IOException {
        QRCodeWriter qrCodeWriter = new QRCodeWriter();
        BitMatrix bitMatrix = qrCodeWriter.encode(text, BarcodeFormat.QR_CODE, 500, 500);

        ByteArrayOutputStream pngOutputStream = new ByteArrayOutputStream();
        MatrixToImageWriter.writeToStream(bitMatrix, "PNG", pngOutputStream);
        byte[] pngData = pngOutputStream.toByteArray();

        String base64Encoded = Base64.getEncoder().encodeToString(pngData);

        return base64Encoded;
    }

    /**
     * 根据文本生成带Logo的二维码
     * @param text 二维码内容
     * @return 二维码 base64编码
     */
    public String generateLogoQRCode(String text, String logoUrl) throws Exception {
        QRCodeWriter qrCodeWriter = new QRCodeWriter();
        HashMap<EncodeHintType, Object> hints = new HashMap<>();
        hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
        // 定义纠错等级,中间插入了Logo,不设置纠错等级会让二维码扫不出来
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L);
        hints.put(EncodeHintType.MARGIN, 1);
        BitMatrix bitMatrix = qrCodeWriter.encode(text, BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE, hints);
        BufferedImage image = new BufferedImage(QRCODE_SIZE, QRCODE_SIZE, BufferedImage.TYPE_INT_RGB);
        for (int x = 0; x < QRCODE_SIZE; x++) {
            for (int y = 0; y < QRCODE_SIZE; y++) {
                image.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);
            }
        }
        // 给图片插入Logo
        insertLogoImage(image, logoUrl);
        return bufferedImageToBase64(image);
    }

    /**
     * 插入logo图片
     *
     * @param source 二维码图片
     */
    private static void insertLogoImage(BufferedImage source, String logoUrl) throws Exception {
        // 绘制缩小后的图,得到插入的Logo图片
        Image logo = drawImage(logoUrl);

        // 插入LOGO
        Graphics2D graph = source.createGraphics();
        // 计算插入LOGO的坐标位置,相对图片左上角(0, 0)
        int x = (QRCODE_SIZE - QRCODE_LOGO_SIZE) / 2;
        int y = (QRCODE_SIZE - QRCODE_LOGO_SIZE) / 2;
        graph.drawImage(logo, x, y, QRCODE_LOGO_SIZE, QRCODE_LOGO_SIZE, null);
        Shape shape = new RoundRectangle2D.Float(x, y, QRCODE_LOGO_SIZE, QRCODE_LOGO_SIZE, 6, 6);
        graph.setStroke(new BasicStroke(3f));
        graph.draw(shape);
        graph.dispose();
    }

    private static Image drawImage(String logoUrl) throws IOException {
        Image src = ImageIO.read(new URL(logoUrl));
        Image image = src.getScaledInstance(QRCODE_LOGO_SIZE, QRCODE_LOGO_SIZE, Image.SCALE_SMOOTH);
        BufferedImage tag = new BufferedImage(QRCODE_LOGO_SIZE, QRCODE_LOGO_SIZE, BufferedImage.TYPE_INT_RGB);
        Graphics g = tag.getGraphics();
        g.drawImage(image, 0, 0, null);
        g.dispose();
        return image;
    }

    /**
     * BufferedImage 编码转换为 base64
     * @param bufferedImage 图片对象
     * @return base64格式编码
     */
    private static String bufferedImageToBase64(BufferedImage bufferedImage) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();//io流
        try {
            ImageIO.write(bufferedImage, FORMAT_TYPE, baos);//写入流中
        } catch (IOException e) {
            e.printStackTrace();
        }
        byte[] bytes = baos.toByteArray();//转换成字节
        BASE64Encoder encoder = new BASE64Encoder();
        String png_base64 = encoder.encodeBuffer(bytes).trim();//转换成base64串
        png_base64 = png_base64.replaceAll("\n", "").replaceAll("\r", "");//删除 \r\n
        log.error("值为:" + "data:image/jpg;base64," + png_base64);
        return png_base64;
    }
}

生成的带logo的二维码示例
在这里插入图片描述


http://www.kler.cn/news/359952.html

相关文章:

  • Android中的内存泄漏及其检测方式
  • 配置Typescript环境
  • git禁用 SSL 证书验证
  • 嵌软面试一百问(持续更新中)
  • 二叉树遍历(前序、中序、后续)
  • OpenCV高级图形用户界面(14)交互式地选择一个或多个感兴趣区域函数selectROIs()的使用
  • 【大模型实战篇】大模型分词算法Unigram及代码示例
  • 【进阶OpenCV】 (11)--DNN板块--实现风格迁移
  • 电动汽车嵌入式软件开发过程中的难题有哪些?
  • JavaGuide(10)
  • commonjs和esmodule的导入导出细节
  • opencv实战项目(三十二):opencv汽车360全景影像制作
  • 【嵌入式软件-STM32】STM32外设
  • 常用数据库获取表,视图,列,索引信息
  • AndroidStudio移动开发:使用Service播放音乐【步骤】
  • 【分布式微服务云原生】《Redis RedLock 算法全解析:应对时钟漂移与网络分区挑战》
  • Python异常检测-3Sigma
  • exchange_proxy exchange 安全代理
  • SqlDbx连接oracle(可用)
  • PDF.js的使用及其跨域问题解决