Java技术绘制二维码(可带logo)(QrCode) google zxing

1 篇文章 0 订阅

Java 生成 二维码 (可带logo)(QrCode) google zxing

  1. 主要Maven 依赖。
     
            <!--谷歌二维码 -->
    		<dependency>
    			<groupId>com.google.zxing</groupId>
    			<artifactId>core</artifactId>
    			<version>3.3.0</version>
    		</dependency>
    
  2. 代码片段
    1. 绘制二维码。
       
      1.  生成二维码 BitMatrix 。
      2.  构建一个同尺寸的 BufferedImage 对象。
      3.  双重遍历,将 二维码对象,通过RGB色值保存到 步骤 2 的 BufferedImage的对象里。
      4.  这里 二维码已经生成好了,只需将其导出即可。
      5.  如果需要插入logo的话,设置 好参数会自动居中插入的。
         
        /**
             * 生成二维码
             * 
             * @param linkUrl
             *            二维码真实uri
             * @param hasFrame
             *            是否删除白边
             * @param logoStatus
             *            是否插入logo
             * @param logoPath
             *            logoPath
             * @param logoNeedCompress
             *            是否压缩 logo
             * @throws Exception
             */
            public static BufferedImage createQrCode(String linkUrl, boolean hasFrame, boolean logoStatus, String logoPath,
                boolean logoNeedCompress, int qrCodeSize) throws Exception {
                Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
                hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
                hints.put(EncodeHintType.CHARACTER_SET, CHARSET);
                hints.put(EncodeHintType.MARGIN, 1);
        
                // 二维码的默认尺寸为 172像素
                if (qrCodeSize == 0) {
                    qrCodeSize = QRCODE_SIZE;
                }
                BitMatrix bitMatrix =
                    new MultiFormatWriter().encode(linkUrl, BarcodeFormat.QR_CODE, qrCodeSize, qrCodeSize, hints);
                // 删除白边
                if (hasFrame) {
                    bitMatrix = QrCodeUtil.deleteWhite(bitMatrix);
                }
                int width = bitMatrix.getWidth();
                int height = bitMatrix.getHeight();
                BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
                for (int x = 0; x < width; x++) {
                    for (int y = 0; y < height; y++) {
                        image.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);
                    }
                }
                // 插入二维码 logo
                if (logoStatus) {
                    // 将logo 图片转换为 BufferedImage。
                    BufferedImage logoBufferedImage = QrCodeUtil.imageToBufferedImage(logoPath);
                    // 构建画笔工具,将logo 绘制到二维码上。
                    QrCodeUtil.insertImage(image, logoBufferedImage, logoNeedCompress, hasFrame, qrCodeSize);
                }
        
                return image;
            }

        补充001: 这里提供一些将 图片地址转换为 BufferdImage的 函数。(PS:转为BufferedImage 直接使用 ImageIO 可能会使图片染红。)

         /**
             * image File 转 BufferedImage 直接使用 ImageIO 可能会使图片染红。
             * 
             * @param imaPath
             * @return
             * @throws Exception
             */
            public static BufferedImage imageToBufferedImage(String imaPath) throws Exception {
                if (StringUtils.isNotBlank(imaPath)) {
                    Image src = null;
                    BufferedImage img = null;
                    if (imaPath.startsWith("http")) {
                        src = Toolkit.getDefaultToolkit().getImage(new URL(imaPath));
                    } else {
                        src = Toolkit.getDefaultToolkit().getImage(imaPath);
                    }
                    if (src != null) {
                        img = toBufferedImage(src);
                    }
                    return img;
                } else {
                    return null;
                }
            }
        
        
        /**
             * image File 转 BufferedImage 的依赖函数
             * 
             * @param image
             * @return
             */
            public static BufferedImage toBufferedImage(Image image) {
                if (image instanceof BufferedImage) {
                    return (BufferedImage)image;
                }
                // This code ensures that all the pixels in the image are loaded
                image = new ImageIcon(image).getImage();
                BufferedImage bimage = null;
                GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
                try {
                    int transparency = Transparency.OPAQUE;
                    GraphicsDevice gs = ge.getDefaultScreenDevice();
                    GraphicsConfiguration gc = gs.getDefaultConfiguration();
                    bimage = gc.createCompatibleImage(image.getWidth(null), image.getHeight(null), transparency);
                } catch (HeadlessException e) {
                    // The system does not have a screen
                }
                if (bimage == null) {
                    // Create a buffered image using the default color model
                    int type = BufferedImage.TYPE_INT_RGB;
                    bimage = new BufferedImage(image.getWidth(null), image.getHeight(null), type);
                }
                // Copy image to buffered image
                Graphics g = bimage.createGraphics();
                // Paint the image onto the buffered image
                g.drawImage(image, 0, 0, null);
                g.dispose();
                return bimage;
            }
        
        

        补充002:删除白边的函数。

            /**
             * 删除二维码白边
             * 
             * @param bitMatrix
             * @return
             */
            public static BitMatrix deleteWhite(BitMatrix bitMatrix) {
                int[] rec = bitMatrix.getEnclosingRectangle();
                int resWidth = rec[2] + 1;
                int resHeight = rec[3] + 1;
        
                BitMatrix resMatrix = new BitMatrix(resWidth, resHeight);
                resMatrix.clear();
                for (int i = 0; i < resWidth; i++) {
                    for (int j = 0; j < resHeight; j++) {
                        if (bitMatrix.get(i + rec[0], j + rec[1])) {
                            resMatrix.set(i, j);
                        }
                    }
                }
                return resMatrix;
            }

        补充003:二维码插入logo。
         

        /*
             * 插入LOGO
             * 
             * @param source 二维码图片
             * 
             * @param imgPath LOGO图片地址
             * 
             * @param needCompress 是否缩放
             * 
             * @param frame 是否去白边
             * 
             * @param qrCodeSize 二维码尺寸
             * 
             * @throws Exception
             */
            public static void insertImage(BufferedImage source, BufferedImage logoBufferedImage, boolean needCompress,
                boolean frame, int qrCodeSize) throws Exception {
                if (logoBufferedImage == null) {
                    return;
                }
                int width = logoBufferedImage.getWidth();
                int height = logoBufferedImage.getHeight();
        
                // 缩放
                if (needCompress) {
                    // 缩放的默认尺寸。
                    if (width > WIDTH) {
                        width = WIDTH;
                    }
                    // 缩放的默认尺寸。
                    if (height > HEIGHT) {
                        height = HEIGHT;
                    }
                    // 缩放。
                    logoBufferedImage = Thumbnails.of(logoBufferedImage).size(width, height).asBufferedImage();
                }
                // 插入LOGO
                Graphics2D graph = source.createGraphics();
                int x = 0;
                int y = 0;
                if (frame) {
                    x = (qrCodeSize - width - (height / 2)) / 2;
                    y = (qrCodeSize - height - (height / 2)) / 2;
                } else {
                    x = (qrCodeSize - width) / 2;
                    y = (qrCodeSize - height) / 2;
                }
                graph.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                // logoBufferedImage 是 logo对象 xy 是gs两个边的距离,width height 是 logo的大小
                graph.drawImage(logoBufferedImage, x, y, width, height, null);
                // 二维码logo居中时的边框 圆角的弧度。美观使用。
                Shape shape = new RoundRectangle2D.Float(x, y, width, height, 8, 8);
                // 默认情况下,Graphics绘图类使用的笔画属性是粗细为1个像素的正方形,而Java2D的Graphics2D类可以调用setStroke()方法设置笔画的属性,如改变线条的粗细、虚实和定义线段端点的形状、风格等
                graph.setStroke(new BasicStroke(3f));
                graph.draw(shape);
                graph.dispose();
            }


        补充004: Thumbnails 这里使用了 google 的 压缩工具类。给出pom依赖。
         

                <!-- google 图片处理工具 -->
        		<dependency>
        			<groupId>net.coobird</groupId>
        			<artifactId>thumbnailator</artifactId>
        			<version>0.4.6</version>
        		</dependency>

        补充005:logo 如果为PNG 格式,可能会出现低背 发黑的问题。解决办法建议,还jpg格式。或者~~~、 

        补充006:这个给出一个测试的将BufferedImage 序列化到本地磁盘的函数。
         

         /**
             * 
             * @param bufferImage
             *            画布对象
             * @param scale
             *            缩放 (0.0~1.0)
             * @param outFormat
             *            输出格式(JPG。PNG)
             * @param outPutQuality
             *            输出品质(0.0~1.0)
             * @param pngPath
             *            输出路径
             * @throws Exception
             */
            public static void savePic(BufferedImage bufferImage, double scale, String outFormat, double outPutQuality,
                String pngPath) throws Exception {
                File file = new File(pngPath);
                byte[] picByQuality = QrCodeUtil.compressPicByQuality(bufferImage, 1f);
                ByteArrayInputStream in = new ByteArrayInputStream(picByQuality);
                BufferedImage qualityBufferImage = ImageIO.read(in);
            Thumbnails.of(qualityBufferImage).scale(scale).outputFormat(outFormat).outputQuality(outPutQuality)
                    .toFile(file);
            }

         

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值