一、概述

  • 使用 zxing 开源库

    • Zxing主要是Google出品的,用于识别一维码和二维码的第三方库
    • 主要类:
    • BitMatrix 位图矩阵
    • MultiFormatWriter 位图编写器
    • MatrixToImageWriter 写入图片
  • 可以生成、识别条形码和二维码

  • 内置三种尺寸:enum Size {SMALL, MIDDLE, BIG}

  • 依赖

<dependency><groupId>com.google.zxing</groupId><artifactId>javase</artifactId><version>3.5.1</version>
</dependency>
<dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version>
</dependency>
<!-- web -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>2.6.7</version>
</dependency>
<dependency><groupId>commons-lang</groupId><artifactId>commons-lang</artifactId><version>2.6</version>
</dependency>

二、效果图

三、条形码

  • 将宽度不等的多个黑条和白条,按照一定的编码规则排序,用以表达一组信息的图像标识符
  • 通常代表一串数字 / 字母,每一位有特殊含义
  • 一般数据容量30个数字 / 字母

1、生成简单条形码(无文字)

/*** 生成简单条形码(无文字)** @param content* @param width* @param height* @return
*/
public static BufferedImage create(String content, int width, int height) {// 定义位图矩阵BitMatrixBitMatrix matrix = null;try {// 定义二维码参数Map<EncodeHintType, Object> hints = new HashMap<>(3);// 设置编码hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");// 设置容错等级hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);// 设置边距,默认为5hints.put(EncodeHintType.MARGIN, 3);// 使用code_128格式进行编码生成条形码MultiFormatWriter writer = new MultiFormatWriter();matrix = writer.encode(content, BarcodeFormat.CODE_128, width, height, hints);} catch (WriterException e) {e.printStackTrace();//throw new RuntimeException("条形码内容写入失败");}return MatrixToImageWriter.toBufferedImage(matrix);
}

2、生成条形码(含文字)

  • 生成条形码(含文字)
