当前位置: 代码迷 >> 综合 >> zxing(二维码生成与读取)
  详细解决方案

zxing(二维码生成与读取)

热度:72   发布时间:2024-02-23 22:33:08.0

1. maven

        <dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.3.0</version></dependency><!--        如果是 web 应用添加--><dependency><groupId>com.google.zxing</groupId><artifactId>javase</artifactId><version>3.3.0</version></dependency>

2. API

1. 基础API(部分)

描述 方法 描述
MultiFormatWriter 用于条码生成,不同类型的条码有各自的Writer类 encode(String contents, BarcodeFormat var2, int w, int h, Map<EncodeHintType, ?> setting)

获取BitMatrix对象

setting参数可不传

BitMatrix 条码位矩阵对象

get(int x, int y)

获取(x, y)的位值,true表示黑色
set(int x, int y) 设置(x, y)的位值为true(黑)
unset(int x, int y) 设置(x, y)的位值为false(白)

flip(int x,int y)

对(x, y)的位值做非运算
clear() 清空矩阵
   
MatrixToImageWriter 条码写出对象 writeToPath(BitMatrix matrix, String format, Path file, MatrixToImageConfig config)

报错条码到本地

matrix:条码位矩阵对象

config参数可无

format: 图片格式

file: 文件路径对象

stream:输出流

file: 文件对象

config:颜色配置,可无

writeToStream(BitMatrix matrix, String format, OutputStream stream, MatrixToImageConfig config)
writeToFile(BitMatrix matrix, String format, File file, MatrixToImageConfig config)
toBufferedImage(BitMatrix matrix, MatrixToImageConfig config)

转换为BufferedImage

config参数可无

MatrixToImageConfig 颜色配置 MatrixToImageConfig(int onColor, int offColor) 构造方法设置条码及背景颜色,无参为白底黑色条码
MultiFormatReader 用于条码解析,不同类型的条码有各自的tReader类 decode(BinaryBitmap image, Map<DecodeHintType, ?> hints) 构造方法
Binarizer   HybridBinarizer(LuminanceSource source) 构造方法
LuminanceSource   BufferedImageLuminanceSource(BufferedImage image, int left, int top, int width, int height) 构造方法,参数可只有image
Result  解析结果对象 getText() 获取条形码文本内容
getBarcodeFormat() 获取条码类型
getRawBytes() 获取原始字节
getResultPoints() 获取结果点

2.2 常量

描述 常量 描述 图例与示例
BarcodeFormat 条码类型 AZTEC 阿兹特克条形码
CODABAR 自检条码,用于读取印刷形式的条码,特别是使用点阵打印机印刷的条码。它的典型用途包含 Fed-Ex 包裹和血库单
CODE_39 第一个同时使用数字和字母的条码。它是一种可变长度的条码,最多可同时对 43 个字母数字字符进行编码。它最常用于军事和汽车行业。
CODE_93 Code 93 条码比 Code 39 条码更新、更安全且更紧凑,能读取字母和数字。它用于军事和汽车领域,还被加拿大邮政用来对特殊投递信息进行编码。
CODE_128 密度最高的一款条码,也是在潜在信息存储方面功能最全的一维条码。它可以解码全部128 ASCII 字符
DATA_MATRIX 二维条码
EAN_8 国际物品编码协会制 定的一种商品用条码,EAN-8 条码是 EAN-13 条码的压缩版
EAN_8: 8位数字    EAN_13: 13位数字
     
EAN_13
ITF 交叉二五条码
 MAXICODE   没有编码器
