创建二维码并支持自定义logo和颜色

package com.shinedata.util;

import com.google.zxing.*;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.QRCodeWriter;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import com.shinedata.util.wxcard.WxConstant;
import lombok.Data;
import lombok.experimental.Accessors;

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

/**
 * 二维码生成工具
 *
 * @Filename QrCodeUtil.java
 * @Description
 * @Version 1.0
 * @Author lixun
 * @History <li>Author: lixun</li>
 * <li>Date: 2017年3月3日</li>
 * <li>Version: 1.0</li>
 * <li>Content: create</li>
 */
public class QrCodeUtil {

    private static final String CHARSET = "utf-8";
    private static final String FORMAT = "PNG";
    // 二维码尺寸
    private static final int QRCODE_SIZE = 300;
    // LOGO高度
    private static final int CENTER_IMAGE_HEIGHT = 60;
    // LOGO宽度
    private static final int CENTER_IMAGE_WIDTH = 60;

    public static final String IMG_BASE64_PREFIX = "data:image/png;base64,";

    private static Integer j = 2000;

    public static String randomNumber() {

        String str = System.currentTimeMillis() + "";
        str = str.substring(5, 13);

        int a = (int) new Random().nextInt(8);
        str = Integer.parseInt(str) / (a + 1) + "";

        if (str.length() < 8) {
            str = str + (int) new Random().nextInt(10);
        }

        if (j > 3000)
            j = 1000;

        String data = j + str;
        j++;

        return data;
    }

    /**
     * 生成二维码 base64
     *
     * @param content
     * @return
     * @throws Exception
     */
    public static String genBase64Qrcode(String content) throws Exception {
        QRCodeWriter qrCodeWriter = new QRCodeWriter();
        BitMatrix bitMatrix = qrCodeWriter.encode(content,
                BarcodeFormat.QR_CODE, 600, 600);
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        MatrixToImageWriter.writeToStream(bitMatrix, FORMAT, outputStream);
        Base64.Encoder encoder = Base64.getEncoder();
        String text = encoder.encodeToString(outputStream.toByteArray());
        return text;
    }

    /**
     * 生成二维码(内嵌LOGO)
     * 调用者指定二维码文件名
     *
     * @param content      内容
     * @param logoUrl      LOGO地址
     * @param needCompress 是否压缩LOGO
     * @throws Exception
     */
    public static QrCode encode(String content, String logoUrl, boolean needCompress) throws Exception {
        QrCode qrCode = new QrCode();
        qrCode.setContent(content)
                .setCenterImageUrl(logoUrl)
                .setNeedCompress(needCompress);
        return encode(qrCode);
    }

    public static QrCode encode(QrCode qrCode) throws Exception {
        if (qrCode == null) {
            throw new IllegalArgumentException("二维码参数异常,qrCode为空");
        }
        qrCode.checkDefaultProperties();
        BufferedImage image = createImage(qrCode);
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        ImageIO.write(image, qrCode.getFormat(), stream);
        String base64 = Base64.getEncoder().encodeToString(stream.toByteArray());
        qrCode.setBase64QrCode(IMG_BASE64_PREFIX + base64);
        return qrCode;
    }

    /**
     * 生成二维码(内嵌LOGO)
     *
     * @param content      内容
     * @param logoUrl      LOGO地址
     * @param output       输出流
     * @param needCompress 是否压缩LOGO
     * @throws Exception
     */
    public static void encode(String content, String logoUrl, OutputStream output, boolean needCompress)
            throws Exception {
        QrCode qrCode = new QrCode();
        qrCode.setContent(content)
                .setCenterImageUrl(logoUrl)
                .setNeedCompress(needCompress);
        BufferedImage image = createImage(qrCode);
        ImageIO.write(image, FORMAT, output);
    }