/*** 生成条形码(含文字)* ***************************************************** ----------------------------------------------* |                         2023-06-10 10:55   |* |                                            |* |            商品名称 /超出不显示/              |* |                                            |* |    | || ||| | || |||| | | | ||| | | ||     |* |    | || ||| | || |||| | | | ||| | | ||     |* |    | || ||| | || |||| | | | ||| | | ||     |* |    | || ||| | || |||| | | | ||| | | ||     |* |               13800000000                  |* ----------------------------------------------* ===================================================* 1、日期:顶部右侧* 2、商品名称:居中* 3、条形码:商品名称下方,且居中* 4、条码内容:条形码下方,且居中* ******************************************************* @param codeImage     条形码图片* @param bottomStr     底部文字* @param titleStr      标题文字* @param topRightStr   右上角文字* @param pictureWidth  图片宽度* @param pictureHeight 图片高度* @param margin        边距* @param fontSize      字体大小* @return 条形码图片*/
private static BufferedImage createWithWords(BufferedImage codeImage,String bottomStr,String titleStr,String topRightStr,int pictureWidth,int pictureHeight,int margin,int fontSize) {BufferedImage picImage = new BufferedImage(pictureWidth, pictureHeight, BufferedImage.TYPE_INT_RGB);Graphics2D g2d = picImage.createGraphics();// 抗锯齿setGraphics2D(g2d);// 设置白色setColorWhite(g2d, picImage.getWidth(), picImage.getHeight());// 条形码默认居中显示int codeStartX = (pictureWidth - codeImage.getWidth()) / 2;int codeStartY = (pictureHeight - codeImage.getHeight()) / 2 + 2 * margin;// 画条形码到新的面板g2d.drawImage(codeImage, codeStartX, codeStartY, codeImage.getWidth(), codeImage.getHeight(), null);// 给条码上下各画一条线// 设置颜色g2d.setColor(Color.LIGHT_GRAY);int y1 = 2 * margin + codeImage.getHeight();int y2 = 2 * margin + 2 * codeImage.getHeight();g2d.drawLine(0, y1, pictureWidth, y1);g2d.drawLine(0, y2, pictureWidth, y2);// 画文字到新的面板g2d.setColor(Color.BLACK);// 字体、字型、字号g2d.setFont(new Font("微软雅黑", Font.PLAIN, fontSize));// 文字与条形码之间的间隔int wordAndCodeSpacing = 3;// 底部文字(居中)if (StringUtils.isNotEmpty(bottomStr)) {// 文字长度int strWidth = g2d.getFontMetrics().stringWidth(bottomStr);// 文字X轴开始坐标int strStartX = (pictureWidth - strWidth) / 2;if (strStartX < margin) {strStartX = margin;}// 文字Y轴开始坐标int strStartY = codeStartY + codeImage.getHeight() + fontSize + wordAndCodeSpacing;// 画文字g2d.drawString(bottomStr, strStartX, strStartY);}// 右上角文字if (StringUtils.isNotEmpty(topRightStr)) {// 文字长度int strWidth = g2d.getFontMetrics().stringWidth(topRightStr);// 文字X轴开始坐标int strStartX = pictureWidth - strWidth - margin;// 文字Y轴开始坐标int strStartY = margin + fontSize;// 画文字g2d.drawString(topRightStr, strStartX, strStartY);}// 标题文字(居中)if (StringUtils.isNotEmpty(titleStr)) {if (titleStr.length() > 11) {titleStr = titleStr.substring(0, 11);}// 字体、字型、字号int fs = (int) Math.ceil(fontSize * 1.5);g2d.setFont(new Font("微软雅黑", Font.PLAIN, fs));// 文字长度int strWidth = g2d.getFontMetrics().stringWidth(titleStr);// 文字X轴开始坐标int strStartX = (pictureWidth - strWidth) / 2;if (strStartX < margin) {strStartX = margin;}// 文字Y轴开始坐标int strStartY = codeStartY - margin;// 画文字g2d.drawString(titleStr, strStartX, strStartY);}g2d.dispose();picImage.flush();return picImage;
}
  • 设置 Graphics2D 属性 (抗锯齿)
/*** 设置 Graphics2D 属性 (抗锯齿)** @param g2d Graphics2D提供对几何形状、坐标转换、颜色管理和文本布局更为复杂的控制*/
private static void setGraphics2D(Graphics2D g2d) {g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_DEFAULT);Stroke s = new BasicStroke(1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER);g2d.setStroke(s);
}
  • 设置背景为白色
/*** 设置背景为白色** @param g2d Graphics2D提供对几何形状、坐标转换、颜色管理和文本布局更为复杂的控制*/
private static void setColorWhite(Graphics2D g2d, int width, int height) {g2d.setColor(Color.WHITE);// 填充整个屏幕g2d.fillRect(0, 0, width, height);// 设置笔刷g2d.setColor(Color.BLACK);
}
  • 创建小号条形码(250x150)
/*** 创建小号条形码(250x150)** @param code* @param name* @return*/
private static BufferedImage createSmallWithWords(@NonNull String code, @NonNull String name) {// 条形码底部内容String bottomStr = code;// 条形码左上角内容//String topLeftStr = name.length() < 11 ? name : name.substring(0, 11);String topLeftStr = name;// 条形码右上角内容DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");String topRightStr = dtf.format(LocalDateTime.now());// 生成条形码BufferedImage barCodeImage = create(bottomStr, 250, 50);return createWithWords(barCodeImage,bottomStr,topLeftStr,topRightStr,250,150,10,14);
}
  • 创建中号条形码(350x210)
