JAVA QR code drawing, you can define the background image and the position of the background image, and the code point drawing avoids 10 pixels in the logo area

Rendering:

Background image:

Look directly at the code and code description:

The method drawQr() is the core of drawing and only draws the QR code on the picture.

The method createQr() includes reading the background image and calling drawQr() . Draw a complete QR code with background image

drawQr() method parameter description:

     * @param content QR code content
     * @param qrSize QR code size
     * @param logoBarry QR code logo byte stream
     * @param qrMaDianColor QR code point color
     * @param qrBgColor QR code background color
     * @param bgImg The background image that wraps the QR code
     * @param qrInBgImgSize The percentage of the size inside the background image that the QR code occupies, between 1-10
     * @param qrInBgImgX The X coordinate of the position of the QR code inside the background image
     * @param qrInBgImgY The Y coordinate of the position of the QR code inside the background image

QR code drawing ensures that the logo is positioned in the center of the QR code, and the size only occupies 20% of the QR code.

The code points are drawn to avoid the 10 pixels in the logo area. It can ensure the beauty of the QR code in the middle

ErrorCorrectionLevel.M is the error level and can be modified by yourself.

The code point shape drawing of the QR code, please stay tuned...

After the code point drawing is developed, it is guaranteed to be free and open source

import cn.hutool.core.img.ImgUtil;
import cn.hutool.core.io.FileUtil;
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 lombok.extern.log4j.Log4j2;

import javax.imageio.ImageIO;
import javax.imageio.ImageWriter;
import javax.imageio.stream.FileImageOutputStream;
import java.awt.*;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * <p>
 * 二维码生成工具
 * </p>
 *
 * @author Garcia
 * @since 2023-05-31
 */
@Log4j2
public class QrCodeUtil {

    /**
     * 使用示例
     */
    private static void useExample() throws IOException {
        BufferedImage schoolLogo = ImgUtil.read(FileUtil.file("C:\\Users\\Garcia\\Desktop\\test\\234.png"));
        ByteArrayOutputStream baos = new ByteArrayOutputStream(); // 创建字节输出流
        DataOutputStream dos = new DataOutputStream(baos); // 创建数据输出流,并关联到字节输出流上
        ImageIO.write(schoolLogo, "png", dos);
        byte[] logo = baos.toByteArray();
        byte[] bytes = QrCodeUtil.generateQr("www.baidu.com",logo);
        QrCodeUtil.generateQrPng("www.baidu.com",logo,"C:\\Users\\Garcia\\Desktop\\test\\qq.png");
    }

    /**
     * 直接生成png到指定路径
     * @param content
     * @param logo
     * @param outPath
     */
    public static void generateQrPng(String content, byte[] logo,String outPath){
        try {
            BufferedImage image = createQr(content,logo);
            Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName("png");
            ImageWriter writer = writers.next();
            ImgUtil.write(image,writer,new FileImageOutputStream(new File(outPath)),1);
        } catch (Exception e) {
            log.error("创建二维码异常",e);
        }
    }

    /**
     * 返回流字节
     * @param content
     * @param logo
     * @return
     */
    public static byte[] generateQr(String content, byte[] logo){
        try {
            Image image = createQr(content,logo);
            return ImgUtil.toBytes(image,"PNG");
        } catch (Exception e) {
            log.error("创建二维码异常",e);
        }
        return null;
    }

    private static BufferedImage createQr(String content,byte[] logo) throws Exception {
	    //读取背景图
        BufferedImage bgImg = ImgUtil.read(FileUtil.file("C:\\Users\\Garcia\\Desktop\\test\\bg.png"));
        BufferedImage originalImage = drawQr(content,
                1000,
                logo,
                Color.white,
                new Color(0,105,183),
                bgImg,5,-1,213);
        return originalImage;
    }