    private static BufferedImage createImage(QrCode qrCode) throws Exception {
        Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
        hints.put(EncodeHintType.CHARACTER_SET, CHARSET);
        hints.put(EncodeHintType.MARGIN, 1);
        BitMatrix bitMatrix = new MultiFormatWriter().encode(qrCode.getContent(), BarcodeFormat.QR_CODE,
                qrCode.getWidth(), qrCode.getHeight(),
                hints);
        int width = bitMatrix.getWidth();
        int height = bitMatrix.getHeight();
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
//                image.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);
                image.setRGB(x, y, bitMatrix.get(x, y) ? qrCode.getColor().getRGB() : qrCode.getBackground().getRGB());
            }
        }
        if (qrCode.getCenterImageUrl() == null || "".equals(qrCode.getCenterImageUrl())) {
            return image;
        }
        // 插入图片
        insertImage(image, qrCode);
        return image;
    }

    /**
     * 插入LOGO
     *
     * @param source 二维码图片
     * @throws Exception
     */
    private static void insertImage(BufferedImage source, QrCode qrCode) throws Exception {
        Image src = ImageIO.read(new URL(qrCode.getCenterImageUrl()));
        int width = src.getWidth(null);
        int height = src.getHeight(null);
        if (qrCode.getNeedCompress()) { // 压缩LOGO
            if (width > qrCode.getCenterImageWidth()) {
                width = qrCode.getCenterImageWidth();
            }
            if (height > qrCode.getCenterImageHeight()) {
                height = qrCode.getCenterImageHeight();
            }
            Image image = src.getScaledInstance(width, height, Image.SCALE_SMOOTH);
            BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
            Graphics g = tag.getGraphics();
            g.drawImage(image, 0, 0, null); // 绘制缩小后的图
            g.dispose();
            src = image;
        }
		// 插入LOGO
        Graphics2D graph = source.createGraphics();
        int x = (qrCode.getWidth() - width) / 2;
        int y = (qrCode.getWidth() - height) / 2;
        graph.drawImage(src, x, y, width, height, null);
        Shape shape = new RoundRectangle2D.Float(x, y, width, width, 6, 6);
        graph.setStroke(new BasicStroke(3f));
        graph.draw(shape);
        graph.dispose();
    }


    /**
     * 解析二维码
     *
     * @param path 二维码本地图片地址
     * @throws Exception
     */
    public static String decodeLocalFile(String path) throws Exception {
        BufferedImage image;
        image = ImageIO.read(new File(path));
        if (image == null) {
            return null;
        }
        return decode(image);
    }

    /**
     * 解析二维码
     *
     * @param url 二维码网络图片地址
     * @throws Exception
     */
    public static String decodeUrlFile(String url) throws Exception {
        BufferedImage image;
        image = ImageIO.read(new URL(url));
        if (image == null) {
            return null;
        }
        return decode(image);
    }

    /**
     * 解析二维码
     */
    public static String decode(BufferedImage image) throws Exception {
        BufferedImageLuminanceSource source = new BufferedImageLuminanceSource(image);
        BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
        com.google.zxing.Result result;
        Hashtable<DecodeHintType, Object> hints = new Hashtable<DecodeHintType, Object>();
        hints.put(DecodeHintType.CHARACTER_SET, CHARSET);
        result = new MultiFormatReader().decode(bitmap, hints);
        String resultStr = result.getText();
        return resultStr;
    }

    @Data
    @Accessors(chain = true)
    public static class QrCode {
        //二维码内容
        private String content;

        //二维码logo或者其他图片网络地址,放在二维码中心位置
        private String centerImageUrl;

        //是否压缩imageUrl
        private Boolean needCompress;

        //二维码宽
        private Integer width;

        //二维码高
        private Integer height;

        //二维码背景色 也可以是new Color()自定义rgb;
        private Color background;

        //二维码前景色
        private Color color;

        //中心位置图片宽度
        private Integer centerImageWidth;

        //中心位置图片高度
        private Integer centerImageHeight;

        private String format = "PNG";
        private String charset = "utf-8";

        private String base64QrCode;

        public QrCode() {
        }

        public QrCode(String content, String centerImageUrl, boolean needCompress, Integer width, Integer height,
                      Color background, Color color, Integer centerImageWidth, Integer centerImageHeight,
                      String format) {
            this.content = content;
            this.centerImageUrl = centerImageUrl;
            this.needCompress = needCompress;
            this.width = width;
            this.height = height;
            this.background = background;
            this.color = color;
            this.centerImageWidth = centerImageWidth;
            this.centerImageHeight = centerImageHeight;
            this.format = format;
            this.charset = "utf-8";
        }

        public void checkDefaultProperties() {
            if (this.needCompress == null) {
                this.needCompress = false;
            }
            if (this.width == null) {
                this.width = QrCodeUtil.QRCODE_SIZE;
            }
            if (this.height == null) {
                this.height = QrCodeUtil.QRCODE_SIZE;
            }
            if (this.background == null) {
                this.background = Color.WHITE;
            }
            if (this.color == null) {
                this.color = Color.BLACK;
            }
            if (this.centerImageWidth == null) {
                this.centerImageWidth = QrCodeUtil.CENTER_IMAGE_HEIGHT;
            }
            if (this.centerImageHeight == null) {
                this.centerImageHeight = QrCodeUtil.CENTER_IMAGE_WIDTH;
            }
        }
    }

    public static void main(String[] args) throws Exception {
        String text = "https://preparent.artstep.cn/wechat/payIndex" +
                ".html?schoolId=1585535185663002&confirmationPersonId=1089&payChannelType=null&profiles=dev";
        String logo = "https://shinedata-edu.oss-cn-shanghai.aliyuncs.com/image/e232bca163174e9092afdf116297bc52.jpg";
		QrCode qrCode = new QrCode();
		qrCode.setContent(text)
				.setCenterImageUrl(logo)
				.setNeedCompress(true)
				.setBackground(Color.WHITE)
				.setColor(Color.blue);
        System.out.println(encode(qrCode).getBase64QrCode());
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值