/*** 创建中号条形码(350x210)** @param code* @param name* @return*/
private static BufferedImage createMiddleWithWords(@NonNull String code, @NonNull String name) {// 条形码底部内容String bottomStr = code;// 条形码左上角内容//String topLeftStr = name.length() < 11 ? name : name.substring(0, 11);String topLeftStr = name;// 条形码右上角内容DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");String topRightStr = dtf.format(LocalDateTime.now());// 生成条形码BufferedImage barCodeImage = create(bottomStr, 350, 70);return createWithWords(barCodeImage,bottomStr,topLeftStr,topRightStr,350,210,14,20);
}
  • 创建大号条形码(500x300)
/*** 创建大号条形码(500x300)** @param code* @param name* @return*/
private static BufferedImage createBigWithWords(@NonNull String code, @NonNull String name) {// 条形码底部内容String bottomStr = code;// 条形码左上角内容//String topLeftStr = name.length() < 11 ? name : name.substring(0, 11);String topLeftStr = name;// 条形码右上角内容DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");String topRightStr = dtf.format(LocalDateTime.now());// 生成条形码BufferedImage barCodeImage = create(bottomStr, 500, 100);return createWithWords(barCodeImage,bottomStr,topLeftStr,topRightStr,500,300,20,28);
}
  • 创建内置尺寸(小/中/大)条形码
/*** 生成条形码(带文字)** @param code 编码内容* @param name 名称* @param size 规格:小中大* @return*/
public static BufferedImage createWithWords(@NonNull String code,@NonNull String name,@NonNull Size size
) {switch (size) {case SMALL:return createSmallWithWords(code, name);case MIDDLE:return createMiddleWithWords(code, name);case BIG:default:return createBigWithWords(code, name);}
}

四、二维码

  • 用某种特定几何图形按一定规律在平面(二维方向上)分布的黑白相间的图形记录数据符号信息
  • 比一维条形码能存储更多信息,表示更多数据类型
  • 能够存储数字 / 字母 / 汉字 / 图片等信息
  • 可存储几百到几十KB字符

1、生成指定尺寸二维码

/*** 生成二维码(正方形)* @param content* @param sideLength 边长(px)* @return*/
public static BufferedImage create(String content, int sideLength) {BitMatrix matrix = null;// 定义二维码参数Map<EncodeHintType, Object> hints = new HashMap<>(3);// 设置编码hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");// 设置容错等级hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);// 设置边距,默认为5hints.put(EncodeHintType.MARGIN, 3);try {matrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, sideLength, sideLength, hints);} catch (Exception e) {e.printStackTrace();//throw new RuntimeException("条形码内容写入失败");}return MatrixToImageWriter.toBufferedImage(matrix);
}

2、生成内置尺寸(小/中/大)二维码

小号:250px;中号:350px;大号:500px;

public static BufferedImage create(String content, Size size) {switch (size) {case SMALL:return create(content, 250);case MIDDLE:return create(content, 350);case BIG:default:return create(content, 500);}
}

五、保存

  • 存入文件
/*** 存入文件** @param barCodeImage* @return 文件名*/
public static String toFile(BufferedImage barCodeImage) {String fileName = getFileName();boolean isWrite = false;try {FileOutputStream outputStream = new FileOutputStream(new File(getImageDir(), fileName));isWrite = ImageIO.write(barCodeImage, "png", outputStream);} catch (IOException e) {e.printStackTrace();}if (isWrite) {return fileName;}return "";
}
  • 存放目录
/*** 得到图片存放目录* 类路径下的image文件夹** @return*/
private static String getImageDir() {String imageDir = "";Resource resource = new ClassPathResource("");try {String _dir = resource.getFile().getAbsolutePath();File file = new File(_dir, "image");if (!file.exists()) {file.mkdirs();}imageDir = file.getAbsolutePath();} catch (IOException e) {e.printStackTrace();}return imageDir;
}
  • 文件名
/*** 生成文件名* 当前时间戳 + 两位随机数** @return*/
private static String getFileName() {// 当前时间戳long second = Instant.now().getEpochSecond();// 两位随机数ThreadLocalRandom r = ThreadLocalRandom.current();int rand = r.nextInt(10, 99);return new StringBuffer().append(second).append(rand).append(".png").toString();
}

