Zxing二维码技术工具类

引入相关依赖:

        <dependency>
            <groupId>com.google.zxing</groupId>
            <artifactId>javase</artifactId>
            <version>3.2.1</version>
        </dependency>
        <dependency>
            <groupId>com.google.zxing</groupId>
            <artifactId>core</artifactId>
            <version>3.2.1</version>
        </dependency>

工具类:

package com.jtj.qrcode.util;

import com.google.zxing.*;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.client.j2se.MatrixToImageConfig;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PathVariable;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Path;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * @Classname CodeUtil
 * @Description TODO 二维码工具类
 * @Date 2019/7/10 19:49
 * @Created by JTJ
 */
public class CodeUtil {

    public static int width = 600;
    public static int height = 600;
    public static String format = "png";

    public static String contents = "默认内容";

    public static String defaultFilePath = "";

    public static String[] checkList = new String[] {"png","jpg","gif","jepg"};

    /**
     * @Title: createLogoAndCode
     * @Desc: 创建二维码
     * @param logo contents path
     * @return
     */
    public static String createLogoAndCode(File logo, String contents, String path) {
        String result = "success";
        if (contents!=null) {
            CodeUtil.contents = contents;
        }
        if(!checkFormat(logo)) {
            return "logo文件出错!";
        }
        // 生成二维码
        try {
            BitMatrix bitMatrix = new MultiFormatWriter().encode(contents, BarcodeFormat.QR_CODE, width, height,
                    setCodeParams());
            if(path!=null) {
                //生成文件路径
                Path filePath = new File(savePalce(path)).toPath();
                MatrixToImageWriter.writeToPath(bitMatrix, format, filePath);
            }
            MatrixToImageConfig matrixToImageConfig = new MatrixToImageConfig(0xFF000001, 0xFFFFFFFF);
            /* 添加logo图片
             *  问题:生成二维码正常,生成带logo的二维码logo变成黑白
             *  原因:MatrixToImageConfig默认黑白,需要设置BLACK、WHITE
             *  解决:https://ququjioulai.iteye.com/blog/2254382
             */
            //判断是否需要logo
            if(logo!=null) {
                BufferedImage bufferedImage = groupImage(MatrixToImageWriter.toBufferedImage(bitMatrix,matrixToImageConfig),logo);
                //生成图片文件
                ImageIO.write(bufferedImage, format, new File(defaultFilePath));
            }else {
                ImageIO.write(MatrixToImageWriter.toBufferedImage(bitMatrix,matrixToImageConfig), format, new File(defaultFilePath));
            }
        } catch (Exception e) {
            result = "生成二维码出错!"+e.toString();
        }
        return result;
    }

    /**
     * 绘制logo图片
     * @param matrixImage
     * @param logoFile
     * @return
     * @throws IOException
     */
    public static BufferedImage groupImage(BufferedImage matrixImage, File logoFile) throws IOException {
        //先读取二维码图片

        Graphics2D g = matrixImage.createGraphics();

        //再读取logo图片
        BufferedImage logoImage = ImageIO.read(logoFile);

        //设置logo大小,太大,会覆盖二维码,此处20%
        int logoWidth = logoImage.getWidth() > matrixImage.getWidth()*2 /10 ? (matrixImage.getWidth()*2 /10) : logoImage.getWidth();
        int logoHeight = logoImage.getHeight() > matrixImage.getHeight()*2 /10 ? (matrixImage.getHeight()*2 /10) : logoImage.getHeight();

        //设置logo图片放置位置  放在中心
        int x = (matrixImage.getWidth() - logoWidth) / 2;
        int y = (matrixImage.getHeight() - logoHeight) / 2;

        //开始合并绘制图片
        g.drawImage(logoImage, x, y, logoWidth, logoHeight, null);
        g.drawRoundRect(x, y, logoWidth, logoHeight, 15 ,15);
        //线条设置
        BasicStroke stroke = new BasicStroke(5,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND);
        g.setStroke(stroke);

        //logo边框颜色
        g.setColor(Color.WHITE);
        g.drawRect(x, y, logoWidth, logoHeight);
        //释放对象
        g.dispose();
        logoImage.flush();
        matrixImage.flush();
        return matrixImage;
    }

