java使用zxing动态生成二维码

首先需要zxing的两个核心jar包,core,javase,我这边用的maven生成的jar包自己导进去的。这两个jar包我会上传到csdn上,大家可以自行下载。

下载地址:https://download.csdn.net/download/zhao_xinhu/10731554

直接上代码:

package org.zhao.util;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.zhao.exception.UtilException;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * Created by zhao_xinhu
 * On 2018/10/18
 * 生成二维码utils
 */
public class ZxingUtils {

    private static Logger logger = LoggerFactory.getLogger(ZxingUtils.class);

    private static final int width = 300;//默认二维码宽度

    private static final int height = 300;//默认二维码高度

    private static final String format = "png";//默认二维码格式

    private static final Map<EncodeHintType, Object> hints = new HashMap<>();//二维码参数

    private static final int logo_width = 60;//默认logo宽度

    private static final int logo_height = 60;//默认logo高度


    static{
        hints.put(EncodeHintType.CHARACTER_SET,"utf-8");//字符编码
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);//容错等级L/M/Q/H其中L为最低,H为最高
        hints.put(EncodeHintType.MARGIN,2);//二维码与图片边距
    }

    /**
     * 生成 默认尺寸、默认名字 无logo 二维码
     * @param srcUrl
     * @param imgPath
     * @return
     * @throws Exception
     */
    public static String createORCode(String srcUrl, String imgPath) throws Exception {
        String finalPath = createORCode(srcUrl, imgPath, width, height, null);
        return finalPath;
    }

    /**
     * 生成 指定大小 指定名称 无logo 二维码
     * @param srcUrl
     * @param imgPath
     * @param imgWidth
     * @param imgHeight
     * @param imgName
     * @return
     */
    public static String createORCode(String srcUrl, String imgPath, int imgWidth, int imgHeight, String imgName) throws Exception {
        String orCode = createORCode(srcUrl, imgPath, imgWidth, imgHeight, imgName, null, false);
        return orCode;
    }
    /**
     * 生成 指定尺寸,默认名称,无logo 的二维码
     * @param srcUrl
     * @param imgPath
     * @param imgWidth
     * @param imgHeight
     * @return
     * @throws WriterException
     * @throws IOException
     */
    public static String createORCode(String srcUrl, String imgPath, int imgWidth, int imgHeight) throws Exception {
        String finalPath = createORCode(srcUrl, imgPath, imgWidth, imgHeight,null, null, false);
        return finalPath;
    }

    /**
     * 生成 默认尺寸,默认名称,包含logo 二维码
     * @param srcUrl
     * @param imgPath
     * @param logoPath
     * @param needCompress
     * @return
     */
    public static String createORCodeLogo(String srcUrl, String imgPath, String logoPath, boolean needCompress) throws Exception {
        String orCodeLogo = createORCodeLogo(srcUrl, imgPath, width, height, logoPath, needCompress);
        return orCodeLogo;
    }

    /**
     * 生成 指定大小 默认名称 包含logo 二维码
     * @param srcUrl
     * @param imgPath
     * @param imgWidth
     * @param imgHeight
     * @param logoPath
     * @param needCompress
     * @return
     */
    public static String createORCodeLogo(String srcUrl, String imgPath, int imgWidth, int imgHeight, String logoPath, boolean needCompress) throws Exception {
        String orCodeLogo = createORCodeLogo(srcUrl, imgPath, imgWidth, imgHeight, null, logoPath, needCompress);
        return orCodeLogo;
    }

    /**
     * 生成 指定大小 指定名称 包含logo 二维码
     * @param srcUrl
     * @param imgPath
     * @param imgWidth
     * @param imgHeight
     * @param imgName
     * @param logoPath
     * @param needCompress
     * @return
     * @throws Exception
     */
    public static String createORCodeLogo(String srcUrl, String imgPath, int imgWidth, int imgHeight, String imgName, String logoPath, boolean needCompress) throws Exception {
        String orCode = createORCode(srcUrl, imgPath, imgWidth, imgHeight, imgName, logoPath, needCompress);
        return orCode;
    }
    /**
     * 生成 指定尺寸、指定名称、包含logo 的二维码
     * 如果logoPath为null,则默认生成不包含logo的二维码
     * 如果确定生成不包含logo的二维码,则可以调用另外指定方法
     * @param srcUrl    需要生成二维码地址
     * @param imgPath   需要保存二维码的目录地址
     * @param imgWidth  需要生成二维码的宽度
     * @param imgHeight 需要生成二维码的高度
     * @param logoPath  需要生成二维码的中间logo
     * @param needCompress  logo是否需要压缩
     * @return
     * @throws Exception
     */
    private static String createORCode(String srcUrl, String imgPath, int imgWidth, int imgHeight, String imgName, String logoPath, boolean needCompress) throws Exception{

        boolean isDirectory = FileUtils.checkDirectory(imgPath);
        if(!isDirectory){
            logger.info("请用户选择正确的保存二维码的路径");
            throw new UtilException("错误图片路径");
        }
        String finalPath = "";
        //如果logo图片是null,生成不包含logo的二维码,否则生成含有logo的二维码
        if(StringUtils.isNotBlank(logoPath)){
            boolean b = FileUtils.checkImg(logoPath);
            if(b) {
                finalPath = createORCodeForLogo(srcUrl, imgPath, imgWidth, imgHeight, imgName, logoPath, needCompress);
            }
            else {
                logger.info("请用户选择正确的logo格式jpg or png");
                throw new UtilException("错误图片后缀");
            }
        }else {
            finalPath = createORCodeNotLogo(srcUrl,imgPath,imgWidth,imgHeight,imgName);
        }
        return finalPath;
    }


    /**
     * 创建一个 指定大小、指定名称、包含logo 二维码
     * @param srcUrl
     * @param imgPath
     * @param imgWidth
     * @param imgHeight
     * @param imgName
     * @param logoPath
     * @param needCompress
     * @throws WriterException
     * @throws IOException
     */
    private static String createORCodeForLogo(String srcUrl, String imgPath, int imgWidth, int imgHeight, String imgName, String logoPath, boolean needCompress) throws WriterException, IOException {

        BufferedImage bufferedImage = drawQR(srcUrl,imgWidth,imgHeight);
        Image src = enterFinalLogoImg(logoPath, needCompress);
        insertLogo(bufferedImage,src);
        String finalPath = outImgToPath(bufferedImage, format, imgPath,imgName);
        return finalPath;
    }

    /**
     * 生成指定大小,指定名称,无logo的二维码
     * @param srcUrl
     * @param imgPath
     * @param imgWidth
     * @param imgHeight
     * @param imgName
     * @return
     * @throws WriterException
     * @throws IOException
     */
    private static String createORCodeNotLogo(String srcUrl, String imgPath, int imgWidth, int imgHeight, String imgName) throws WriterException, IOException {
        BufferedImage bufferedImage = drawQR(srcUrl, imgWidth, imgHeight);
        String s = outImgToPath(bufferedImage, format, imgPath, imgName);
        return s;
    }

    /**
     * 绘制二维码
     * @param srcUrl
     * @param imgWidth
     * @param imgHeight
     * @return
     * @throws WriterException
     */
    private static BufferedImage drawQR(String srcUrl, int imgWidth, int imgHeight) throws WriterException {
        BitMatrix bitMatrix = new MultiFormatWriter().encode(srcUrl, BarcodeFormat.QR_CODE, imgWidth, imgHeight, hints);

        BufferedImage bufferedImage = new BufferedImage(imgWidth, imgHeight, BufferedImage.TYPE_INT_BGR);
        //绘制成二维码(应该)
        for (int x = 0; x < imgWidth; x++) {
            for (int y = 0; y < imgHeight; y++) {
                bufferedImage.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000
                        : 0xFFFFFFFF);
            }
        }
        return bufferedImage;
    }

    /**
     * 确定最终需要添加的logo大小(是否需要压缩)
     * @param logoPath
     * @param needCompress
     * @return
     * @throws IOException
     */
    private static Image enterFinalLogoImg(String logoPath, boolean needCompress) throws IOException {
        //插入logo
        BufferedImage logoImage = ImageIO.read(new File(logoPath));
        int tempWidth = logoImage.getWidth(null);
        int tempHeight = logoImage.getHeight(null);
        //最终确定的logo图片
        Image src = logoImage;
        //需要压缩
        if(needCompress){
            if(tempWidth > logo_width){
                tempWidth = logo_width;
            }
            if(tempHeight > logo_height){
                tempHeight = logo_height;
            }
            Image scaledInstance = logoImage.getScaledInstance(tempWidth, tempHeight, Image.SCALE_SMOOTH);
            BufferedImage tag = new BufferedImage(width, height,
                    BufferedImage.TYPE_INT_RGB);
            Graphics graphics = tag.getGraphics();
            graphics.drawImage(scaledInstance,0,0,null);
            graphics.dispose();
            src = scaledInstance;
        }
        return src;
    }

    /**
     * 将二维码中间插入logo
     * @param img
     * @param logo
     */
    private static void insertLogo(BufferedImage img, Image logo){
        Graphics2D graphics2D = img.createGraphics();
        int imgWidth = img.getWidth(null);
        int imgHeight = img.getHeight(null);
        //将logo定位到中间位置
        int logoWidth = logo.getWidth(null);
        int logoHeight = logo.getHeight(null);
        int x = (imgWidth - logoWidth) / 2;
        int y = (imgHeight - logoHeight) / 2;
        graphics2D.drawImage(logo, x, y, logoWidth, logoHeight, null);
        Shape shape = new RoundRectangle2D.Float(x, y, logoWidth, logoHeight, 6, 6);
        graphics2D.setStroke(new BasicStroke(3f));
        graphics2D.draw(shape);
        graphics2D.dispose();
    }

    /**
     * 将二维码保存到指定位置
     * @param image
     * @param format        生成二维码格式、暂时png格式
     * @param imgPath       生成二维码路径
     * @param imgName       生成二维码名称
     * @throws IOException
     * @return 返回生成二维码的图片地址
     */
    private static String outImgToPath(BufferedImage image, String format, String imgPath, String imgName) throws IOException {
        if(StringUtils.isBlank(imgName))
            imgName = UUID.randomUUID().toString();
        String finalImgPath = imgPath + imgName + "." + format;
        ImageIO.write(image, format, new File(finalImgPath));
        return finalImgPath;
    }
}

 中间有个判断图片后缀的和判断路径是否存在的方法也给大家贴一下吧: 

    /**
     * 检查该path是否是路径
     * @param path
     * @return
     */
    public static boolean checkDirectory(String path){
        File file = new File(path);
        if(!file.exists()){
            file.mkdirs();
        }
        return file.isDirectory();
    }

    /**
     * 检测该参数是图片后缀的
     * 暂时只支持jpg png
     * @param path
     * @return
     */
    public static boolean checkImg(String path){
        File file = new File(path);
        String fileName = file.getName();
        int i = fileName.indexOf(".");
        String suff = "";
        if(i != -1){
            suff = fileName.substring(i + 1);
        }
        boolean isImg = false;
        if(StringUtils.isNotBlank(suff)){
            //SUPPORT_FILE_SUFFIX是一个list("jpg","png")
            boolean contains = SUPPORT_FILE_SUFFIX.contains(suff);
            if(contains)
                isImg = true;
        }
        return isImg;
    }

