zoukankan      html  css  js  c++  java
  • Java 二维码生成工具类

    /**
     * 二维码 工具
     *
     * @author Rubekid
     *
     */
    public class QRcodeUtils {
        
        /**
         * 默认version
         */
        public static final int DEFAULT_VERSION = 9;
    
        /**
         * 图片类型 png (默认) 比较小
         */
        public static final String IMAGE_TYPE_PNG = "png";
    
        /**
         * 图片类型 jpg
         */
        public static final String IMAGE_TYPE_JPEG = "jpg";
    
        /**
         * 容错率等级 L
         */
        public static final char CORRECT_L = 'L';
    
        /**
         * 容错率等级 M
         */
        public static final char CORRECT_M = 'M';
    
        /**
         * 容错率等级 Q
         */
        public static final char CORRECT_Q = 'Q';
    
        /**
         * 容错率等级 H
         */
        public static final char CORRECT_H = 'H';
    
        /**
         * 旁白占用比率
         */
        public static final double PADDING_RATIO = 0.02;
    
        /**
         * 生成二维码
         *
         * @param content
         *            要生成的内容
         * @param size
         *            要生成的尺寸
         * @param versoin
         *            二维码尺寸,取值范围1-40,值越大尺寸越大,可存储的信息越大
         * @param ecc
         *            二维码排错率,可选L(7%)、M(15%)、Q(25%)、H(30%)
         * @return
         * @throws Exception
         */
        public static BufferedImage encode(String content, int size, int version, char ecc) throws Exception {
            BufferedImage image = null;
            Qrcode qrcode = new Qrcode();
            // 设置二维码排错率,可选L(7%)、M(15%)、Q(25%)、H(30%),排错率越高可存储的信息越少,但对二维码清晰度的要求越小
            qrcode.setQrcodeErrorCorrect(ecc);
            qrcode.setQrcodeEncodeMode('B');
            // 设置设置二维码尺寸,取值范围1-40,值越大尺寸越大,可存储的信息越大
            qrcode.setQrcodeVersion(version);
            // 获得内容的字节数组,设置编码格式
            byte[] contentBytes = content.getBytes("utf-8");
    
            double ratio = 3;// 默认放大三倍
            int qrcodeSize = 21 + 4 * (version - 1);
            if (size > 0) {
                ratio = (double) size / qrcodeSize;
            }
            int intRatio = (int) Math.ceil(ratio);
    
            // 旁白
            int padding = (int) Math.ceil(qrcodeSize * intRatio * PADDING_RATIO);
            if (padding < 5) {
                padding = 5;
            }
            // 图片尺寸
            int imageSize = qrcodeSize * intRatio + padding * 2;
    
            // 图片边长 调整(10的倍数)
            if (intRatio > ratio) {
                int newSize = (int) Math.ceil(ratio * imageSize / intRatio);
                int r = newSize % 10;
                newSize += 10 - r;
                int newImageSize = (int) Math.floor(intRatio * newSize / ratio);
                padding += (newImageSize - imageSize) / 2;
                imageSize = newImageSize;
            } else {
                int r = imageSize % 10;
                int d = 10 - r;
                padding += d / 2;
                imageSize += d;
            }
    
            image = new BufferedImage(imageSize, imageSize, BufferedImage.TYPE_INT_RGB);
            Graphics2D gs = image.createGraphics();
            // 设置背景颜色
            gs.setBackground(Color.WHITE);
            gs.clearRect(0, 0, imageSize, imageSize);
    
            // 设定图像颜色 BLACK
            gs.setColor(Color.BLACK);
    
            // 输出内容 二维码
            if (contentBytes.length > 0 && contentBytes.length < 800) {
                boolean[][] codeOut = qrcode.calQrcode(contentBytes);
                for (int i = 0; i < codeOut.length; i++) {
                    for (int j = 0; j < codeOut.length; j++) {
                        if (codeOut[j][i]) {
                            gs.fillRect(j * intRatio + padding, i * intRatio + padding, intRatio, intRatio);
                        }
                    }
                }
            } else {
                throw new Exception("QRCode content bytes length = " + contentBytes.length + " not in [0, 800].");
            }
            gs.dispose();
            image.flush();
    
            if (intRatio > ratio) {
                image = resize(image, (int) Math.ceil(ratio * imageSize / intRatio));
            }
            return image;
        }
    
        /**
         * 生成二维码
         *
         * @param content
         * @param size
         * @return
         * @throws Exception
         */
        public static BufferedImage encode(String content, int size) throws Exception {
            return encode(content, size, DEFAULT_VERSION, CORRECT_Q);
        }
    
        /**
         * 生成二维码
         *
         * @param content
         * @param size
         * @param version
         * @return
         */
        public static BufferedImage encode(String content, int size, int version) throws Exception {
            return encode(content, size, version, CORRECT_Q);
        }
    
        /**
         * 生成二维码
         *
         * @param content
         * @param size
         * @param ecc
         * @return
         */
        public static BufferedImage encode(String content, int size, char ecc) throws Exception {
            return encode(content, size, DEFAULT_VERSION, ecc);
        }
    
        /**
         * 生成二维码
         *
         * @param content
         * @return
         */
        public static BufferedImage encode(String content) throws Exception {
            return encode(content, 0, DEFAULT_VERSION, CORRECT_Q);
        }
    
        /**
         * 解析二维码
         *
         * @throws UnsupportedEncodingException
         * @throws DecodingFailedException
         */
        public static String decode(BufferedImage bufferedImage) throws DecodingFailedException,
                UnsupportedEncodingException {
            QRCodeDecoder decoder = new QRCodeDecoder();
            return new String(decoder.decode(new MyQRCodeImage(bufferedImage)), "utf-8");
        }
    
        /**
         * 下载二维码
         *
         * @param response
         * @param filename
         * @param content
         * @param size
         * @param imageType
         * @throws Exception`
         */
        public static void download(HttpServletResponse response, String filename, String content, int size,
                String imageType, String logoPath) throws Exception {
            if (size > 2000) {
                size = 2000;
            }
            BufferedImage image = QRcodeUtils.encode(content, size);
            if(logoPath !=null){
                markLogo(image, logoPath);
            }
            // 替换占位符
            filename = filename.replace("{size}", String.valueOf(image.getWidth()));
            InputStream inputStream = toInputStream(image, imageType);
            int length = inputStream.available();
    
            // 设置response
            response.setContentType("application/x-msdownload");
            response.setContentLength(length);
            response.setHeader("Content-Disposition", "attachment;filename="
                    + new String(filename.getBytes("gbk"), "iso-8859-1"));
    
            // 输出流
            byte[] bytes = new byte[1024];
            OutputStream outputStream = response.getOutputStream();
            while (inputStream.read(bytes) != -1) {
                outputStream.write(bytes);
            }
            outputStream.flush();
        }
        
        /**
         * 下载二维码
         * @param response
         * @param filename
         * @param content
         * @param size
         * @param imageType
         * @throws Exception
         */
        public static void download(HttpServletResponse response, String filename, String content, int size,
                String imageType) throws Exception {
            download(response, filename, content, size, imageType, null);
        }
    
        /**
         * 下载二维码
         *
         * @param response
         * @param filename
         * @param content
         * @param size
         * @throws Exception
         */
        public static void download(HttpServletResponse response, String filename, String content, int size)
                throws Exception {
            download(response, filename, content, size, IMAGE_TYPE_PNG);
        }
        
        /**
         * 生成二维码文件
         * @param destFile
         * @param content
         * @param size
         * @param logoPath
         * @throws Exception
         */
        public static void createQrcodeFile(File destFile, String content, int size, String logoPath) throws Exception{
            if(!destFile.exists() || !destFile.isFile()){
                destFile.createNewFile();
            }
            OutputStream outputStream = new FileOutputStream(destFile);
            BufferedImage image = QRcodeUtils.encode(content, size);
            if(logoPath !=null){
                markLogo(image, logoPath);
            }
            InputStream inputStream = toInputStream(image, QRcodeUtils.IMAGE_TYPE_PNG);
            // 输出流
            byte[] bytes = new byte[1024];
            while (inputStream.read(bytes) != -1) {
                outputStream.write(bytes);
            }
            inputStream.close();
            outputStream.close();
        }
        
        /**
         * 生成二维码文件
         * @param destFile
         * @param content
         * @param size
         * @throws Exception
         */
        public static void createQrcodeFile(File destFile, String content, int size) throws Exception{
            createQrcodeFile(destFile, content, size, null);
        }
        
        /**
         * logo水印
         * @param qrcode
         * @param logoPath
         * @throws IOException
         */
        public static void markLogo(BufferedImage qrcode, String logoPath) throws IOException{
            File logoFile = new File(logoPath);
            if(logoFile.exists()){
                Graphics2D gs = qrcode.createGraphics();
                int width = qrcode.getWidth();
                int height = qrcode.getHeight();
                Image logo = ImageIO.read(logoFile);
                
                
                int scale = 6; //显示为图片的 1/n;
                
                //logo显示大小
                int lw = width / scale;
                int lh = height / scale;
                int wx = (width - lw) /2;
                int wy = (height -lh) / 2;
                gs.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 1));
                gs.drawImage(logo, wx, wy, lw, lh, null); // 图片水印文件结束
                gs.dispose();
                qrcode.flush();
            }
            
        }
    
        /**
         * 获取内容二维码图片出流
         *
         * @param content
         * @param size
         * @param imageType
         * @return
         * @throws Exception
         * InputStream
         */
        public static InputStream getQrcodeImageStream(String content, int size, String imageType, String logoPath) throws Exception {
            if (size > 2000) {
                size = 2000;
            }
            BufferedImage image = QRcodeUtils.encode(content, size);
            if(logoPath!=null){
                markLogo(image, logoPath);
            }
            return toInputStream(image, imageType);
        }
        
        public static InputStream getQrcodeImageStream(String content, int size, String imageType) throws Exception {
            return getQrcodeImageStream(content, size, imageType, null);
        }
        
        /**
         * 转成InputStream
         * @param image
         * @param imageType
         * @return
         * @throws IOException
         */
        private static InputStream toInputStream(BufferedImage image, String imageType) throws IOException{
            // BufferedImage 转 InputStream
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            ImageOutputStream imageOutput = ImageIO.createImageOutputStream(byteArrayOutputStream);
    
            // 生成jpg格式
            if (IMAGE_TYPE_JPEG.equals(imageType)) {
                Iterator<ImageWriter> iterator = ImageIO.getImageWritersByFormatName("jpeg");
                ImageWriter imageWriter = iterator.next();
                ImageWriteParam imageWriteParam = imageWriter.getDefaultWriteParam();
                imageWriteParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
                imageWriteParam.setCompressionQuality(1); // 设置质量
                imageWriter.setOutput(imageOutput);
                IIOImage iioImage = new IIOImage(image, null, null);
                imageWriter.write(null, iioImage, imageWriteParam);
                imageWriter.dispose();
            } else {
                ImageIO.write(image, "png", imageOutput);
            }
            return  new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
        }
    
        /**
         * 图片缩放
         */
        private static BufferedImage resize(BufferedImage image, int size) {
            int imageSize = (size % 2) > 0 ? (size + 1) : size;
    
            BufferedImage bufferedImage = new BufferedImage(imageSize, imageSize, BufferedImage.TYPE_INT_RGB);
            Graphics2D gs = bufferedImage.createGraphics();
            gs.setBackground(Color.WHITE);
            gs.clearRect(0, 0, imageSize, imageSize);
            gs.setColor(Color.BLACK);
            gs.fillRect(0, 0, imageSize, imageSize);
            gs.drawImage(image, 0, 0, size, size, null);
            gs.dispose();
            image.flush();
            return bufferedImage;
        }
    
    }
  • 相关阅读:
    http
    Hive与HBase的区别与联系
    超好用python库(Pathlib)
    JS中every()和some()的用法
    kubectl create 和 kubectl apply区别
    Servlet/Tomcat/ Spring 之间的关系
    Android Fragment详解
    vue路由钩子拦截器beforeEach和afterEach及页面路由变化路由监听
    Vue + Webpack 将路由文件分拆为多个文件分别管理
    VUE中常用的几种import(模块、文件)引入方式
  • 原文地址:https://www.cnblogs.com/rubekid/p/4047262.html
Copyright © 2011-2022 走看看