二维码工具类

二维码工具类,提供多种生成二维码、解析二维码的方法,包括中间logo的二维码等方法。

 

源码如下:(点击下载 - QrcodeUtils.javaMatrixToImageWriterEx.javaMatrixToLogoImageConfig.javacommons-io-2.4.jarcommons-lang-2.6.jarslf4j-api-1.7.12.jarjavase-3.1.0.jarcore-3.1.0.jar 、FolderUtils.java)

 

QrcodeUtils.java 源码:

  1 import java.awt.Color;
  2 import java.awt.image.BufferedImage;
  3 import java.io.BufferedInputStream;
  4 import java.io.BufferedOutputStream;
  5 import java.io.File;
  6 import java.io.FileInputStream;
  7 import java.io.FileNotFoundException;
  8 import java.io.FileOutputStream;
  9 import java.io.IOException;
 10 import java.io.InputStream;
 11 import java.io.OutputStream;
 12 import java.net.URL;
 13 import java.util.HashMap;
 14 import java.util.Map;
 15 import java.util.UUID;
 16 import javax.imageio.ImageIO;
 17 import org.apache.commons.io.FilenameUtils;
 18 import org.apache.commons.io.IOUtils;
 19 import org.apache.commons.lang.ArrayUtils;
 20 import org.apache.commons.lang.StringUtils;
 21 import org.apache.commons.lang.SystemUtils;
 22 import org.slf4j.Logger;
 23 import org.slf4j.LoggerFactory;
 24 import com.google.zxing.BinaryBitmap;
 25 import com.google.zxing.DecodeHintType;
 26 import com.google.zxing.LuminanceSource;
 27 import com.google.zxing.MultiFormatReader;
 28 import com.google.zxing.Reader;
 29 import com.google.zxing.ReaderException;
 30 import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
 31 import com.google.zxing.client.j2se.MatrixToImageWriter;
 32 import com.google.zxing.common.BitMatrix;
 33 import com.google.zxing.common.HybridBinarizer;
 34 import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
 35 
 36 /**
 37  * 二维码工具类
 38  * 
 39  */
 40 public class QrcodeUtils {
 41 
 42     private static final transient Logger LOGGER = LoggerFactory.getLogger(QrcodeUtils.class);
 43 
 44     private static transient String DEFAULT_FORMAT = "jpg";
 45     private static transient int DEFAULT_WIDTH = 200;
 46     private static transient int DEFAULT_HEIGHT = 200;
 47 
 48     static {
 49         try {
 50             final String[] foo = new String[] { "240", "240" };
 51             final String format = "jpg";
 52             if (StringUtils.isNotBlank(format)) {
 53                 DEFAULT_FORMAT = StringUtils.strip(format).toLowerCase();
 54             }
 55 
 56             if (ArrayUtils.isNotEmpty(foo) && foo.length == 2) {
 57                 Integer tmpWidth = Integer.valueOf(foo[0]);
 58                 Integer tmpHeight = Integer.valueOf(foo[1]);
 59                 if (tmpWidth > 0 && tmpHeight > 0) {
 60                     DEFAULT_WIDTH = tmpWidth;
 61                     DEFAULT_HEIGHT = tmpHeight;
 62                 } else {
 63                     LOGGER.warn("qrcode size must be lager than zero.");
 64                 }
 65             }
 66         } catch (Throwable e) {
 67             LOGGER.warn("read default qrcode size config error: ", e);
 68         }
 69     }
 70 
 71     /**
 72      * 生成二维码(无中间logo)
 73      * 
 74      * @param content
 75      *            二维码文本内容
 76      * @param destFile
 77      *            输出文件
 78      */
 79     public static final void gen(final String content, File destFile) throws Exception {
 80         gen(content, destFile, DEFAULT_WIDTH, DEFAULT_HEIGHT);
 81     }
 82 
 83     /**
 84      * 生成二维码
 85      * 
 86      * @param content
 87      *            二维码文本内容
 88      * @param destFile
 89      *            目的文件
 90      * @param logoFile
 91      *            中间logo文件
 92      * 
 93      */
 94     public static final void gen(final String content, final File destFile, final File logoFile) throws Exception {
 95         gen(content, destFile, logoFile, DEFAULT_WIDTH, DEFAULT_HEIGHT);
 96     }
 97 
 98     /**
 99      * 生成二维码
100      * 
101      * @param content
102      *            二维码文本内容
103      * @param destFile
104      *            目的文件
105      * @param logoFile
106      *            中间logo文件
107      * @param width
108      *            宽度
109      * @param height
110      *            高度
111      */
112     public static final void gen(final String content, final File destFile,
113             final File logoFile, int width, int height) throws Exception {
114         FolderUtils.mkdirs(destFile.getParent());
115         OutputStream output = null;
116         InputStream input = null;
117         try {
118             output = new BufferedOutputStream(new FileOutputStream(destFile));
119             if (logoFile != null && logoFile.exists() && logoFile.isFile()) {
120                 input = new BufferedInputStream(new FileInputStream(logoFile));
121             }
122             gen(content, output, input, width, height);
123         } catch (FileNotFoundException e) {
124             e.printStackTrace();
125             throw new Exception(e);
126         } finally {
127             IOUtils.closeQuietly(output);
128             IOUtils.closeQuietly(input);
129         }
130     }
131 
132     /**
133      * 生成二维码(无中间logo)
134      * 
135      * @param content
136      *            二维码文本内容
137      * @param destFile
138      *            输出文件
139      * @param width
140      *            宽度
141      * @param height
142      *            高度
143      */
144     public static final void gen(final String content, File destFile, int width, int height) throws Exception {
145         FolderUtils.mkdirs(destFile.getParent());
146         OutputStream output = null;
147         try {
148             output = new BufferedOutputStream(new FileOutputStream(destFile));
149             gen(content, output, width, height);
150         } catch (FileNotFoundException e) {
151             e.printStackTrace();
152             throw new Exception(e);
153         } catch (Exception e) {
154             throw e;
155         } finally {
156             IOUtils.closeQuietly(output);
157         }
158     }
159 
160     /**
161      * 生成二维码
162      * 
163      * @param content
164      *            二维码文本内容
165      * @param output
166      *            输出流
167      */
168     public static final void gen(final String content, final OutputStream output) throws Exception {
169         gen(content, output, DEFAULT_WIDTH, DEFAULT_HEIGHT);
170     }
171 
172     /**
173      * 生成二维码
174      * 
175      * @param content
176      *            二维码文本内容
177      * @param output
178      *            输出流
179      * @param logoInput
180      *            中间logo输入流,为空时中间无logo
181      */
182     public static final void gen(final String content,
183             final OutputStream output, final InputStream logoInput) throws Exception {
184         gen(content, output, logoInput, DEFAULT_WIDTH, DEFAULT_HEIGHT);
185     }
186 
187     /**
188      * 生成二维码
189      * 
190      * @param content
191      *            二维码文本内容
192      * @param output
193      *            输出流
194      * @param logoInput
195      *            中间logo输入流,为空时中间无logo
196      * @param width
197      *            宽度
198      * @param height
199      *            高度
200      */
201     public static final void gen(final String content,
202             final OutputStream output, final InputStream logoInput, int width, int height) throws Exception {
203         gen(content, output, logoInput, width, height, ErrorCorrectionLevel.M);
204     }
205 
206     /**
207      * 生成二维码
208      * 
209      * @param content
210      *            二维码文本内容
211      * @param output
212      *            输出流
213      * @param logoInput
214      *            中间logo输入流,为空时中间无logo
215      * @param width
216      *            宽度
217      * @param height
218      *            高度
219      * @param errorCorrectionLevel
220      *            容错级别
221      */
222     public static final void gen(final String content,
223             final OutputStream output, final InputStream logoInput, int width,
224             int height, ErrorCorrectionLevel errorCorrectionLevel) throws Exception {
225         if (StringUtils.isEmpty(content)) {
226             throw new IllegalArgumentException("qr code content cannot be empty.");
227         }
228         if (output == null) {
229             throw new IllegalArgumentException("qr code output stream cannot be null.");
230         }
231 
232         final BitMatrix matrix = MatrixToImageWriterEx.createQRCode(content, width, height, errorCorrectionLevel);
233 
234         if (logoInput == null) {
235             try {
236                 MatrixToImageWriter.writeToStream(matrix, DEFAULT_FORMAT, output);
237                 return;
238             } catch (IOException e) {
239                 e.printStackTrace();
240                 throw new Exception(e);
241             }
242         }
243 
244         final MatrixToLogoImageConfig logoConfig = new MatrixToLogoImageConfig(Color.BLUE, 4);
245 
246         final String destPath = FilenameUtils.normalizeNoEndSeparator(SystemUtils.getJavaIoTmpDir()
247                         + File.separator + UUID.randomUUID().toString()
248                         + ".tmp");
249         InputStream tmpInput = null;
250         final File destFile = new File(destPath);
251         try {
252             MatrixToImageWriterEx.writeToFile(matrix, DEFAULT_FORMAT, destPath, logoInput, logoConfig);
253             tmpInput = new BufferedInputStream(new FileInputStream(destFile));
254             IOUtils.copy(tmpInput, output);
255         } catch (IOException e) {
256             e.printStackTrace();
257             throw new Exception(e);
258         } finally {
259             IOUtils.closeQuietly(tmpInput);
260             destFile.delete();
261         }
262     }
263 
264     /**
265      * 生成二维码
266      * 
267      * @param content
268      *            二维码文本内容
269      * @param output
270      *            输出流
271      * @param width
272      *            宽度
273      * @param height
274      *            高度
275      */
276     public static final void gen(final String content, final OutputStream output, int width, int height) throws Exception {
277         gen(content, output, null, width, height);
278     }
279 
280     /**
281      * 生成二维码
282      * 
283      * @param content
284      *            二维码文本内容
285      * @param destPath
286      *            输出文件路径
287      */
288     public static final void gen(final String content, final String destPath) throws Exception {
289         gen(content, destPath, DEFAULT_WIDTH, DEFAULT_HEIGHT);
290     }
291 
292     /**
293      * 生成二维码
294      * 
295      * @param content
296      *            二维码文本内容
297      * @param destPath
298      *            输出文件路径
299      * @param width
300      *            宽度
301      * @param height
302      *            高度
303      */
304     public static final void gen(final String content, final String destPath, int width, int height) throws Exception {
305         gen(content, new File(destPath), width, height);
306     }
307 
308     /**
309      * 生成二维码
310      * 
311      * @param content
312      *            二维码文本内容
313      * @param destPath
314      *            目的文件路径
315      * @param logoPath
316      *            中间logo文件路径
317      */
318     public static final void gen(final String content, final String destPath, final String logoPath) throws Exception {
319         gen(content, destPath, logoPath, DEFAULT_WIDTH, DEFAULT_HEIGHT);
320     }
321 
322     /**
323      * 生成二维码
324      * 
325      * @param content
326      *            二维码文本内容
327      * @param destPath
328      *            目的文件路径
329      * @param logoPath
330      *            中间logo文件路径
331      * @param width
332      *            宽度
333      * @param height
334      *            高度
335      */
336     public static final void gen(final String content, final String destPath,
337             final String logoPath, int width, int height) throws Exception {
338         File foo = new File(destPath);
339         File bar = new File(logoPath);
340         gen(content, foo, bar, width, height);
341     }
342 
343     /**
344      * 解析二维码
345      * 
346      * @param input
347      *            二维码输入流
348      */
349     public static final String parse(InputStream input) throws Exception {
350         Reader reader = null;
351         BufferedImage image;
352         try {
353             image = ImageIO.read(input);
354             if (image == null) {
355                 throw new Exception("cannot read image from inputstream.");
356             }
357             final LuminanceSource source = new BufferedImageLuminanceSource(image);
358             final BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
359             final Map<DecodeHintType, String> hints = new HashMap<DecodeHintType, String>();
360             hints.put(DecodeHintType.CHARACTER_SET, "utf-8");
361             // 解码设置编码方式为:utf-8,
362             reader = new MultiFormatReader();
363             return reader.decode(bitmap, hints).getText();
364         } catch (IOException e) {
365             e.printStackTrace();
366             throw new Exception("parse QR code error: ", e);
367         } catch (ReaderException e) {
368             e.printStackTrace();
369             throw new Exception("parse QR code error: ", e);
370         }
371     }
372 
373     /**
374      * 解析二维码
375      * 
376      * @param url
377      *            二维码url
378      */
379     public static final String parse(URL url) throws Exception {
380         InputStream in = null;
381         try {
382             in = url.openStream();
383             return parse(in);
384         } catch (IOException e) {
385             e.printStackTrace();
386             throw new Exception("parse QR code error: ", e);
387         } finally {
388             IOUtils.closeQuietly(in);
389         }
390     }
391 
392     /**
393      * 解析二维码
394      * 
395      * @param file
396      *            二维码图片文件
397      */
398     public static final String parse(File file) throws Exception {
399         InputStream in = null;
400         try {
401             in = new BufferedInputStream(new FileInputStream(file));
402             return parse(in);
403         } catch (FileNotFoundException e) {
404             e.printStackTrace();
405             throw new Exception("parse QR code error: ", e);
406         } finally {
407             IOUtils.closeQuietly(in);
408         }
409     }
410 
411     /**
412      * 解析二维码
413      * 
414      * @param filePath
415      *            二维码图片文件路径
416      */
417     public static final String parse(String filePath) throws Exception {
418         InputStream in = null;
419         try {
420             in = new BufferedInputStream(new FileInputStream(filePath));
421             return parse(in);
422         } catch (FileNotFoundException e) {
423             e.printStackTrace();
424             throw new Exception("parse QR code error: ", e);
425         } finally {
426             IOUtils.closeQuietly(in);
427         }
428     }
429 }
430 
431 
432 
433 
434 MatrixToImageWriterEx.java 源码:
435 
436 import java.awt.BasicStroke;
437 import java.awt.Graphics2D;
438 import java.awt.image.BufferedImage;
439 import java.io.BufferedInputStream;
440 import java.io.File;
441 import java.io.FileInputStream;
442 import java.io.IOException;
443 import java.io.InputStream;
444 import java.util.Hashtable;
445 import javax.imageio.ImageIO;
446 import org.apache.commons.io.IOUtils;
447 import com.google.zxing.BarcodeFormat;
448 import com.google.zxing.EncodeHintType;
449 import com.google.zxing.MultiFormatWriter;
450 import com.google.zxing.WriterException;
451 import com.google.zxing.client.j2se.MatrixToImageConfig;
452 import com.google.zxing.client.j2se.MatrixToImageWriter;
453 import com.google.zxing.common.BitMatrix;
454 import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
455 
456 class MatrixToImageWriterEx {
457 
458     private static final MatrixToLogoImageConfig DEFAULT_CONFIG = new MatrixToLogoImageConfig();
459 
460     /**
461      * 根据内容生成二维码数据
462      * 
463      * @param content
464      *            二维码文字内容[为了信息安全性,一般都要先进行数据加密]
465      * @param width
466      *            二维码照片宽度
467      * @param height
468      *            二维码照片高度
469      * @param errorCorrectionLevel
470      *            纠错等级
471      * @return a {@link com.google.zxing.common.BitMatrix} object.
472      * @since 0.0.7
473      */
474     public static BitMatrix createQRCode(String content, int width, int height,
475             ErrorCorrectionLevel errorCorrectionLevel) {
476         Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
477         // 设置字符编码
478         hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
479         // 指定纠错等级
480         hints.put(EncodeHintType.ERROR_CORRECTION, errorCorrectionLevel);
481         BitMatrix matrix = null;
482         try {
483             matrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints);
484         } catch (WriterException e) {
485             e.printStackTrace();
486         }
487         return matrix;
488     }
489 
490     /**
491      * 根据内容生成二维码数据
492      * 
493      * @param content
494      *            二维码文字内容[为了信息安全性,一般都要先进行数据加密]
495      * @param width
496      *            二维码照片宽度
497      * @param height
498      *            二维码照片高度
499      * @return a {@link com.google.zxing.common.BitMatrix} object.
500      * @since 0.0.7
501      */
502     public static BitMatrix createQRCode(String content, int width, int height) {
503         return createQRCode(content, width, height, ErrorCorrectionLevel.H);
504     }
505 
506     /**
507      * 写入二维码、以及将照片logo写入二维码中
508      * 
509      * @param matrix
510      *            要写入的二维码
511      * @param format
512      *            二维码照片格式
513      * @param imagePath
514      *            二维码照片保存路径
515      * @param logoPath
516      *            logo路径
517      * @throws java.io.IOException
518      *             if any.
519      * @since 0.0.7
520      */
521     public static void writeToFile(BitMatrix matrix, String format,
522             String imagePath, String logoPath) throws IOException {
523         InputStream input = null;
524         try {
525             input = new BufferedInputStream(new FileInputStream(logoPath));
526             writeToFile(matrix, format, imagePath, input);
527         } catch (IOException e) {
528             throw e;
529         } finally {
530             IOUtils.closeQuietly(input);
531         }
532 
533     }
534 
535     /**
536      * <p>
537      * writeToFile.
538      * </p>
539      * 
540      * @param matrix
541      *            a {@link com.google.zxing.common.BitMatrix} object.
542      * @param format
543      *            a {@link java.lang.String} object.
544      * @param imagePath
545      *            a {@link java.lang.String} object.
546      * @param logoInputStream
547      *            a {@link java.io.InputStream} object.
548      * @throws java.io.IOException
549      *             if any.
550      * @since 0.0.7
551      */
552     public static void writeToFile(BitMatrix matrix, String format,
553             String imagePath, InputStream logoInputStream) throws IOException {
554         MatrixToImageWriter.writeToPath(matrix, format, new File(imagePath).toPath(), new MatrixToImageConfig());
555         // 添加logo图片, 此处一定需要重新进行读取,而不能直接使用二维码的BufferedImage 对象
556         BufferedImage img = ImageIO.read(new File(imagePath));
557         MatrixToImageWriterEx.overlapImage(img, format, imagePath, logoInputStream, DEFAULT_CONFIG);
558     }
559 
560     /**
561      * 写入二维码、以及将照片logo写入二维码中
562      * 
563      * @param matrix
564      *            要写入的二维码
565      * @param format
566      *            二维码照片格式
567      * @param imagePath
568      *            二维码照片保存路径
569      * @param logoPath
570      *            logo路径
571      * @param logoConfig
572      *            logo配置对象
573      * @throws java.io.IOException
574      *             if any.
575      * @since 0.0.7
576      */
577     public static void writeToFile(BitMatrix matrix, String format, String imagePath, InputStream logoPath,
578             MatrixToLogoImageConfig logoConfig) throws IOException {
579         MatrixToImageWriter.writeToPath(matrix, format, new File(imagePath).toPath(), new MatrixToImageConfig());
580         // 添加logo图片, 此处一定需要重新进行读取,而不能直接使用二维码的BufferedImage 对象
581         BufferedImage img = ImageIO.read(new File(imagePath));
582         MatrixToImageWriterEx.overlapImage(img, format, imagePath, logoPath, logoConfig);
583     }
584 
585     /**
586      * 将照片logo添加到二维码中间
587      * 
588      * @param image
589      *            生成的二维码照片对象
590      * @param imagePath
591      *            照片保存路径
592      * @param imagePath
593      *            照片保存路径
594      * @param imagePath
595      *            照片保存路径
596      * @param imagePath
597      *            照片保存路径
598      * @param imagePath
599      *            照片保存路径
600      * @param imagePath
601      *            照片保存路径
602      * @param logoInputStream
603      *            logo输入流
604      * @param formate
605      *            照片格式
606      * @param logoConfig
607      *            a {@link cn.yicha.commons.qrcode.MatrixToLogoImageConfig}
608      *            object.
609      * @since 0.0.7
610      */
611     public static void overlapImage(BufferedImage image, String formate,
612             String imagePath, InputStream logoInputStream,
613             MatrixToLogoImageConfig logoConfig) {
614         try {
615             BufferedImage logo = ImageIO.read(logoInputStream);
616             Graphics2D g = image.createGraphics();
617             // 考虑到logo照片贴到二维码中,建议大小不要超过二维码的1/5;
618             int width = image.getWidth() / logoConfig.getLogoPart();
619             int height = image.getHeight() / logoConfig.getLogoPart();
620             // logo起始位置,此目的是为logo居中显示
621             int x = (image.getWidth() - width) / 2;
622             int y = (image.getHeight() - height) / 2;
623             // 绘制图
624             g.drawImage(logo, x, y, width, height, null);
625 
626             // 给logo画边框
627             // 构造一个具有指定线条宽度以及 cap 和 join 风格的默认值的实心 BasicStroke
628             g.setStroke(new BasicStroke(logoConfig.getBorder()));
629             g.setColor(logoConfig.getBorderColor());
630             g.drawRect(x, y, width, height);
631 
632             g.dispose();
633             // 写入logo照片到二维码
634             ImageIO.write(image, formate, new File(imagePath));
635         } catch (Exception e) {
636             e.printStackTrace();
637         }
638     }
639 
640 }