六、识别

/*** 识别图形码(条形码/二维码)* ************************************************ ------ 条形码 ----------------------------------* 可以识别内容:手机号、纯数字、字母数字、网址(中大号)* 识别不了小号(250x150)含文字的网址条形码* 存储网址时用二维码,不要使用条形码* ************************************************ ------ 二维码 ----------------------------------* 比条形码有优势;能识别三种尺寸的网址二维码* ************************************************* @param imageCode 图形码文件* @return void*/
public static String scan(File imageCode) {String text = "";try {BufferedImage image = ImageIO.read(imageCode);if (image == null) {return text;}LuminanceSource source = new BufferedImageLuminanceSource(image);BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));Map<DecodeHintType, Object> hints = new HashMap<>(3);hints.put(DecodeHintType.CHARACTER_SET, "UTF-8");hints.put(DecodeHintType.PURE_BARCODE, Boolean.TRUE);hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);Result result = new MultiFormatReader().decode(bitmap, hints);text = result.getText();} catch (Exception e) {e.printStackTrace();System.out.println("无法识别");}return text;
}public static String scan(String fileName) {return scan(new File(getImageDir(), fileName));
}public static String scan(String fileName, String fileParent) {return scan(new File(fileParent, fileName));
}

七、测试类

package com.tuwer.util;/*** <p>描述...</p>** @author 土味儿* @version 1.0* @Date 2023/6/10*/
public class ImageCodeTest {public static void main(String[] args) {cr();//sc();}/*** 创建*/private static void cr() {//String code = "13800000000";String code = "1667320863285510145";//String code = "abcdefg123456789012";//String code = "http://www.baidu.com";String title = "商品名称(超出不显示)";System.out.println(ImageCodeUtil.toFile(ImageCodeUtil.BarCode.createWithWords(code, title, ImageCodeUtil.Size.SMALL)));System.out.println(ImageCodeUtil.toFile(ImageCodeUtil.BarCode.createWithWords(code, title, ImageCodeUtil.Size.MIDDLE)));System.out.println(ImageCodeUtil.toFile(ImageCodeUtil.BarCode.createWithWords(code, title, ImageCodeUtil.Size.BIG)));//System.out.println(toFile(QrCode.create(code, 500)));//System.out.println(ImageCodeUtil.toFile(ImageCodeUtil.QrCode.create(code, ImageCodeUtil.Size.SMALL)));//System.out.println(ImageCodeUtil.toFile(ImageCodeUtil.QrCode.create(code, ImageCodeUtil.Size.MIDDLE)));//System.out.println(ImageCodeUtil.toFile(ImageCodeUtil.QrCode.create(code, ImageCodeUtil.Size.BIG)));}/*** 识别*/private static void sc() {// 扫描// 13800000000//String[] fs = {"168636218096.png", "168636218180.png", "168636218127.png"};// 1667320863285510145//String[] fs = {"168636260651.png", "168636260766.png", "168636260794.png"};// abcdefg123456789012//String[] fs = {"168636320566.png", "168636320750.png", "168636320743.png"};// http://www.baidu.comString[] fs = {"168636738387.png", "168636738545.png", "168636738539.png"};for (String f : fs) {System.out.println("-----------------");System.out.println(ImageCodeUtil.scan(f));}}
}

八、完整源码

package com.tuwer.util;import com.google.zxing.*;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import org.apache.commons.lang.StringUtils;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.lang.NonNull;import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ThreadLocalRandom;/*** <p>图形码工具类</p>** @author 土味儿* @version 1.0* @Date 2023/6/9*/
public class ImageCodeUtil {/*** 尺寸*/enum Size {SMALL, MIDDLE, BIG}// ====================== 条形码内部类 ========================/*** 条形码*/public static class BarCode {/*** 生成简单条形码(无文字)** @param content* @param width* @param height* @return*/public static BufferedImage create(String content, int width, int height) {// 定义位图矩阵BitMatrixBitMatrix matrix = null;try {// 定义二维码参数Map<EncodeHintType, Object> hints = new HashMap<>(3);// 设置编码hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");// 设置容错等级hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);// 设置边距,默认为5hints.put(EncodeHintType.MARGIN, 3);// 使用code_128格式进行编码生成条形码MultiFormatWriter writer = new MultiFormatWriter();matrix = writer.encode(content, BarcodeFormat.CODE_128, width, height, hints);} catch (WriterException e) {e.printStackTrace();//throw new RuntimeException("条形码内容写入失败");}return MatrixToImageWriter.toBufferedImage(matrix);}/*** 生成条形码(含文字)* ***************************************************** ----------------------------------------------* |                         2023-06-10 10:55   |* |                                            |* |            商品名称 /超出不显示/              |* |                                            |* |    | || ||| | || |||| | | | ||| | | ||     |* |    | || ||| | || |||| | | | ||| | | ||     |* |    | || ||| | || |||| | | | ||| | | ||     |* |    | || ||| | || |||| | | | ||| | | ||     |* |               13800000000                  |* ----------------------------------------------* ===================================================* 1、日期:顶部右侧* 2、商品名称:居中* 3、条形码:商品名称下方,且居中* 4、条码内容:条形码下方,且居中* ******************************************************* @param codeImage     条形码图片* @param bottomStr     底部文字* @param titleStr      标题文字* @param topRightStr   右上角文字* @param pictureWidth  图片宽度* @param pictureHeight 图片高度* @param margin        边距* @param fontSize      字体大小* @return 条形码图片*/private static BufferedImage createWithWords(BufferedImage codeImage,String bottomStr,String titleStr,String topRightStr,int pictureWidth,int pictureHeight,int margin,int fontSize) {BufferedImage picImage = new BufferedImage(pictureWidth, pictureHeight, BufferedImage.TYPE_INT_RGB);Graphics2D g2d = picImage.createGraphics();// 抗锯齿setGraphics2D(g2d);// 设置白色setColorWhite(g2d, picImage.getWidth(), picImage.getHeight());// 条形码默认居中显示int codeStartX = (pictureWidth - codeImage.getWidth()) / 2;int codeStartY = (pictureHeight - codeImage.getHeight()) / 2 + 2 * margin;// 画条形码到新的面板g2d.drawImage(codeImage, codeStartX, codeStartY, codeImage.getWidth(), codeImage.getHeight(), null);// 给条码上下各画一条线// 设置颜色g2d.setColor(Color.LIGHT_GRAY);int y1 = 2 * margin + codeImage.getHeight();int y2 = 2 * margin + 2 * codeImage.getHeight();g2d.drawLine(0, y1, pictureWidth, y1);g2d.drawLine(0, y2, pictureWidth, y2);// 画文字到新的面板g2d.setColor(Color.BLACK);// 字体、字型、字号g2d.setFont(new Font("微软雅黑", Font.PLAIN, fontSize));// 文字与条形码之间的间隔int wordAndCodeSpacing = 3;// 底部文字(居中)if (StringUtils.isNotEmpty(bottomStr)) {// 文字长度int strWidth = g2d.getFontMetrics().stringWidth(bottomStr);// 文字X轴开始坐标int strStartX = (pictureWidth - strWidth) / 2;if (strStartX < margin) {strStartX = margin;}// 文字Y轴开始坐标int strStartY = codeStartY + codeImage.getHeight() + fontSize + wordAndCodeSpacing;// 画文字g2d.drawString(bottomStr, strStartX, strStartY);}// 右上角文字if (StringUtils.isNotEmpty(topRightStr)) {// 文字长度int strWidth = g2d.getFontMetrics().stringWidth(topRightStr);// 文字X轴开始坐标int strStartX = pictureWidth - strWidth - margin;// 文字Y轴开始坐标int strStartY = margin + fontSize;// 画文字g2d.drawString(topRightStr, strStartX, strStartY);}// 标题文字(居中)if (StringUtils.isNotEmpty(titleStr)) {// 字体、字型、字号int fs = (int) Math.ceil(fontSize * 1.5);g2d.setFont(new Font("微软雅黑", Font.PLAIN, fs));// 文字长度int strWidth = g2d.getFontMetrics().stringWidth(titleStr);// 文字X轴开始坐标int strStartX = (pictureWidth - strWidth) / 2;if (strStartX < margin) {strStartX = margin;}// 文字Y轴开始坐标int strStartY = codeStartY - margin;// 画文字g2d.drawString(titleStr, strStartX, strStartY);}g2d.dispose();picImage.flush();return picImage;}/*** 设置 Graphics2D 属性 (抗锯齿)** @param g2d Graphics2D提供对几何形状、坐标转换、颜色管理和文本布局更为复杂的控制*/private static void setGraphics2D(Graphics2D g2d) {g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_DEFAULT);Stroke s = new BasicStroke(1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER);g2d.setStroke(s);}/*** 设置背景为白色** @param g2d Graphics2D提供对几何形状、坐标转换、颜色管理和文本布局更为复杂的控制*/private static void setColorWhite(Graphics2D g2d, int width, int height) {g2d.setColor(Color.WHITE);// 填充整个屏幕g2d.fillRect(0, 0, width, height);// 设置笔刷g2d.setColor(Color.BLACK);}/*** 创建小号条形码(250x150)** @param code* @param name* @return*/private static BufferedImage createSmallWithWords(@NonNull String code, @NonNull String name) {// 条形码底部内容String bottomStr = code;// 条形码左上角内容//String topLeftStr = name.length() < 11 ? name : name.substring(0, 11);String topLeftStr = name;// 条形码右上角内容DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");String topRightStr = dtf.format(LocalDateTime.now());// 生成条形码BufferedImage barCodeImage = create(bottomStr, 250, 50);return createWithWords(barCodeImage,bottomStr,topLeftStr,topRightStr,250,150,10,14);}/*** 创建中号条形码(350x210)** @param code* @param name* @return*/private static BufferedImage createMiddleWithWords(@NonNull String code, @NonNull String name) {// 条形码底部内容String bottomStr = code;// 条形码左上角内容//String topLeftStr = name.length() < 11 ? name : name.substring(0, 11);String topLeftStr = name;// 条形码右上角内容DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");String topRightStr = dtf.format(LocalDateTime.now());// 生成条形码BufferedImage barCodeImage = create(bottomStr, 350, 70);return createWithWords(barCodeImage,bottomStr,topLeftStr,topRightStr,350,210,14,20);}/*** 创建大号条形码(500x300)** @param code* @param name* @return*/private static BufferedImage createBigWithWords(@NonNull String code, @NonNull String name) {// 条形码底部内容String bottomStr = code;// 条形码左上角内容//String topLeftStr = name.length() < 11 ? name : name.substring(0, 11);String topLeftStr = name;// 条形码右上角内容DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");String topRightStr = dtf.format(LocalDateTime.now());// 生成条形码BufferedImage barCodeImage = create(bottomStr, 500, 100);return createWithWords(barCodeImage,bottomStr,topLeftStr,topRightStr,500,300,20,28);}/*** 生成条形码(带文字)** @param code 编码内容* @param name 名称* @param size 规格:小中大* @return*/public static BufferedImage createWithWords(@NonNull String code,@NonNull String name,@NonNull Size size) {switch (size) {case SMALL:return createSmallWithWords(code, name);case MIDDLE:return createMiddleWithWords(code, name);case BIG:default:return createBigWithWords(code, name);}}}// ====================== 二维码内部类 ========================/*** 二维码*/public static class QrCode {/*** 生成二维码(正方形)** @param content* @param sideLength 边长(px)* @return*/public static BufferedImage create(String content, int sideLength) {BitMatrix matrix = null;// 定义二维码参数Map<EncodeHintType, Object> hints = new HashMap<>(3);// 设置编码hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");// 设置容错等级hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);// 设置边距,默认为5hints.put(EncodeHintType.MARGIN, 3);try {matrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, sideLength, sideLength, hints);} catch (Exception e) {e.printStackTrace();//throw new RuntimeException("条形码内容写入失败");}return MatrixToImageWriter.toBufferedImage(matrix);}public static BufferedImage create(String content, Size size) {switch (size) {case SMALL:return create(content, 250);case MIDDLE:return create(content, 350);case BIG:default:return create(content, 500);}}}// ======================== 存入文件 =========================/*** 存入文件** @param barCodeImage* @return 文件名*/public static String toFile(BufferedImage barCodeImage) {String fileName = getFileName();boolean isWrite = false;try {FileOutputStream outputStream = new FileOutputStream(new File(getImageDir(), fileName));isWrite = ImageIO.write(barCodeImage, "png", outputStream);} catch (IOException e) {e.printStackTrace();}if (isWrite) {return fileName;}return "";}/*** 得到图片存放目录* 类路径下的image文件夹** @return*/private static String getImageDir() {String imageDir = "";Resource resource = new ClassPathResource("");try {String _dir = resource.getFile().getAbsolutePath();File file = new File(_dir, "image");if (!file.exists()) {file.mkdirs();}imageDir = file.getAbsolutePath();} catch (IOException e) {e.printStackTrace();}return imageDir;}/*** 生成文件名* 当前时间戳 + 两位随机数** @return*/private static String getFileName() {// 当前时间戳long second = Instant.now().getEpochSecond();// 两位随机数ThreadLocalRandom r = ThreadLocalRandom.current();int rand = r.nextInt(10, 99);return new StringBuffer().append(second).append(rand).append(".png").toString();}// ======================= 识别图形码 ========================/*** 识别图形码(条形码/二维码)* ************************************************ ------ 条形码 ----------------------------------* 可以识别内容:手机号、纯数字、字母数字、网址(中大号)* 识别不了小号(250x150)含文字的网址条形码* 存储网址时用二维码,不要使用条形码* ************************************************ ------ 二维码 ----------------------------------* 比条形码有优势;能识别三种尺寸的网址二维码* ************************************************* @param imageCode 图形码文件* @return void*/public static String scan(File imageCode) {String text = "";try {BufferedImage image = ImageIO.read(imageCode);if (image == null) {return text;}LuminanceSource source = new BufferedImageLuminanceSource(image);BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));Map<DecodeHintType, Object> hints = new HashMap<>(3);hints.put(DecodeHintType.CHARACTER_SET, "UTF-8");hints.put(DecodeHintType.PURE_BARCODE, Boolean.TRUE);hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);Result result = new MultiFormatReader().decode(bitmap, hints);text = result.getText();} catch (Exception e) {e.printStackTrace();System.out.println("无法识别");}return text;}public static String scan(String fileName) {return scan(new File(getImageDir(), fileName));}public static String scan(String fileName, String fileParent) {return scan(new File(fileParent, fileName));}
}

参考自:Java生成读取条形码及二维码

java生成、识别条形码和二维码相关推荐