PDF_417 一种堆叠式二维条码
QR_CODE 二维码
RSS_14   没有编码器
RSS_EXPANDED   没有编码器
UPC_A 由 12 位数字组成
UPC_E UPC-E 是标准尺寸的 UPC-A 数字条码的压缩版
UPC_EAN_EXTENSION   没有编码器
EncodeHintType 编码时的额外参数 ERROR_CORRECTION 容错率,指定容错等级,例如二维码中使用的ErrorCorrectionLevel, Aztec使用Integer  
CHARACTER_SET 编码集  
DATA_MATRIX_SHAPE 指定生成的数据矩阵的形状,类型为SymbolShapeHint  
MIN_SIZE 最小数量  
MAX_SIZE 最大数量  
MARGIN 边距  
PDF417_COMPACT 指定是否使用PDF417紧凑模式, 类型Boolean  
PDF417_COMPACTION 指定PDF417的紧凑类型  
PDF417_DIMENSIONS 指定PDF417的最大最小行列数  
AZTEC_LAYERS AZTEC编码层数  
QR_VERSION 指定二维码版本,版本越高越复杂,反而不容易解析  
DecodeHintType 解码时的额外参数 OTHER    
PURE_BARCODE Boolean类型,指定图片是一个纯粹的二维码  
POSSIBLE_FORMATS 可能的编码格式,List类型  
CHARACTER_SET 编码字符集,通常指定UTF-8  
TRY_HARDER 花更多的时间用于寻找图上的编码,优化准确性,但不优化速度,Boolean类型  
ALLOWED_LENGTHS 允许的编码数据长度 - 拒绝多余的数据。不懂这是什么,int[]类型  
ASSUME_CODE_39_CHECK_DIGIT CODE 39 使用  
ASSUME_GS1 使用GS1编码来解析  
RETURN_CODABAR_START_END CODABAR编码使用  
NEED_RESULT_POINT_CALLBACK 当解析到可能的结束点时进行回调  ResultPointCallback  
ALLOWED_EAN_EXTENSIONS 允许EAN或UPC编码有额外的长度int[]  
ErrorCorrectionLevel 容错率,指定容错等级 L 1  
M 0  
Q 3  
H 2  
SymbolShapeHint 数据矩阵的形状 FORCE_NONE  
FORCE_SQUARE 正方形  
FORCE_RECTANGLE 长方形  
MatrixToImageConfig 条码颜色 BLACK 黑色  
WHITE 白色  

3. 示例

3.1 二维码生成

        MultiFormatWriter qrCodeWriter=new MultiFormatWriter();Map<EncodeHintType, Object> hints = new HashMap<>();hints.put(EncodeHintType.CHARACTER_SET, "utf-8");hints.put(EncodeHintType.MARGIN,1);   //先设置margin为1BitMatrix bitMatrix = qrCodeWriter.encode("https://www.baidu.com", BarcodeFormat.QR_CODE, 500, 500,hints);Path path = FileSystems.getDefault().getPath("D:\\demo\\zxing\\"+System.currentTimeMillis()+"—QR_CODE.png");MatrixToImageWriter.writeToPath(bitMatrix, "PNG", path,new MatrixToImageConfig( -100000,-1777216));

3.2 二维码解码

        BufferedImage image = ImageIO.read(new File("D:\\demo\\zxing\\1592875410059—QR_CODE_1.png"));LuminanceSource luminanceSource = new BufferedImageLuminanceSource(image);Binarizer binarizer = new HybridBinarizer(luminanceSource);BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer);Map<DecodeHintType, Object> hints = new HashMap<>();hints.put(DecodeHintType.CHARACTER_SET, "utf-8");hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);hints.put(DecodeHintType.POSSIBLE_FORMATS, BarcodeFormat.QR_CODE);Result result = new QRCodeReader().decode(binaryBitmap, hints);System.out.println(result.getText());

3.3 带loge,背景图片及文字的二维码工具类

