JAVA 二维码绘制,可定义背景图与在背景图种的位置,码点绘制避开logo区域10个像素点

效果图:

背景图:

直接看代码和代码说明:

方法drawQr() 为绘制核心仅绘制出图上的二维码

方法createQr() 包含 读取背景图和 调用drawQr()绘制出完整的带有背景图的二维码

drawQr()方法参数说明:

     * @param content                            二维码内容
     * @param qrSize                              二维码大小
     * @param logoBarry                         二维码logo字节流
     * @param qrMaDianColor                二维码码点颜色
     * @param qrBgColor                        二维码背景颜色
     * @param bgImg                              包裹二维码的背景图
     * @param qrInBgImgSize                二维码占用背景图内部的大小的百分之多少,1-10之间
     * @param qrInBgImgX                     二维码在背景图内部的位置X坐标
     * @param qrInBgImgY                     二维码在背景图内部的位置Y坐标

二维码绘制保证了logo在二维码中心的位置,且大小仅是占用二维码的20%

码点的绘制避开了logo区域的10个像素点。可以保证二维码在中间的美观性

ErrorCorrectionLevel.M 是错误等级,可自行修改。

二维码的码点形状绘制,敬请期待...

码点绘制开发好后保证全部免费开源

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;
    }

}

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Qensq

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值