  1. Java 创建/识别条形码、二维码

    条形码(Barcode)是将宽度不等的多个黑条和空白,按照一定的编码规则排列,用以表达一组信息的图形标识符.常用于标示物品的生产国.制造厂家.商品名称.生产日期.图书分类号.邮件起止地点.类别.日期等 ...

  2. Opencv+ZBar识别条形码、二维码

    文章目录 Opencv识别条形码.二维码 1.ZBar环境配置 2.一维码(条形码)识别 3. 二维码的识别 4. Opencv识别二维码 结束 Opencv识别条形码.二维码 最近的一次作业,恰好之 ...

  3. winform中实现打开摄像头+识别条形码和二维码

    我们去菜鸟驿站拿快递的时候,需要我们把自己的快递拿到扫描台上扫下,表示包裹已出库.今天我们就来实现这个功能,基于winform程序开发快递单的扫描和识别,顺便也识别下二维码.用到的组件有2个,分别是A ...

  4. Java生成微信小程序二维码

    Java生成微信小程序二维码 import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.Byt ...

  5. Spire.Barcode for Java组件(二)识别条形码、二维码

    Spire.Barcode for Java支持生成多种一维.二维条码,例如Code 128,Pdf 417以及QR code等,同时它也支持从图片上识别这些条码.上篇文章-Spire.Barcode ...

