JAVA中生成二维码图片的方法

Posted 技术宅de小坑

tags:

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

  JAVA中生成、解析二维码的方法并不复杂,使用google的zxing包就可以实现。下面的方法包含了生成二维码、在中间附加logo、添加文字功能,并有解析二维码的方法。

 

一、下载zxing的架包,并导入项目中,如下:

最主要的包都在com.google.zxing.core下。如果是maven项目,maven依赖如下:

1 <dependency>
2   <groupId>com.google.zxing</groupId>
3   <artifactId>core</artifactId>
4   <version>3.3.0</version>
5 </dependency>

 

二、二维码生成,附上代码例子,如下:

  1 public class TestQRcode {
  2     
  3     private static final int BLACK = 0xFF000000;
  4     private static final int WHITE = 0xFFFFFFFF;
  5     private static final int margin = 0;
  6     private static final int LogoPart = 4;
  7     
  8     /**
  9      * 生成二维码矩阵信息
 10      * @param content 二维码图片内容
 11      * @param width 二维码图片宽度
 12      * @param height 二维码图片高度
 13      */
 14     public static BitMatrix setBitMatrix(String content, int width, int height){
 15         Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
 16         hints.put(EncodeHintType.CHARACTER_SET, "UTF-8"); // 指定编码方式,防止中文乱码
 17         hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); // 指定纠错等级
 18         hints.put(EncodeHintType.MARGIN, margin); // 指定二维码四周白色区域大小
 19         BitMatrix bitMatrix = null;
 20         try {
 21             bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints);
 22         } catch (WriterException e) {
 23             e.printStackTrace();
 24         }
 25         return bitMatrix;
 26     }
 27     
 28     /** 
 29      * 将二维码图片输出
 30      * @param matrix 二维码矩阵信息
 31      * @param format 图片格式
 32      * @param outStream 输出流
 33      * @param logoPath logo图片路径
 34      */  
 35     public static void writeToFile(BitMatrix matrix, String format, OutputStream outStream, String logoPath) throws IOException {
 36         BufferedImage image = toBufferedImage(matrix);
 37         // 加入LOGO水印效果
 38         if (StringUtils.isNotBlank(logoPath)) {
 39             image = addLogo(image, logoPath);
 40         }
 41         ImageIO.write(image, format, outStream);
 42     }
 43     
 44     /**
 45      * 生成二维码图片
 46      * @param matrix 二维码矩阵信息
 47      */
 48     public static BufferedImage toBufferedImage(BitMatrix matrix) {
 49         int width = matrix.getWidth();
 50         int height = matrix.getHeight();
 51         BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
 52         for (int x = 0; x < width; x++) {
 53             for (int y = 0; y < height; y++) {
 54                 image.setRGB(x, y, matrix.get(x, y) ? BLACK : WHITE);
 55             }
 56         }
 57         return image;
 58     }
 59     
 60     /**
 61      * 在二维码图片中添加logo图片
 62      * @param image 二维码图片
 63      * @param logoPath logo图片路径
 64      */
 65     public static BufferedImage addLogo(BufferedImage image, String logoPath) throws IOException {
 66         Graphics2D g = image.createGraphics();
 67         BufferedImage logoImage = ImageIO.read(new File(logoPath));
 68         // 计算logo图片大小,可适应长方形图片,根据较短边生成正方形
 69         int width = image.getWidth() < image.getHeight() ? image.getWidth() / LogoPart : image.getHeight() / LogoPart;
 70         int height = width;
 71         // 计算logo图片放置位置
 72         int x = (image.getWidth() - width) / 2;
 73         int y = (image.getHeight() - height) / 2;
 74         // 在二维码图片上绘制logo图片
 75         g.drawImage(logoImage, x, y, width, height, null);
 76         // 绘制logo边框,可选
 77 //        g.drawRoundRect(x, y, logoImage.getWidth(), logoImage.getHeight(), 10, 10);
 78         g.setStroke(new BasicStroke(2)); // 画笔粗细
 79         g.setColor(Color.WHITE); // 边框颜色
 80         g.drawRect(x, y, width, height); // 矩形边框
 81         logoImage.flush();
 82         g.dispose();
 83         return image;
 84     }
 85     
 86     /**
 87      * 为图片添加文字
 88      * @param pressText 文字
 89      * @param newImage 带文字的图片
 90      * @param targetImage 需要添加文字的图片
 91      * @param fontStyle 字体风格
 92      * @param color 字体颜色
 93      * @param fontSize 字体大小
 94      * @param width 图片宽度
 95      * @param height 图片高度
 96      */
 97     public static void pressText(String pressText, String newImage, String targetImage, int fontStyle, Color color, int fontSize, int width, int height) {
 98         // 计算文字开始的位置
 99         // x开始的位置:(图片宽度-字体大小*字的个数)/2
100         int startX = (width-(fontSize*pressText.length()))/2;
101         // y开始的位置:图片高度-(图片高度-图片宽度)/2
102         int startY = height-(height-width)/2 + fontSize;
103         try {
104             File file = new File(targetImage);
105             BufferedImage src = ImageIO.read(file);
106             int imageW = src.getWidth(null);
107             int imageH = src.getHeight(null);
108             BufferedImage image = new BufferedImage(imageW, imageH, BufferedImage.TYPE_INT_RGB);
109             Graphics g = image.createGraphics();
110             g.drawImage(src, 0, 0, imageW, imageH, null);
111             g.setColor(color);
112             g.setFont(new Font(null, fontStyle, fontSize));
113             g.drawString(pressText, startX, startY);
114             g.dispose();
115             FileOutputStream out = new FileOutputStream(newImage);
116             ImageIO.write(image, "png", out);
117             out.close();
118         } catch (Exception e) {
119             e.printStackTrace();
120         }
121     }
122     
123     public static void main(String[] args) {
124         String content = "http://www.baidu.com";
125         String logoPath = "C:/logo.png";
126         String format = "jpg";
127         int width = 180;
128         int height = 220;
129         BitMatrix bitMatrix = setBitMatrix(content, width, height);
130         // 可通过输出流输出到页面,也可直接保存到文件
131         OutputStream outStream = null;
132         String path = "c:/qr"+new Date().getTime()+".png";
133         try {
134             outStream = new FileOutputStream(new File(path));        
135             writeToFile(bitMatrix, format, outStream, logoPath);
136             outStream.close();
137         } catch (Exception e) {
138             e.printStackTrace();
139         }
140         // 添加文字效果
141         int fontSize = 12; // 字体大小
142         int fontStyle = 1; // 字体风格
143         String text = "测试二维码";
144         String withTextPath = "c:/text"+new Date().getTime()+".png";
145         pressText(text, withTextPath, path, fontStyle, Color.BLUE, fontSize, width, height);
146     }
147 }

 