    /**
     * 二维码绘制
     * @param content
     * @param qrSize
     * @param logoBarry
     * @param qrMaDianColor
     * @param qrBgColor
     * @param bgImg
     * @param qrInBgImgSize
     * @param qrInBgImgX
     * @param qrInBgImgY
     * @return
     * @throws Exception
     */
    private static BufferedImage drawQr(String content,
                                        int qrSize ,
                                        byte[] logoBarry,
                                        Color qrMaDianColor,
                                        Color qrBgColor,
                                        BufferedImage bgImg,
                                        int qrInBgImgSize,
                                        int qrInBgImgX,
                                        int qrInBgImgY) throws Exception {
        int logoRadius = 10;
        float cornerRadius = 50.525f;
        int prohibitArea = 15;
        Map<EncodeHintType, Object> hints = new HashMap<>();
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
        hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
        hints.put(EncodeHintType.MARGIN, 1); //二维码边界距离
        BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, qrSize, qrSize, hints);
        int matrixWidth = bitMatrix.getWidth();
        int matrixHeight = bitMatrix.getHeight();
        BufferedImage image = new BufferedImage(matrixWidth, matrixHeight, BufferedImage.TYPE_INT_ARGB);
        if (logoBarry!=null&&logoBarry.length>0){
            BufferedImage logo = ImageIO.read(new ByteArrayInputStream(logoBarry));
            BufferedImage borderImage = new BufferedImage(logo.getWidth(), logo.getHeight(), BufferedImage.TYPE_INT_ARGB);
            Graphics2D g2dff1 = borderImage.createGraphics();
            g2dff1.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2dff1.setColor(Color.WHITE);
            g2dff1.fill(new RoundRectangle2D.Float(0, 0, logo.getWidth(), logo.getHeight(), logoRadius * 2, logoRadius * 2));
            g2dff1.setComposite(AlphaComposite.SrcIn);
            g2dff1.drawImage(logo, 0, 0, null);
            g2dff1.dispose();

            //计算放置logo到二维码中的大小
            int widthLogo = image.getWidth()*2/10;
            int heightLogo = image.getHeight()*2/10;

            //计算放置logo到二维码中的位置
            int leftX = (qrSize - widthLogo) / 2;
            int leftY = (qrSize - heightLogo) / 2;

            //logo右下角坐标
            int rightX = leftX + widthLogo;
            int rightY = leftY + heightLogo;

            for (int mx = 0; mx < matrixWidth; mx++) {
                for (int my = 0; my < matrixHeight; my++) {
                    //logo区域禁止画码点
                    if (mx>=leftX-prohibitArea&&mx<=rightX+prohibitArea&&my>=leftY-prohibitArea&&my<=rightY+prohibitArea){
                        image.setRGB(mx, my, qrBgColor.getRGB());
                        continue;
                    }
                    if (!bitMatrix.get(mx, my)){
                        image.setRGB(mx, my, qrBgColor.getRGB());
                        continue;
                    }
                    //码点样式,有机会再修改
                    image.setRGB(mx, my, qrMaDianColor.getRGB());
                }
            }

            //放置logo到二维码
            Graphics2D graph = image.createGraphics();
            graph.drawImage(borderImage, leftX, leftY, widthLogo, heightLogo, null); //将 Logo 插入到二维码中间
            graph.dispose();
        }else {
            for (int mx = 0; mx < matrixWidth; mx++) {
                for (int my = 0; my < matrixHeight; my++) {
                    image.setRGB(mx, my, bitMatrix.get(mx, my)?qrMaDianColor.getRGB():qrBgColor.getRGB());
                }
            }
        }

        //将二维码绘制为圆角矩形
        BufferedImage roundedCornerQRCode = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2dff = roundedCornerQRCode.createGraphics();
        g2dff.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2dff.setColor(Color.white);
        g2dff.fill(new RoundRectangle2D.Float(0, 0, image.getWidth(), image.getHeight(), cornerRadius * 2, cornerRadius * 2));
        g2dff.setComposite(AlphaComposite.SrcIn);
        g2dff.drawImage(image, 0, 0, null);
        g2dff.dispose();

        //背景
        int emw = Math.min(roundedCornerQRCode.getWidth(null), bgImg.getWidth() * qrInBgImgSize / 10),
                emh = roundedCornerQRCode.getHeight(null)>bgImg.getWidth()*qrInBgImgSize/10?(bgImg.getWidth()*qrInBgImgSize/10):roundedCornerQRCode.getWidth(null);

        int X=qrInBgImgX,Y=qrInBgImgY;
        if (qrInBgImgY==-1){
            //计算放置二维码到背景中的位置
            Y = ( bgImg.getHeight() - emh) / 2;
        }
        if (qrInBgImgX==-1){
            //计算放置二维码到背景中的位置
            X = ( bgImg.getWidth() - emw) / 2;
        }
        Graphics2D bg2d = bgImg.createGraphics();
        bg2d.drawImage(roundedCornerQRCode, X, Y, emw, emh, null);
        bg2d.dispose();
        return bgImg;
    }

}

Guess you like

Origin blog.csdn.net/Qensq/article/details/131434272
Recommended