    /**
     * @Title: setCodeParams
     * @Desc: 设置二维码参数
     * @param
     * @return
     */
    public static HashMap<EncodeHintType, Object> setCodeParams() {
        // 封装二维码的参数
        HashMap<EncodeHintType, Object> hashMap = new HashMap<>();
        hashMap.put(EncodeHintType.CHARACTER_SET, "UTF-8"); // 字符集
        hashMap.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M); // 纠错等级
        hashMap.put(EncodeHintType.MARGIN, 2); // 边距
        return hashMap;
    }

    /**
     * @Title: savePalce
     * @Desc: 二维码保存地址
     * @param
     * @return
     */
    public static String savePalce(String path) {
        String codeName = UUID.randomUUID().toString() + new SimpleDateFormat("YYYY-MM-DD").format(new Date()).replace("-", "s");
        defaultFilePath = path + codeName.trim() + "." + format;
        return defaultFilePath;
    }

    /**
     * @Title: readCode
     * @Desc: 读取二维码信息
     * @param file
     * @return
     */
    public static String readCode(File file) {
        String result = "";
        try {
            MultiFormatReader formatReader = new MultiFormatReader();

            BufferedImage image = ImageIO.read(file);

            BinaryBitmap binaryBitmap = new BinaryBitmap(new HybridBinarizer(new BufferedImageLuminanceSource(image)));

            Map<DecodeHintType, Object> hints = new HashMap<>();
            hints.put(DecodeHintType.CHARACTER_SET, "utf-8");// 字符集
            Result decodeResult = formatReader.decode(binaryBitmap, hints);

            result = "解析之后的结果:" + decodeResult.toString() + "\n" + "二维码格式类型:" + decodeResult.getBarcodeFormat() + "\n"
                    + "二维码文本内容:" + decodeResult.getText() + "!";
        } catch (Exception e) {
            result = "解析错误";
            return result;
        }
        return result;
    }

    /**
     * @Title: checkFormat
     * @Desc: 验证文件后缀格式
     * @param logoFile
     * @return
     */
    public static boolean checkFormat(File logoFile) {
        //文件是否为空
        if (null == logoFile) {
            System.out.println("logo文件为空!");
            return true;
        }

        String fileName = logoFile.getName();
        String suffix = fileName.substring(fileName.lastIndexOf(".") + 1);

        for (String s : checkList) {
            if (s.equalsIgnoreCase(suffix)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 实现 流文件 响应给浏览器
     * @param content
     * @param response
     */
    public static void encodeQrcode(@PathVariable("content") String content, HttpServletResponse response) {
        if (StringUtils.isEmpty(content))        return;
        MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
        Map hints = new HashMap();
        //设置字符集编码类型
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
        //设置二维码四周的白色边框 ,默认是4,默认为4的时候白色边框实在是太粗了
        hints.put(EncodeHintType.MARGIN, 0);
        BitMatrix bitMatrix = null;
        try {
            bitMatrix = multiFormatWriter.encode(content, BarcodeFormat.QR_CODE, 190, 190, hints);
            BufferedImage image = MatrixToImageWriter.toBufferedImage(bitMatrix);
            //输出二维码图片流
            try {
                OutputStream out = response.getOutputStream();
                response.setContentType("image/png");
                //为文件重新设置名字,采用数据库内存储的文件名称
                response.addHeader("Content-Disposition", "attachment; filename=\"" + new String("code.png".getBytes("UTF-8"),"ISO8859-1") + "\"");
                ImageIO.write(image, "png", out);
                out.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
        } catch (WriterException e1) {
            e1.printStackTrace();
        }
    }
}

测试controller:

    //不保存二维码图片,以流的形式返回
    @RequestMapping("/code")
    public void getCode(HttpServletResponse response){
        CodeUtil.encodeQrcode("邀请码",response);
    }

测试html文件:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>二维码</title>
</head>
<body>
<img src="/code/">
<a href="/code/">下载</a>
</body>
</html>

浏览器访问:http://localhost:8080/index.html

点击下载就会下载此二维码!服务器没有做图片的保存,看个人需要修改!

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

十万芙特

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

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

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

打赏作者

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

抵扣说明:

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

余额充值