package com.example.project.demo;import com.google.zxing.*;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import org.apache.commons.lang3.StringUtils;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.*;/*** 二维码工具类*/
public class BarcodeUtils {private static final int QRCOLOR = 0xFF000000; // 二维码颜色 默认是黑色private static final int BGWHITE = 0xFFFFFFFF; // 背景颜色private static final int WIDTH = 215; // 二维码宽private static final int HEIGHT = 215; // 二维码高private static final int WORDHEIGHT = 235; // 加文字二维码高/*** 用于设置QR二维码参数*/private static Map<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>() {private static final long serialVersionUID = 1L;{// 设置QR二维码的纠错级别(H为最高级别)具体级别信息put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);// 设置编码方式put(EncodeHintType.CHARACTER_SET, "utf-8");put(EncodeHintType.MARGIN, 0);}};/*** 设置 Graphics2D 属性  (抗锯齿)** @param graphics2D*/private static void setGraphics2D(Graphics2D graphics2D) {graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);graphics2D.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_DEFAULT);Stroke s = new BasicStroke(1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER);graphics2D.setStroke(s);}/*** 生成二维码图片存储到filePath中** @param content  二维码内容* @param filePath 成二维码图片保存路径* @return*/public static boolean createImg(String content, String filePath) {boolean flag = false;try {MultiFormatWriter multiFormatWriter = new MultiFormatWriter();BitMatrix bitMatrix = multiFormatWriter.encode(content, BarcodeFormat.QR_CODE, WIDTH, HEIGHT, hints);// 图片输出路径String code = content.split("=")[1]; // 设备编号File file = new File(filePath + "//PSD" + code + ".jpg");if (!file.exists()) {// 如果文件夹不存在则创建file.mkdirs();}// 输出二维码图片到文件夹MatrixToImageWriter.writeToFile(bitMatrix, "jpg", file);flag = true;} catch (IOException e) {e.printStackTrace();} catch (Exception e) {e.printStackTrace();}return flag;}/*** 把带logo的二维码下面加上文字** @param image* @param words* @return*/private static BufferedImage insertWords(BufferedImage image, String words) {// 新的图片,把带logo的二维码下面加上文字if (StringUtils.isNotEmpty(words)) {//创建一个带透明色的BufferedImage对象BufferedImage outImage = new BufferedImage(WIDTH, WORDHEIGHT, BufferedImage.TYPE_INT_ARGB);Graphics2D outg = outImage.createGraphics();setGraphics2D(outg);// 画二维码到新的面板outg.drawImage(image, 0, 0, image.getWidth(), image.getHeight(), null);// 画文字到新的面板Color color = new Color(183, 183, 183);outg.setColor(color);// 字体、字型、字号outg.setFont(new Font("微软雅黑", Font.PLAIN, 18));//文字长度int strWidth = outg.getFontMetrics().stringWidth(words);//总长度减去文字长度的一半  (居中显示)int wordStartX = (WIDTH - strWidth) / 2;//height + (outImage.getHeight() - height) / 2 + 12int wordStartY = HEIGHT + 10;// 画文字outg.drawString(words, wordStartX, wordStartY);outg.dispose();outImage.flush();return outImage;}return null;}/*** @param logoFile loge图片的路径* @param bgFile   背景图片的路径* @param codeFile 图片输出路径* @param qrUrl    二维码内容* @param words    二维码下面的文字* @description 生成带logo的二维码图片 二维码下面带文字*/public static void drawLogoQRCode(File logoFile, File bgFile, File codeFile, String qrUrl, String words) {try {MultiFormatWriter multiFormatWriter = new MultiFormatWriter();// 参数顺序分别为:编码内容,编码类型,生成图片宽度,生成图片高度,设置参数BitMatrix bm = multiFormatWriter.encode(qrUrl, BarcodeFormat.QR_CODE, WIDTH, HEIGHT, hints);BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);// 开始利用二维码数据创建Bitmap图片,分别设为黑(0xFFFFFFFF)白(0xFF000000)两色for (int x = 0; x < WIDTH; x++) {for (int y = 0; y < HEIGHT; y++) {image.setRGB(x, y, bm.get(x, y) ? QRCOLOR : BGWHITE);}}//把logo画到二维码上面if (Objects.nonNull(logoFile) && logoFile.exists()) {// 构建绘图对象Graphics2D g = image.createGraphics();setGraphics2D(g);// 读取Logo图片BufferedImage logo = ImageIO.read(logoFile);// 开始绘制logo图片 等比缩放:(width * 2 / 10 height * 2 / 10)不需缩放直接使用图片宽高//width * 2 / 5 height * 2 / 5  logo绘制在中心点位置g.drawImage(logo, WIDTH * 2 / 5, HEIGHT * 2 / 5, logo.getWidth(), logo.getHeight(), null);g.dispose();logo.flush();}// 新的图片,把带logo的二维码下面加上文字image = insertWords(image, words);image.flush();ImageIO.write(image, "png", codeFile);} catch (Exception e) {e.printStackTrace();}}public static void main(String[] args) {//logoFile logoFile = new File("D:\\demo\\zxing\\1592875410059—QR_CODE_1.png");//背景图片File bgFile = new File("D:\\demo\\zxing\\1.jpg");//生成图片File qrCodeFile = new File("D:\\demo\\zxing\\12345.png");//二维码内容String url = "https://w.url.cn/s/AYmfAV3";//二维码下面的文字String words = "PSD000001";drawLogoQRCode(logoFile, bgFile, qrCodeFile, url, words);}
}

