• java调用pyzbar解析base64型的二维码实践优化


    1. Java代码
      UserController.java
    package com.yang.springbootlucene.controller;
    
    import lombok.Data;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.core.io.ClassPathResource;
    import org.springframework.web.bind.annotation.RequestBody;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import java.io.File;
    import java.io.FileWriter;
    import java.io.IOException;
    
    /**
     * @author:yjx
     * @description:
     * @date:2019/11/28 15:29
     */
    @Slf4j
    @RestController
    @RequestMapping("/user")
    public class UserController {
    
        @Value("${pyzbar.script}")
        private String scriptPath;
    
        private static final String BASE_64_PREFIX = "data:image/png;base64,";
    
        /**
         * 这种方式在源码中成功调用,但达成jar包后,找不到脚本路径,所以脚本必须放在外面
         */
        @Deprecated
        private static String pyZbarScriptPath;
        /* static {
            ClassPathResource pathResource = new ClassPathResource("/script/my_py_zbar.py");
            try {
                pyZbarScriptPath = pathResource.getFile().getAbsolutePath();
            } catch (IOException e) {
                e.printStackTrace();
            }
        } */
    
        @RequestMapping("/cameraScanPyZbar")
        public Object cameraScanPyZbar(@RequestBody String base64) throws IOException {
            if (this.checkBase64Head(base64)) {
                //1.去掉base64字符的头部
                String base64Str = this.cutHead(base64);
    
                //2.创建临时文件(由于图片的base64字符太长,不支持直接以命令参数的形式传递,故将字符串写入临时文件,而后python程序读取临时文件内容)
                String tempPath = "./" + Thread.currentThread().getName();
                File tempFile = new File(tempPath);
                FileWriter fileWriter = new FileWriter(tempFile, false);
                fileWriter.write(base64Str);
                fileWriter.flush();
                fileWriter.close();
    
                //3.调用pyzbar解析base64字符串
                String plainText = PyZbarUtil.executePyzbar("python", scriptPath, tempFile.getAbsolutePath());
    
                //4.删除临时文件
                tempFile.delete();
                System.err.println("--------->" + plainText);
                return plainText;
            } else {
                return "参数格式错误";
            }
        }
    
        /**
         * 校验Base64值是否已规定的串开始
         *
         * @param base64
         * @return
         */
        private boolean checkBase64Head(String base64) {
            return base64.startsWith(BASE_64_PREFIX);
        }
    
        /**
         * Base64去头
         *
         * @param base64
         * @return
         */
        private String cutHead(String base64) {
            return base64.replaceAll(BASE_64_PREFIX, "");
        }
    }
    

    PyZbarUtil.java

    package com.yang.springbootlucene.controller;
    
    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    
    public final class PyZbarUtil {
    
        /**
         * 脚本执行工具类
         *
         * @param lang       命令语言
         * @param scriptPath 脚本绝对路劲
         * @param base64Path     base64文件绝对路径
         * @return
         */
        public static String executePyzbar(String lang, String scriptPath, String base64Path) {
            String[] arguments = new String[]{lang, scriptPath, base64Path};
            try {
                Process process = Runtime.getRuntime().exec(arguments);
                int re = process.waitFor();
                if (re == 0) {
                    try (BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream(), "GBK"));) {
                        return in.readLine();
                    }
                } else {
                    System.err.println("脚本调用失败");
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    }
    
    1. python脚本my_py_zbar.py
    # -*-coding:UTF-8-*-
    
    import sys
    import base64
    from io import BytesIO
    import pyzbar.pyzbar as pyzbar
    from PIL import Image,ImageEnhance
    
    
    '''将base64转换为字节流'''
    def convert_base64_to_byte_stream(base64_str):
        # 1.解码Base64字符串
        img_data = base64.b64decode(base64_str)
    
        # 2.将节码结果转为字节流
        byte_stream = BytesIO(img_data)
        return byte_stream
    
    
    '''从将字节流解析二维码'''
    def parse_byte_stream_qr_code(byte_stream):
        # 3.打开字节流得到图片对象
        img = Image.open(byte_stream)
    
        img = ImageEnhance.Brightness(img).enhance(2.0)  #增加亮度
        img = ImageEnhance.Contrast(img).enhance(4.0)  #增加对比度
        # img = ImageEnhance.Sharpness(img).enhance(17.0)  #锐利化
        # img = img.convert('L')  #灰度化
    
        # img.show()  # 播放图片,供测试用
    
        # 4.调用pyzbar解析图片中的二维码
        barcodes = pyzbar.decode(img)
    
        # 5.打印解析结果
        return barcodes[0].data.decode("utf-8")
    
    
    def main(argv):
    #    print(parse_byte_stream_qr_code(convert_base64_to_byte_stream(argv[1])))
        print(parse_byte_stream_qr_code(convert_base64_to_byte_stream(open(argv[1]).readline())))
    
    
    if __name__ == "__main__":
        main(sys.argv)
    
    1. yaml配置项
    pyzbar:
      script: 'C:UsersTyraelDesktoppypyscriptmy_py_zbar.py'
    
    1. 坑点:
    • 图片转base64后,得到的字符串太长,不能直接以命令参数的形式传递,所以必须将其写入临时文件,然后python脚本读取临时文件进行解析
    • 若将python脚本放在项目中,项目打成jar包后,无法定位脚本路径,导致执行失败,所以必须将脚本放在jar包外,以配置的形式将路径传递给java项目
  • 相关阅读:
    Latin1的所有字符编码
    Qt自定义委托在QTableView中绘制控件、图片、文字(内容比较全)
    Delphi5 update1的序列号
    Access Violation at address 00000000.Read of address 00000000 解决办法
    RealThinClient学习(一)
    使用WebDriver遇到的那些坑
    谱聚类(Spectral Clustering)详解
    Asp.net Mvc4默认权限详细(上)
    ASP.NET Web API中的JSON和XML序列化
    [珠玑之椟]估算的应用与Little定律
  • 原文地址:https://www.cnblogs.com/JaxYoun/p/13476900.html
Copyright © 2020-2023  润新知