zoukankan      html  css  js  c++  java
  • ZXing 生成、读取二维码(带logo)

      前言

      ZXing,一个支持在图像中解码和生成条形码(如二维码、PDF 417、EAN、UPC、Aztec、Data Matrix、Codabar)的库。ZXing(“zebra crossing”)是一个开源的、多格式的、用Java实现的一维/二维条码图像处理库,具有到其他语言的端口。

      GitHub地址,猛戳:https://github.com/zxing/zxing

      API文档,猛戳:https://zxing.github.io/zxing/apidocs/index.html

      介绍文档,猛戳:https://zxing.github.io/zxing/

      代码编写

      部分代码参考:https://blog.csdn.net/weixin_39494923/article/details/79058799

      maven

      我们是java端,所以需要引这两个

            <!-- ZXing -->
            <dependency>
                <groupId>com.google.zxing</groupId>
                <artifactId>core</artifactId>
                <version>3.3.3</version>
            </dependency>
            <dependency>
                <groupId>com.google.zxing</groupId>
                <artifactId>javase</artifactId>
                <version>3.3.3</version>
            </dependency>

      Test.java

    public class Test{
    
        public static void main(String[] args) {
            try {
                QREncode();
    
                QRReader(new File("D:\zxing1.gif"));
            } catch (WriterException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (NotFoundException e) {
                e.printStackTrace();
            }
        }
    
        /**
         * 生成二维码
         */
        public static void QREncode() throws WriterException, IOException {
            String content = "个人博客:https://www.cnblogs.com/huanzi-qch/";//二维码内容
            int width = 200; // 图像宽度
            int height = 200; // 图像高度
            String format = "gif";// 图像类型
            Map<EncodeHintType, Object> hints = new HashMap<>();
            //内容编码格式
            hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
            // 指定纠错等级
            hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
            //设置二维码边的空度,非负数
            hints.put(EncodeHintType.MARGIN, 1);
            BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints);
            MatrixToImageWriter.writeToPath(bitMatrix, format, new File("D:\zxing.gif").toPath());// 输出原图片
            MatrixToImageConfig matrixToImageConfig = new MatrixToImageConfig(0xFF000001, 0xFFFFFFFF);
            /*
                问题:生成二维码正常,生成带logo的二维码logo变成黑白
                原因:MatrixToImageConfig默认黑白,需要设置BLACK、WHITE
                解决:https://ququjioulai.iteye.com/blog/2254382
             */
            BufferedImage bufferedImage = LogoMatrix(MatrixToImageWriter.toBufferedImage(bitMatrix,matrixToImageConfig), new File("D:\logo.png"));
    //        BufferedImage bufferedImage = LogoMatrix(toBufferedImage(bitMatrix), new File("D:\logo.png"));
            ImageIO.write(bufferedImage, "gif", new File("D:\zxing1.gif"));//输出带logo图片
            System.out.println("输出成功.");
        }
    
        /**
         * 识别二维码
         */
        public static void QRReader(File file) throws IOException, NotFoundException {
            MultiFormatReader formatReader = new MultiFormatReader();
            //读取指定的二维码文件
            BufferedImage bufferedImage =ImageIO.read(file);
            BinaryBitmap binaryBitmap= new BinaryBitmap(new HybridBinarizer(new BufferedImageLuminanceSource(bufferedImage)));
            //定义二维码参数
            Map  hints= new HashMap<>();
            hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
            com.google.zxing.Result result = formatReader.decode(binaryBitmap, hints);
            //输出相关的二维码信息
            System.out.println("解析结果:"+result.toString());
            System.out.println("二维码格式类型:"+result.getBarcodeFormat());
            System.out.println("二维码文本内容:"+result.getText());
            bufferedImage.flush();
        }
    
        /**
         * 二维码添加logo
         * @param matrixImage 源二维码图片
         * @param logoFile logo图片
         * @return 返回带有logo的二维码图片
         * 参考:https://blog.csdn.net/weixin_39494923/article/details/79058799
         */
        public static BufferedImage LogoMatrix(BufferedImage matrixImage, File logoFile) throws IOException{
            /**
             * 读取二维码图片,并构建绘图对象
             */
            Graphics2D g2 = matrixImage.createGraphics();
    
            int matrixWidth = matrixImage.getWidth();
            int matrixHeigh = matrixImage.getHeight();
    
            /**
             * 读取Logo图片
             */
            BufferedImage logo = ImageIO.read(logoFile);
    
            //开始绘制图片
            g2.drawImage(logo,matrixWidth/5*2,matrixHeigh/5*2, matrixWidth/5, matrixHeigh/5, null);//绘制
            BasicStroke stroke = new BasicStroke(5,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND);
            g2.setStroke(stroke);// 设置笔画对象
            //指定弧度的圆角矩形
            RoundRectangle2D.Float round = new RoundRectangle2D.Float(matrixWidth/5*2, matrixHeigh/5*2, matrixWidth/5, matrixHeigh/5,20,20);
            g2.setColor(Color.white);
            g2.draw(round);// 绘制圆弧矩形
    
            //设置logo 有一道灰色边框
            BasicStroke stroke2 = new BasicStroke(1,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND);
            g2.setStroke(stroke2);// 设置笔画对象
            RoundRectangle2D.Float round2 = new RoundRectangle2D.Float(matrixWidth/5*2+2, matrixHeigh/5*2+2, matrixWidth/5-4, matrixHeigh/5-4,20,20);
            g2.setColor(new Color(128,128,128));
            g2.draw(round2);// 绘制圆弧矩形
    
            g2.dispose();
            matrixImage.flush() ;
            return matrixImage ;
        }
    }

      

      效果演示

      D盘文件

      查看图片

      后台识别、微信扫描结果

      后记

      后端生成我们可以用ZXing框架,那么前端js又应该如何生成、识别二维码呢?QRCode.js,QRCode.js 是一个用于生成二维码的 JavaScript 库。主要是通过获取 DOM 的标签,再通过 HTML5 Canvas 绘制而成,不依赖任何库。菜鸟教程,猛戳:http://www.runoob.com/w3cnote/javascript-qrcodejs-library.html

      但是qrcode默认不支持自定义logo,怎么办呢?两种方法:

      1、创建一个img标签,调整样式,让logo在二维码区域上居中显示

      2、创建一个canvas画布,将二维码跟logo重新绘制,让logo在二维码区域上居中显示

      补充

      2020-02-25补充:实现二维码输出到浏览器功能

      1、生成二维码时,不是直接保存成图片,而是返回BufferedImage

        /**
         * 生成二维码
         */
        public static BufferedImage QREncode(String content){
            int width = 250; // 图像宽度
            int height = 250; // 图像高度
            Map<EncodeHintType, Object> hints = new HashMap<>();
            //内容编码格式
            hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
            // 指定纠错等级
            hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
            //设置二维码边的空度,非负数
            hints.put(EncodeHintType.MARGIN, 1);
            BitMatrix bitMatrix = null;
            BufferedImage bufferedImage = null;
            try {
                bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints);
    
                MatrixToImageConfig matrixToImageConfig = new MatrixToImageConfig(0xFF000001, 0xFFFFFFFF);
                bufferedImage = MatrixToImageWriter.toBufferedImage(bitMatrix,matrixToImageConfig);
            } catch (WriterException e) {
                e.printStackTrace();
            }
    
            //无logo
            //return bufferedImage;
    
            //带logo,System.getProperty("user.dir")是项目工程根路径
            assert bufferedImage != null;
            return LogoMatrix(bufferedImage,new File(System.getProperty("user.dir") + "\src\main\resources\static\img\logo.png"));
        }

      2、新增controller,供web调用

        //获取二维码图片
        @GetMapping("getBarCodeImage/{id}")
        public void getBarCodeImage(@PathVariable("id") String id) throws IOException {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
            HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getResponse();
    
            //设置页面不缓存
            assert response != null;
            response.setHeader("Pragma", "no-cache");
            response.setHeader("Cache-Control", "no-cache");
            response.setDateHeader("Expires", 0);
            response.getOutputStream();
    
            //设置输出的内容的类型为JPEG图像
            response.setContentType("image/jpeg");
    
            //通过id查询数据设置二维码内容
            String text = "{"id":""+ id +""}"
    
            BufferedImage bufferedImage = QREncode(text);
    
            //写给浏览器
            ImageIO.write(bufferedImage, "JPEG", response.getOutputStream());
        }

         3、web页面调用,thymeleaf语法

    <img id="barCodeImage" th:src="@{'/getBarCodeImage/' + ${id}}"/>
    <br/><br/>
    <button th:onclick="${'document.getElementById(''barCodeImage'').src = ctx + ''/getBarCodeImage/'+ id +'?time='' + new Date().getTime()'}">
    刷新二维码
    </button>
  • 相关阅读:
    CSS3 动画-- 鼠标移上去,div 会旋转、放大、移动
    jquery 微信端 点击物理返回按钮,弹出提示框
    H5 canvas pc 端米字格 写字板
    【三剑客】awk函数
    【三剑客】awk运算符
    【三剑客】awk命令2
    【三剑客】awk命令
    磁盘
    用户管理
    定时任务Crond
  • 原文地址:https://www.cnblogs.com/huanzi-qch/p/10097791.html
Copyright © 2011-2022 走看看