测试一下:

public static void main(String[] args) {
        String srcUrl = "http://www.baidu.com";
        String imgPath = "d:/QR/";
        int imgWidth = 400;
        int imgHeight = 400;
        String logoPath = "C:/Users/Administrator/Desktop/zhao_xinhu/img/myself/镇魂街.jpg";
        boolean needCompress = true;

        try{
            //生成 默认尺寸,默认名称,无logo
            String orCode = ZxingUtils.createORCode(srcUrl, imgPath);
            //生成 指定尺寸,默认名称,无logo
            String orCode2 = ZxingUtils.createORCode(srcUrl,imgPath,imgWidth,imgHeight);
            //生成指定尺寸,指定名称,无logo
            String orCode3 = ZxingUtils.createORCode(srcUrl,imgPath,imgWidth,imgHeight,"指定的名称");
            System.out.println("默认尺寸、默认名称、无logo地址:" + orCode);
            System.out.println("指定尺寸、默认名称、无logo地址:" + orCode2);
            System.out.println("指定尺寸、指定名称、无logo地址:" + orCode3);
            //生成 默认尺寸,默认名称,有logo
            String orCodeLogo = ZxingUtils.createORCodeLogo(srcUrl,imgPath,logoPath,needCompress);
            //生成 指定尺寸 默认名称,有logo
            String orCodeLogo2 = ZxingUtils.createORCodeLogo(srcUrl,imgPath,imgWidth,imgHeight,logoPath,needCompress);
            //生成 指定尺寸,指定名称,有logo
            String orCodeLogo3 = ZxingUtils.createORCodeLogo(srcUrl,imgPath,imgWidth,imgHeight,"包含logo指定名称",logoPath,needCompress);
            System.out.println("默认尺寸、默认名称、有logo地址:" + orCodeLogo);
            System.out.println("指定尺寸、默认名称、有logo地址:" + orCodeLogo2);
            System.out.println("指定尺寸、指定名称、有logo地址:" + orCodeLogo3);
        }catch (Exception e){
            e.printStackTrace();
        }
        return;
    }

生成结果:

 不含logo的:

含logo的:

不知道大家会使用zxing了吗?

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章