三、生成效果如下:

  代码注释比较详细,就不多解释啦,大家可以根据自己的需求进行调整。

PS:

1、如果想生成带文字的二维码,记得要用长方形图片,为文字预留空间。

2、要生成带logo的二维码要注意遮挡率的问题,setBitMatrix()方法中ErrorCorrectionLevel.H这个纠错等级参数决定了二维码可被遮挡率。对应如下:

L水平 7%的字码可被修正
M水平 15%的字码可被修正
Q水平 25%的字码可被修正
H水平 30%的字码可被修正

 

 

 

 

 

四、二维码解析,附上代码例子,如下:

 1     /**
 2      * 解析二维码图片
 3      * @param filePath 图片路径
 4      */
 5     public static String decodeQR(String filePath) {
 6         if ("".equalsIgnoreCase(filePath) && filePath.length() == 0) {
 7             return "二维码图片不存在!";
 8         }
 9         String content = "";
10         EnumMap<DecodeHintType, Object> hints = new EnumMap<DecodeHintType, Object>(DecodeHintType.class);
11         hints.put(DecodeHintType.CHARACTER_SET, "UTF-8"); // 指定编码方式,防止中文乱码
12         try {
13             BufferedImage image = ImageIO.read(new FileInputStream(filePath));
14             LuminanceSource source = new BufferedImageLuminanceSource(image);
15             Binarizer binarizer = new HybridBinarizer(source);
16             BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer);
17             MultiFormatReader reader = new MultiFormatReader();
18             Result result = reader.decode(binaryBitmap, hints);
19             content = result.getText();
20         } catch (Exception e) {
21             e.printStackTrace();
22         }
23         return content;
24     }

  可以从二维码图片中解析出具体的内容。

 

以上是关于JAVA中生成二维码图片的方法的主要内容,如果未能解决你的问题,请参考以下文章

为什么我不能在此片段中生成唯一对象数组?

vue项目中生成二维码

C# 代码生成二维码方法及代码示例(QRCoder)

如何在JSP网页中生成动态图表

使用在另一个片段(NPE)中生成的值设置片段的 TextView [重复]

vue环境中生成二维码