MatrixToLogoImageConfig.java 源码:

 1 import java.awt.Color;
 2 
 3 class MatrixToLogoImageConfig {
 4     // logo默认边框颜色
 5     /** Constant <code>DEFAULT_BORDERCOLOR</code> */
 6     public static final Color DEFAULT_BORDERCOLOR = Color.RED;
 7     // logo默认边框宽度
 8     /** Constant <code>DEFAULT_BORDER=2</code> */
 9     public static final int DEFAULT_BORDER = 2;
10     // logo大小默认为照片的1/5
11     /** Constant <code>DEFAULT_LOGOPART=5</code> */
12     public static final int DEFAULT_LOGOPART = 5;
13 
14     private final int border = DEFAULT_BORDER;
15     private final Color borderColor;
16     private final int logoPart;
17 
18     /**
19      * Creates a default config with on color {@link #BLACK} and off color
20      * {@link #WHITE}, generating normal black-on-white barcodes.
21      * 
22      * @since 0.0.7
23      */
24     public MatrixToLogoImageConfig() {
25         this(DEFAULT_BORDERCOLOR, DEFAULT_LOGOPART);
26     }
27 
28     /**
29      * <p>
30      * Constructor for MatrixToLogoImageConfig.
31      * </p>
32      * 
33      * @param borderColor
34      *            a {@link java.awt.Color} object.
35      * @param logoPart
36      *            a int.
37      * @since 0.0.7
38      */
39     public MatrixToLogoImageConfig(Color borderColor, int logoPart) {
40         this.borderColor = borderColor;
41         this.logoPart = logoPart;
42     }
43 
44     /**
45      * <p>
46      * Getter for the field <code>borderColor</code>.
47      * </p>
48      * 
49      * @return a {@link java.awt.Color} object.
50      * @since 0.0.7
51      */
52     public Color getBorderColor() {
53         return borderColor;
54     }
55 
56     /**
57      * <p>
58      * Getter for the field <code>border</code>.
59      * </p>
60      * 
61      * @return a int.
62      * @since 0.0.7
63      */
64     public int getBorder() {
65         return border;
66     }
67 
68     /**
69      * <p>
70      * Getter for the field <code>logoPart</code>.
71      * </p>
72      * 
73      * @return a int.
74      * @since 0.0.7
75      */
76     public int getLogoPart() {
77         return logoPart;
78     }
79 }
原文地址:https://www.cnblogs.com/zhoubang521/p/5200118.html