java实现二维码的生成与解析

Posted 苏克俊

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java实现二维码的生成与解析相关的知识,希望对你有一定的参考价值。

二维码的生成及解析的低层实现并不简单,我们只需要知道怎么使用就可以了,参考博客:https://blog.csdn.net/jam_fanatic/article/details/82818857

1.maven中jar包引用com.google.zxing;

2.创建QRCodeUtil二维码工具类,使用谷歌提供的帮助类BufferedImageLuminanceSource绘制二维码。

  生成二维码:QRCodeUtil.encode(编码到二维码中的内容, 嵌入二维码的图片路径, 生成的二维码的存放路径, 图片是否进行压缩);

  解析二维码:QRCodeUtil.decode(要解析的二维码的存放路径);

  注意事项:如果你想让别人扫描后跳转一个页面的话,直接在编码的方法里,将编码内容改为一个地址就可以了,这样别人扫描二维码后会自动跳转。二维码存的信息越多,二维码图片也就越复杂,容错率也就越低,识别率也越低,并且二维码能存的内容大小也是有限的(大概500个汉字左右)

  1 package com.gsafety.consumer.util;
  2 
  3 import java.awt.Graphics;
  4 import java.awt.Graphics2D;
  5 import java.awt.Image;
  6 import java.awt.Shape;
  7 import java.awt.geom.RoundRectangle2D;
  8 import java.awt.image.BufferedImage;
  9 import java.io.File;
 10 import java.io.OutputStream;
 11 import java.util.Hashtable;
 12 
 13 import javax.imageio.ImageIO;
 14 
 15 import com.google.zxing.BarcodeFormat;
 16 import com.google.zxing.BinaryBitmap;
 17 import com.google.zxing.DecodeHintType;
 18 import com.google.zxing.EncodeHintType;
 19 import com.google.zxing.MultiFormatReader;
 20 import com.google.zxing.MultiFormatWriter;
 21 import com.google.zxing.Result;
 22 import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
 23 import com.google.zxing.common.BitMatrix;
 24 import com.google.zxing.common.HybridBinarizer;
 25 import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
 26 
 27 import lombok.extern.slf4j.Slf4j;
 28 
 29 /**
 30  *   二维码工具类  
 31  */
 32 @Slf4j
 33 public class QRCodeUtil {
 34     
 35     
 36     
 37     private static final String CHARSET = "utf-8";
 38     private static final String FORMAT_NAME = "JPG";
 39     // 二维码尺寸
 40     private static final int QRCODE_SIZE = 250;
 41     // LOGO宽度
 42     private static final int WIDTH = 50;
 43     // LOGO高度
 44     private static final int HEIGHT = 50;
 45     static SnowflakeIdWorker snowflakeIdWorker = new SnowflakeIdWorker(0,0);
 46     private static BufferedImage createImage(String content, String imgPath, boolean needCompress) throws Exception {
 47         Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
 48         hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
 49         hints.put(EncodeHintType.CHARACTER_SET, CHARSET);
 50         hints.put(EncodeHintType.MARGIN, 0);
 51         BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE,
 52                 hints);
 53         int width = bitMatrix.getWidth();
 54         int height = bitMatrix.getHeight();
 55         BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
 56         for (int x = 0; x < width; x++) {
 57             for (int y = 0; y < height; y++) {
 58                 image.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);
 59             }
 60         }
 61         if (imgPath == null || "".equals(imgPath)) {
 62             return image;
 63         }
 64         // 插入图片
 65         QRCodeUtil.insertImage(image, imgPath, needCompress);
 66         return image;
 67     }
 68     /**
 69      *  插入LOGO          
 70      * @param source    二维码图片    
 71      * @param imgPath  LOGO图片地址    
 72      * @param needCompress   是否压缩    
 73      * @throws Exception    
 74      */
 75     private static void insertImage(BufferedImage source, String imgPath, boolean needCompress) throws Exception {
 76         File file = new File(imgPath);
 77         if (!file.exists()) {
 78             log.info("{}该文件不存在!",imgPath);
 79             return;
 80         }
 81         Image src = ImageIO.read(new File(imgPath));
 82         int width = src.getWidth(null);
 83         int height = src.getHeight(null);
 84         if (needCompress) { // 压缩LOGO
 85             if (width > WIDTH) {
 86                 width = WIDTH;
 87             }
 88             if (height > HEIGHT) {
 89                 height = HEIGHT;
 90             }
 91             Image image = src.getScaledInstance(width, height, Image.SCALE_SMOOTH);
 92             BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
 93             Graphics g = tag.getGraphics();
 94             g.drawImage(image, 0, 0, null); // 绘制缩小后的图
 95             g.dispose();
 96             src = image;
 97         }
 98         // 插入LOGO
 99         Graphics2D graph = source.createGraphics();
100         int x = (QRCODE_SIZE - width) / 2;
101         int y = (QRCODE_SIZE - height) / 2;
102 //        graph.setClip(new RoundRectangle2D.Double(0, 0, width, height, 90, 90));
103         graph.drawImage(src, x, y, width, height, null);
104         Shape shape = new RoundRectangle2D.Float(x, y, width, width, 90,90);
105 //        graph.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
106 //        graph.setStroke(new BasicStroke(-1f));
107         graph.draw(shape);
108         graph.dispose();
109     }
110 
111     /**
112      *    
113      *  生成二维码(内嵌LOGO)   
114      *  @param content   内容    
115      *  @param imgPath   LOGO地址   
116      *  @param destPath  存放目录    
117      *  @param needCompress   是否压缩LOGO    
118      *  @throws Exception    
119      */
120     
121     public static String encode(String content, String imgPath, String destPath, boolean needCompress) throws Exception {
122         BufferedImage image = QRCodeUtil.createImage(content, imgPath, needCompress);
123         mkdirs(destPath);
124         String random = snowflakeIdWorker.nextId();
125         String file = random + ".jpg";
126         ImageIO.write(image, FORMAT_NAME, new File(destPath + "/" + file));
127         return "/consumer_qrcode/"+file;
128     }
129 
130     /**
131      *  当文件夹不存在时,mkdirs会自动创建多层目录,区别于mkdir.(mkdir如果父目录不存在则会抛出异常)    
132      * @author  
133       * @date 2013-12-11 上午10:16:36
134      * @param destPath 存放目录    
135      */
136     public static void mkdirs(String destPath) {
137         File file = new File(destPath);
138         // 当文件夹不存在时,mkdirs会自动创建多层目录,区别于mkdir.(mkdir如果父目录不存在则会抛出异常)
139         if (!file.exists() && !file.isDirectory()) {
140             file.mkdirs();
141         }
142     }
143 
144     /**
145      *     
146      *  生成二维码(内嵌LOGO)         
147      *  @param content  内容    
148      *  @param imgPath  LOGO地址     
149      *  @param destPath  存储地址   
150      *  @throws Exception    
151      */
152     public static void encode(String content, String imgPath, String destPath) throws Exception {
153         QRCodeUtil.encode(content, imgPath, destPath, false);
154     }
155 
156     /**
157      *   
158      *   生成二维码     
159      *  @param content   内容    
160      *  @param destPath  存储地址   
161      *  @param needCompress   是否压缩LOGO    
162      *  @throws Exception    
163      */
164     public static void encode(String content, String destPath, boolean needCompress) throws Exception {
165         QRCodeUtil.encode(content, null, destPath, needCompress);
166     }
167 
168     /**
169      *     
170      *  生成二维码  
171      * @param content   内容    
172      * @param destPath  存储地址    
173      * @throws Exception    
174      */
175     public static void encode(String content, String destPath) throws Exception {
176         QRCodeUtil.encode(content, null, destPath, false);
177     }
178 
179     /**
180      *     
181      *   生成二维码(内嵌LOGO)     
182      *  @param content  内容     
183      *  @param imgPath  LOGO地址    
184      *  @param output   输出流    
185      *  @param needCompress  是否压缩LOGO    
186      *  @throws Exception    
187      */
188     public static void encode(String content, String imgPath, OutputStream output, boolean needCompress)
189             throws Exception {
190         BufferedImage image = QRCodeUtil.createImage(content, imgPath, needCompress);
191         ImageIO.write(image, FORMAT_NAME, output);
192     }
193 
194     /**
195      *    
196      *  生成二维码    
197      *  @param content  内容    
198      *  @param output   输出流
199      *  @throws Exception    
200      */
201     public static void encode(String content, OutputStream output) throws Exception {
202         QRCodeUtil.encode(content, null, output, false);
203     }
204 
205     /**
206      *     
207      *   解析二维码     
208      *   @param file 二维码图片     
209      *   @return    
210      *   @throws
211      * Exception    
212      */
213     public static String decode(File file) throws Exception {
214         BufferedImage image;
215         image = ImageIO.read(file);
216         if (image == null) {
217             return null;
218         }
219         BufferedImageLuminanceSource source = new BufferedImageLuminanceSource(image);
220         BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
221         Result result;
222         Hashtable<DecodeHintType, Object> hints = new Hashtable<DecodeHintType, Object>();
223         // 解码设置编码方式为:utf-8,
224         hints.put(DecodeHintType.CHARACTER_SET, CHARSET);
225         //优化精度
226         hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
227         //复杂模式,开启PURE_BARCODE模式
228         hints.put(DecodeHintType.PURE_BARCODE, Boolean.TRUE);
229         result = new MultiFormatReader().decode(bitmap, hints);
230         
231         String resultStr = result.getText();
232         return resultStr;
233     }
234 
235     /**
236      *    
237      * 
238      *  解析二维码      
239      * @param   path   二维码图片地址    
240      * @return    
241      * @throws  Exception    
242      */
243     public static String decode(String path) throws Exception {
244         return QRCodeUtil.decode(new File(path));
245     }
246     
247     public static void main(String[] args) throws Exception {
248         String text = "爱你一万年"; // 二维码内容
249          String logoPath = "D:\\\\work\\\\二维码.png"; //嵌入二维码的图片路径
250         String destPath = "D:\\\\work";//生成二维码的地址
251         QRCodeUtil.encode(text, logoPath, destPath, false);//生成二维码
252 //        String decode = QRCodeUtil.decode("D:\\\\work/659518998202810368.jpg");//解析二维码
253 //        System.out.println(decode);//答应解析二维码的内容
254     }
255 }
View Code

 

待补充。。。

  微信支付二维码:https://www.cnblogs.com/xu-xiang/p/5797575.html

  支付宝支付二维码:https://www.cnblogs.com/xu-xiang/p/5797643.html

以上是关于java实现二维码的生成与解析的主要内容,如果未能解决你的问题,请参考以下文章

关于java的二维码的生成与解析

java实现二维码的生成与解析

如何使用java开发二维码代码

Java实现二维码的生成与解析

Java实现二维码的生成与解析

java zxing实现二维码生成和解析zxing实现二维码生成和解析