目录
一、Zxing介绍
ZXing是一个开放源码的,用Java实现的多种格式的1D/2D条码图像处理库,它包含了联系到其他语言的端口。Zxing可以实现使用手机的内置的摄像头完成条形码的扫描及解码。
二、关键类及方法说明
Zxing将生成图形编码的方式抽象成了一个类com.google.zxing.Writer
, 在实现类中不仅仅生成二维码,还可以生成条形码等其他图形编码。
我们实际开发中,可以选择Writer类的实现类MultiFormatWriter。
参数
参数 | 说明 |
---|---|
String contents | 编码的内容 |
BarcodeFormat format | 编码的方式(二维码、条形码...) |
int width | 生成的码的宽度 |
int height | 生成的码的高度 |
Map<EncodeHintType,?> hints | 编码时额外的参数 |
额外参数说明
编码额外的参数是以一个Map<EncodeHintType, ?>
存在的,key为EncodeHintType
枚举,那么可以看到所有的参数类型。
参数 | 说明 |
---|---|
ERROR_CORRECTION | 容错率,指定容错等级,例如二维码中使用的ErrorCorrectionLevel , Aztec使用Integer |
CHARACTER_SET | 编码集 |
DATA_MATRIX_SHAPE | 指定生成的数据矩阵的形状,类型为SymbolShapeHint |
MARGIN | 生成条码的时候使用,指定边距,单位像素,受格式的影响。类型Integer, 或String代表的数字类型 |
PDF417_COMPACT | 指定是否使用PDF417紧凑模式(具体含义不懂)类型Boolean |
PDF417_COMPACTION | 指定PDF417的紧凑类型 |
PDF417_DIMENSIONS | 指定PDF417的最大最小行列数 |
AZTEC_LAYERS | aztec编码相关,不理解 |
QR_VERSION | 指定二维码版本,版本越高越复杂,反而不容易解析 |
从上面的参数表格可以看出,适用于二维码的有:ERROR_CORRECTION
, CHARACTER_SET
, MARGIN
, QR_VERSION。
参数 | 使用说明 |
---|---|
ERROR_CORRECTION | 分为四个等级:L/M/Q/H, 等级越高,容错率越高,识别速度降低。例如一个角被损坏,容错率高的也许能够识别出来。通常为H |
CHARACTER_SET | 编码集,通常有中文,设置为 utf-8 |
MARGIN | 默认为4, 实际效果并不是填写的值,一般默认值就行 |
QR_VERSION | 通常不变,设置越高,反而不好用 |
代码演示
下面是最简化的生成二维码的代码:
/**
* 生成二维码
*
* @param contents 二维码内容
* @return 二维码的描述对象 BitMatrix
* @throws WriterException 编码时出错
*/
private BitMatrix encode(String contents) throws WriterException {
final Map<EncodeHintType, Object> hints = new HashMap<>();
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
return new QRCodeWriter().encode(contents, BarcodeFormat.QR_CODE, 320, 320, hints);
}
没错,就是这么简单。但是我们得到的是一个BitMatrix
, 如果需要显示出来则要根据不同平台来处理。
BitMatrix 转换成图片
首先明确Java SE平台和Android平台的区别:Android平台移除关于swing部分的代码,所以如果SE平台使用到这部分代码,Android平台则不能用,不幸的是,官方的代码恰恰用到了这部分。
明确另外一个概念:图片在一个平台的存在形式有两种,内存和文件。虽然文件在不同平台通用,但是转换成文件的过程却不是通用的。如Android中将Bitmap
转换成图片文件,SE中将BufferedImage
转换成图片文件。所以实际上,最重要的是将BitMatrix
转换成在内存中图片的存在形式。
Java SE平台
将BitMatrix
转换成BufferedImage
.
在官方提供的zxing-javase包中已经有了相应的方法。下面是示例代码:
BufferedImage bufferedImage = MatrixToImageWriter.toBufferedImage(bitMatrix, new MatrixToImageConfig(Color.BLACK.getRGB(), Color.WHITE.getRGB()));
其他就不过多介绍了,下面我们实际代码完整演示一遍。
三、完整代码演示
3.1 导入依赖
<!-- zxing生成二维码 -->
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.3.3</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.3.3</version>
</dependency>
3.2 代码示例
package com.pink.jucstudy.utils;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Map;
public class CodeX {
/**
* 1. 设置二维码的参数
* 2. 生成二维码
* 3. 将二维码导出
*/
/**
*
* @param content 编码的内容
* @param path 本地保存的路径
* @return
*/
public boolean createCode(String content,String path){
// 1 设置基本参数
int width = 300;
int height = 300;
String format = "png";//保存图片的格式,注意:不同平台可能有它的图片格式要求
// 2 设置额外参数,一定要保存到map集合中
Map map = new HashMap();
// 2.1 设置容错率
// 其中key键就是EncodeHintType.ERROR_CORRECTION
// value值也是枚举类ErrorCorrectionLevel.M,可自行选择容错率等级l>M>Q>H
// 当等级越高,扫描所需的时间越高,但是准确率越高。
map.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
// 2.2 生成条码的时候使用,指定边距,单位像素
map.put(EncodeHintType.MARGIN,2);
// 2.3 设置字符集
map.put(EncodeHintType.CHARACTER_SET,"utf-8");
// 3 生成二维码
// MultiFormatWriter继承了Writer
// 通过该对象的encode方法即可生成二维码BitMatrix
// 该方法形参分别对应了:
// 第一个参数为编码的内容,
// 第二个参数选择生成编码为二维码
// 第三第四分别对应编码的宽度和高度
// 第五个参数为对应的额外参数
// 然后需要try、catch抛出异常
try {
BitMatrix encode = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height, map);
// 4 导出到本地
File file = new File(path);
Path path1 = file.toPath();
System.out.println(path1);
MatrixToImageWriter.writeToPath(encode,format,path1);
return true;
} catch (WriterException | IOException e) {
e.printStackTrace();
}
return false;
}
public static void main(String[] args) {
boolean code = new CodeX().createCode("夏至小姐姐,留个微信呗", "E:\\xx\\2.png");
if (code){
System.out.println("成功");
}else {
System.out.println("失败了");
}
}
}
3.3 运行测试
3.4 测试Springboot生成二维码并回显到页面上
@GetMapping("/qrcode")
public void qrcodeTest(HttpServletResponse response) throws WriterException, IOException {
ServletOutputStream outputStream = response.getOutputStream();
int width = 300;
int height =300;
String format = "png";
HashMap<EncodeHintType, Object> map = new HashMap<>();
map.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
map.put(EncodeHintType.CHARACTER_SET,"utf-8");
String content = "今年是兔年,兔飞猛进!猪兔猛进!";
BitMatrix encode = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height, map);
MatrixToImageWriter.writeToStream(encode,format,outputStream);
System.out.println("成功!");
}
3.5 如果希望用html页面的方式展示再写页面即可
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>首页</title>
</head>
<body>
<h5>扫码获取信息</h5>
<img src="/qrcode">
</body>
</html>