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了嗎?

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