  6. 批量识别条形码和二维码

    依赖 <dependency><groupId>net.sf.barcode4j</groupId><artifactId>barcode4j-ligh ...

  7. Java生成中间logo的二维码(还可以加上二维码名称哦)

    最近有负责微信开发,对于微信开发的项目,肯定少不了二维码啦,正好有个这样的需求,这对不同的商品生成一个二维码,扫码即刻下单.博主就弄了一个二维码生成的工具类. 弄出来之后,产品经理又说了,中间放上公司 ...

  8. Java生成微信小程序二维码,5种实现方式,一个比一个简单

    文章目录 前言 先看官网 一.JDK自带的URLConnection方式 二.Apache的HttpClient方式 三.okhttp3方式 四.Unirest方式 五.RestTemplate方式 ...

  9. 【java】Java生成微信小程序二维码

    文章目录 前言 应用场景 微信小程序官网 1.RestTemplate方式 核心代码 getAccessToken 2. Unirest方式 Maven依赖 核心代码 3. okhttp3方式 Mav ...

最新文章

  1. android 跳转到应用市场
  2. lodash(一)数组
  3. 安装Oracle 10g sys,system 密码忘记设置解决办法
  4. 第5周实践项目1 顺序栈建立的算法库
  5. java核心标签库,16.JSTL标签库(我的JavaEE笔记)
  6. mysql批量生成修改表和列注释语句
  7. No virtual method diskCacheStrategy
  8. css z-index
  9. 微博办公李国庆:急招副总裁,提请股权激励,希望俞渝同意
  10. 51单片机入门教程(5)——定时器中断
  11. 云计算与云原生 — ETCD 数据库完全解析
  12. 从写作到演讲,虾米君不断尝试的 2021|年终回顾
  13. Thunderbolt3 方案介绍及应用案例介绍
  14. 简单上手理解Dav框架
  15. NB-IoT是什么?
  16. 修改我的世界服务器怪物爆率,精英生成概率以及部分能力参数设置_我的世界精英怪mod教程如何调控怪物属性和掉落物__单机攻略_跑跑车单机游戏网...
  17. vivado 2018.2官方下载
  18. matlab视网膜血管分割,视网膜血管增强与分割算法研究
  19. 10、类和对象:使用日期类计算相隔天数
  20. 智慧校园一卡通全场景解决方案(附原版PPT下载)

热门文章

  1. 记录排查rocketMQ-broker-JVM进程消失问题
  2. 使用 React Hooks实现一个返回顶部的按钮
  3. 应用时间序列分析清华大学出版社电子版_时间序列分析简介
  4. 【顶】利用分子分母有理化或者平方开方解题的典型及一道待解决的问题
  5. 我想是我该离开九又四分之三站台的时候了
  6. 如果你用String.spit(“|”)
  7. 人间真实:最烂代码排行榜!!!
  8. 计算机学院的迎新晚会,计算机学院举办迎新晚会
  9. 振兴会杜振国 目前传统基建板块的情况
  10. 3D渲染数学基础(2)向量