3.4 可带内容文本的条形码工具类

package com.example.project.demo;import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.util.Hashtable;public class Code_128Utils {private static final int WIDTH = 351;private static final int CODEHEIGHT = 55;private static final int HEIGHT = 78;private static final int FONTSIZE = 25;private static final String IMAGETYPE = "JPEG";/**** @param no 条形码内容* @param codePath* @param isShowNum*/public static void createCode(String no, String codePath, Boolean isShowNum) throws Exception {FileOutputStream fos;fos = new FileOutputStream(new File(codePath));int width = WIDTH;int height = CODEHEIGHT;Hashtable<EncodeHintType, String> hints = new Hashtable<EncodeHintType, String>();hints.put(EncodeHintType.CHARACTER_SET, "utf-8");BitMatrix m = new MultiFormatWriter().encode(no,BarcodeFormat.CODE_128, width, height, hints);MatrixToImageWriter.writeToStream(m, IMAGETYPE, fos);fos.flush();fos.close();if(isShowNum){createFont(no, codePath);}}///该方法用来生成二维码字体并且把二维码拼接到字体图片上private static void createFont(String no, String codePath) throws Exception {BufferedImage font = new BufferedImage(WIDTH, HEIGHT,BufferedImage.TYPE_INT_RGB);BufferedImage code = ImageIO.read(new File(codePath));Graphics2D g = (Graphics2D) font.getGraphics();//长宽是总的 字体加二维码的g.clearRect(0, 0, WIDTH, HEIGHT);g.setColor(Color.WHITE);g.fillRect(0, 0, WIDTH, HEIGHT);//字体渲染g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);g.setRenderingHint(RenderingHints.KEY_RENDERING,RenderingHints.VALUE_RENDER_QUALITY);//在图片上把字写好for (int i = 0; i < no.length(); i++) {g.setColor(Color.black);Font font_ = new Font("Consolas", 0, FONTSIZE);g.setFont(font_);g.drawString(no.charAt(i) + "", (FONTSIZE * 2 + WIDTH - no.length()* FONTSIZE)/ 2 + (i - 1) * FONTSIZE, CODEHEIGHT + HEIGHT - CODEHEIGHT);}//然后把二维码加上去 g.drawImage(code, 0, 0, null);g.dispose();//进行图片处理,防止出现模糊int[] rgb = new int[3];for (int i = 0; i < WIDTH; i++) {for (int j = CODEHEIGHT; j < HEIGHT; j++) {int pixel = font.getRGB(i, j);rgb[0] = (pixel & 0xff0000) >> 16;rgb[1] = (pixel & 0xff00) >> 8;rgb[2] = (pixel & 0xff);if (rgb[0] > 125 || rgb[1] > 125 || rgb[2] > 125) {font.setRGB(i, j, -1);}if (rgb[0] < 100 || rgb[1] < 100 || rgb[2] < 100) {font.setRGB(i, j, -16777216);}}}File outputfile = new File(codePath);ImageIO.write(font, IMAGETYPE, outputfile);}public static void main(String[] args) throws Exception {String s = "D:\\demo\\zxing\\"+System.currentTimeMillis()+".jpg";createCode("S1234567", s,false);}
}