`
frank1998819
  • 浏览: 729405 次
  • 性别: Icon_minigender_1
  • 来自: 南京
文章分类
社区版块
存档分类

Java实现将文本内容、网址链接url,生成二维码与反解析(转)

 
阅读更多

 

  QR码的“QR”是Quick Response 的缩写,是二维码的一种。这种二维码能够快速读取,与之前的条形码相比,QR 码能存储更丰富的信息,包括对文字、URL 地址和其他类型的数据加密。这篇文章将分享如何使用Java实现将文本内容及任意数据生成二维码,扫码就解析显示数据;将网址链接url,生成二维码,扫码即可跳转;并实现二维码数据反解析。

1、下载QR二维码包,zxing.jar 我这里用的是3.0 版本的core包(core-3.0.0.jar)。下载地址:http://download.csdn.net/detail/ljheee/9686956

      ZXing是一个开源Java类库用于解析多种格式的1D/2D条形码。目标是能够对QR编码、Data MatrixUPC1D条形码进行解码。

2、Java工程

      新建一个java工程,将下载好的jar包,core-3.0.0.jar导入工程Bulid Path

      步骤:右击工程,选择“Bulid Path”,选择弹出对话框的“Libraries”,之后选择“add  External JARs”,找到jar文件的存放路径,点击Apply

 

工程代码2个核心Java文件如下:

BufferedImageLuminanceSource.java 

 

[java] view plain copy
 
  1. package com.ljheee.demo;  
  2.   
  3. import java.awt.Graphics2D;  
  4. import java.awt.geom.AffineTransform;  
  5. import java.awt.image.BufferedImage;  
  6. import com.google.zxing.LuminanceSource;  
  7.   
  8. /** 
  9.  * LuminanceSource这类层次结构的目的是不同的位图实现跨平台为请求获得灰度亮度值的标准接口。该接口只提供了抽象方法, 
  10.  * 因此可以生成和旋转创建副本。这是为了确保一个读者不修改原来的亮度源,并让它在一个未知的状态,在链中的其他读者。 
  11.  * https://zxing.github.io/zxing/apidocs/com/google/zxing/LuminanceSource.html 
  12.  * @author ljheee 
  13.  * 
  14.  */  
  15. public class BufferedImageLuminanceSource extends LuminanceSource {  
  16.       
  17.     private final BufferedImage image;  
  18.     private final int left;  
  19.     private final int top;  
  20.   
  21.     public BufferedImageLuminanceSource(BufferedImage image) {  
  22.         this(image, 00, image.getWidth(), image.getHeight());  
  23.     }  
  24.   
  25.     /** 
  26.      * 构造方法 
  27.      * @param image 
  28.      * @param left 
  29.      * @param top 
  30.      * @param width 
  31.      * @param height 
  32.      */  
  33.     public BufferedImageLuminanceSource(BufferedImage image, int left, int top, int width, int height) {  
  34.         super(width, height);  
  35.   
  36.         int sourceWidth = image.getWidth();  
  37.         int sourceHeight = image.getHeight();  
  38.         if (left + width > sourceWidth || top + height > sourceHeight) {  
  39.             throw new IllegalArgumentException("Crop rectangle does not fit within image data.");  
  40.         }  
  41.   
  42.         for (int y = top; y < top + height; y++) {  
  43.             for (int x = left; x < left + width; x++) {  
  44.                 if ((image.getRGB(x, y) & 0xFF000000) == 0) {  
  45.                     image.setRGB(x, y, 0xFFFFFFFF); // = white  
  46.                 }  
  47.             }  
  48.         }  
  49.   
  50.         this.image = new BufferedImage(sourceWidth, sourceHeight, BufferedImage.TYPE_BYTE_GRAY);  
  51.         this.image.getGraphics().drawImage(image, 00null);  
  52.         this.left = left;  
  53.         this.top = top;  
  54.     }  
  55.   
  56.       
  57.     @Override  
  58.     public byte[] getRow(int y, byte[] row) {//从底层平台的位图提取一行(only one row)的亮度数据值  
  59.         if (y < 0 || y >= getHeight()) {  
  60.             throw new IllegalArgumentException("Requested row is outside the image: " + y);  
  61.         }  
  62.         int width = getWidth();  
  63.         if (row == null || row.length < width) {  
  64.             row = new byte[width];  
  65.         }  
  66.         image.getRaster().getDataElements(left, top + y, width, 1, row);  
  67.         return row;  
  68.     }  
  69.   
  70.     @Override  
  71.     public byte[] getMatrix() {///从底层平台的位图提取亮度数据值  
  72.         int width = getWidth();  
  73.         int height = getHeight();  
  74.         int area = width * height;  
  75.         byte[] matrix = new byte[area];  
  76.         image.getRaster().getDataElements(left, top, width, height, matrix);  
  77.         return matrix;  
  78.     }  
  79.   
  80.     @Override  
  81.     public boolean isCropSupported() {//是否支持裁剪  
  82.         return true;  
  83.     }  
  84.   
  85.     /** 
  86.      * 返回一个新的对象与裁剪的图像数据。实现可以保存对原始数据的引用,而不是复制。 
  87.      */  
  88.     @Override  
  89.     public LuminanceSource crop(int left, int top, int width, int height) {  
  90.         return new BufferedImageLuminanceSource(image, this.left + left, this.top + top, width, height);  
  91.     }  
  92.       
  93.     @Override  
  94.     public boolean isRotateSupported() {//是否支持旋转  
  95.         return true;  
  96.     }  
  97.   
  98.     @Override  
  99.     public LuminanceSource rotateCounterClockwise() {//逆时针旋转图像数据的90度,返回一个新的对象。  
  100.         int sourceWidth = image.getWidth();  
  101.         int sourceHeight = image.getHeight();  
  102.         AffineTransform transform = new AffineTransform(0.0, -1.01.00.00.0, sourceWidth);  
  103.         BufferedImage rotatedImage = new BufferedImage(sourceHeight, sourceWidth, BufferedImage.TYPE_BYTE_GRAY);  
  104.         Graphics2D g = rotatedImage.createGraphics();  
  105.         g.drawImage(image, transform, null);  
  106.         g.dispose();  
  107.         int width = getWidth();  
  108.         return new BufferedImageLuminanceSource(rotatedImage, top, sourceWidth - (left + width), getHeight(), width);  
  109.     }  
  110. }  

 

 

QRCodeUtil.java

 

[java] view plain copy
 
  1. package com.ljheee.demo;  
  2.   
  3. import java.awt.BasicStroke;  
  4. import java.awt.Graphics;  
  5. import java.awt.Graphics2D;  
  6. import java.awt.Image;  
  7. import java.awt.Shape;  
  8. import java.awt.geom.RoundRectangle2D;  
  9. import java.awt.image.BufferedImage;  
  10. import java.io.File;  
  11. import java.io.OutputStream;  
  12. import java.util.Hashtable;  
  13. import java.util.Random;  
  14. import javax.imageio.ImageIO;  
  15.   
  16. import com.google.zxing.BarcodeFormat;  
  17. import com.google.zxing.BinaryBitmap;  
  18. import com.google.zxing.DecodeHintType;  
  19. import com.google.zxing.EncodeHintType;  
  20. import com.google.zxing.MultiFormatReader;  
  21. import com.google.zxing.MultiFormatWriter;  
  22. import com.google.zxing.Result;  
  23. import com.google.zxing.common.BitMatrix;  
  24. import com.google.zxing.common.HybridBinarizer;  
  25. import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;  
  26. /** 
  27.  * 二维码生成工具 
  28.  * @author ljheee 
  29.  * 
  30.  */  
  31. public class QRCodeUtil {  
  32.   
  33.     private static final String CHARSET = "utf-8";  
  34.     private static final String FORMAT_NAME = "JPG";  
  35.     // 二维码尺寸  
  36.     private static final int QRCODE_SIZE = 300;  
  37.     // LOGO宽度  
  38.     private static final int WIDTH = 60;  
  39.     // LOGO高度  
  40.     private static final int HEIGHT = 60;  
  41.       
  42.   
  43.     /** 
  44.      * 生成二维码 
  45.      * @param content   源内容 
  46.      * @param imgPath   生成二维码保存的路径 
  47.      * @param needCompress  是否要压缩 
  48.      * @return      返回二维码图片 
  49.      * @throws Exception 
  50.      */  
  51.     private static BufferedImage createImage(String content, String imgPath, boolean needCompress) throws Exception {  
  52.         Hashtable hints = new Hashtable();  
  53.         hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);  
  54.         hints.put(EncodeHintType.CHARACTER_SET, CHARSET);  
  55.         hints.put(EncodeHintType.MARGIN, 1);  
  56.         BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE,  
  57.                 hints);  
  58.         int width = bitMatrix.getWidth();  
  59.         int height = bitMatrix.getHeight();  
  60.         BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);  
  61.         for (int x = 0; x < width; x++) {  
  62.             for (int y = 0; y < height; y++) {  
  63.                 image.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);  
  64.             }  
  65.         }  
  66.         if (imgPath == null || "".equals(imgPath)) {  
  67.             return image;  
  68.         }  
  69.         // 插入图片  
  70.         QRCodeUtil.insertImage(image, imgPath, needCompress);  
  71.         return image;  
  72.     }  
  73.   
  74.     /** 
  75.      * 在生成的二维码中插入图片 
  76.      * @param source 
  77.      * @param imgPath 
  78.      * @param needCompress 
  79.      * @throws Exception 
  80.      */  
  81.     private static void insertImage(BufferedImage source, String imgPath, boolean needCompress) throws Exception {  
  82.         File file = new File(imgPath);  
  83.         if (!file.exists()) {  
  84.             System.err.println("" + imgPath + "   该文件不存在!");  
  85.             return;  
  86.         }  
  87.         Image src = ImageIO.read(new File(imgPath));  
  88.         int width = src.getWidth(null);  
  89.         int height = src.getHeight(null);  
  90.         if (needCompress) { // 压缩LOGO  
  91.             if (width > WIDTH) {  
  92.                 width = WIDTH;  
  93.             }  
  94.             if (height > HEIGHT) {  
  95.                 height = HEIGHT;  
  96.             }  
  97.             Image image = src.getScaledInstance(width, height, Image.SCALE_SMOOTH);  
  98.             BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);  
  99.             Graphics g = tag.getGraphics();  
  100.             g.drawImage(image, 00null); // 绘制缩小后的图  
  101.             g.dispose();  
  102.             src = image;  
  103.         }  
  104.         // 插入LOGO  
  105.         Graphics2D graph = source.createGraphics();  
  106.         int x = (QRCODE_SIZE - width) / 2;  
  107.         int y = (QRCODE_SIZE - height) / 2;  
  108.         graph.drawImage(src, x, y, width, height, null);  
  109.         Shape shape = new RoundRectangle2D.Float(x, y, width, width, 66);  
  110.         graph.setStroke(new BasicStroke(3f));  
  111.         graph.draw(shape);  
  112.         graph.dispose();  
  113.     }  
  114.   
  115.     /** 
  116.      * 生成带logo二维码,并保存到磁盘 
  117.      * @param content 
  118.      * @param imgPath   logo图片 
  119.      * @param destPath 
  120.      * @param needCompress 
  121.      * @throws Exception 
  122.      */  
  123.     public static void encode(String content, String imgPath, String destPath, boolean needCompress) throws Exception {  
  124.         BufferedImage image = QRCodeUtil.createImage(content, imgPath, needCompress);  
  125.         mkdirs(destPath);  
  126.         String file = new Random().nextInt(99999999) + ".jpg";//生成随机文件名  
  127.         ImageIO.write(image, FORMAT_NAME, new File(destPath + "/" + file));  
  128.     }  
  129.   
  130.     public static void mkdirs(String destPath) {  
  131.         File file = new File(destPath);  
  132.         // 当文件夹不存在时,mkdirs会自动创建多层目录,区别于mkdir。(mkdir如果父目录不存在则会抛出异常)  
  133.         if (!file.exists() && !file.isDirectory()) {  
  134.             file.mkdirs();  
  135.         }  
  136.     }  
  137.   
  138.     public static void encode(String content, String imgPath, String destPath) throws Exception {  
  139.         QRCodeUtil.encode(content, imgPath, destPath, false);  
  140.     }  
  141.   
  142.     public static void encode(String content, String destPath, boolean needCompress) throws Exception {  
  143.         QRCodeUtil.encode(content, null, destPath, needCompress);  
  144.     }  
  145.   
  146.     public static void encode(String content, String destPath) throws Exception {  
  147.         QRCodeUtil.encode(content, null, destPath, false);  
  148.     }  
  149.   
  150.     public static void encode(String content, String imgPath, OutputStream output, boolean needCompress)  
  151.             throws Exception {  
  152.         BufferedImage image = QRCodeUtil.createImage(content, imgPath, needCompress);  
  153.         ImageIO.write(image, FORMAT_NAME, output);  
  154.     }  
  155.   
  156.     public static void encode(String content, OutputStream output) throws Exception {  
  157.         QRCodeUtil.encode(content, null, output, false);  
  158.     }  
  159.   
  160.       
  161.     /** 
  162.      * 从二维码中,解析数据 
  163.      * @param file  二维码图片文件 
  164.      * @return   返回从二维码中解析到的数据值 
  165.      * @throws Exception 
  166.      */  
  167.     public static String decode(File file) throws Exception {  
  168.         BufferedImage image;  
  169.         image = ImageIO.read(file);  
  170.         if (image == null) {  
  171.             return null;  
  172.         }  
  173.         BufferedImageLuminanceSource source = new BufferedImageLuminanceSource(image);  
  174.         BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));  
  175.         Result result;  
  176.         Hashtable hints = new Hashtable();  
  177.         hints.put(DecodeHintType.CHARACTER_SET, CHARSET);  
  178.         result = new MultiFormatReader().decode(bitmap, hints);  
  179.         String resultStr = result.getText();  
  180.         return resultStr;  
  181.     }  
  182.   
  183.     public static String decode(String path) throws Exception {  
  184.         return QRCodeUtil.decode(new File(path));  
  185.     }  
  186.   
  187. }  

 

 

工程路径下,有一个11.jpg图片做logo:

 

 

main方法:

 

[java] view plain copy
 
  1. package com.ljheee.app;  
  2. import com.ljheee.demo.QRCodeUtil;  
  3.   
  4. public class App {  
  5.   
  6.     public static void main(String[] args) throws Exception {  
  7.           
  8.         //生成带logo 的二维码   
  9.         String text = "http://my.csdn.net/ljheee";  
  10.         QRCodeUtil.encode(text, "11.JPG""d:/WPS"true);  
  11.           
  12.         //生成不带logo 的二维码  
  13.         String textt = "http://www.baidu.com";  
  14.         QRCodeUtil.encode(textt,"","d:/WPS",true);  
  15.           
  16.         //指定二维码图片,解析返回数据  
  17.         System.out.println(QRCodeUtil.decode("D:/WPS/75040887.jpg"));  
  18.    
  19.     }  
  20. }  

 

 

结果:在指定目录下,生成并保存了二维码。

 

 

扫码后,即可加入我的博客。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics