java生成、识别条形码和二维码
一、概述
使用
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生成、识别条形码和二维码相关推荐
- Java 创建/识别条形码、二维码
条形码(Barcode)是将宽度不等的多个黑条和空白,按照一定的编码规则排列,用以表达一组信息的图形标识符.常用于标示物品的生产国.制造厂家.商品名称.生产日期.图书分类号.邮件起止地点.类别.日期等 ...
- Opencv+ZBar识别条形码、二维码
文章目录 Opencv识别条形码.二维码 1.ZBar环境配置 2.一维码(条形码)识别 3. 二维码的识别 4. Opencv识别二维码 结束 Opencv识别条形码.二维码 最近的一次作业,恰好之 ...
- winform中实现打开摄像头+识别条形码和二维码
我们去菜鸟驿站拿快递的时候,需要我们把自己的快递拿到扫描台上扫下,表示包裹已出库.今天我们就来实现这个功能,基于winform程序开发快递单的扫描和识别,顺便也识别下二维码.用到的组件有2个,分别是A ...
- Java生成微信小程序二维码
Java生成微信小程序二维码 import java.io.BufferedInputStream; import java.io.BufferedReader; import java.io.Byt ...
- Spire.Barcode for Java组件(二)识别条形码、二维码
Spire.Barcode for Java支持生成多种一维.二维条码,例如Code 128,Pdf 417以及QR code等,同时它也支持从图片上识别这些条码.上篇文章-Spire.Barcode ...
- 批量识别条形码和二维码
依赖 <dependency><groupId>net.sf.barcode4j</groupId><artifactId>barcode4j-ligh ...
- Java生成中间logo的二维码(还可以加上二维码名称哦)
最近有负责微信开发,对于微信开发的项目,肯定少不了二维码啦,正好有个这样的需求,这对不同的商品生成一个二维码,扫码即刻下单.博主就弄了一个二维码生成的工具类. 弄出来之后,产品经理又说了,中间放上公司 ...
- Java生成微信小程序二维码,5种实现方式,一个比一个简单
文章目录 前言 先看官网 一.JDK自带的URLConnection方式 二.Apache的HttpClient方式 三.okhttp3方式 四.Unirest方式 五.RestTemplate方式 ...
- 【java】Java生成微信小程序二维码
文章目录 前言 应用场景 微信小程序官网 1.RestTemplate方式 核心代码 getAccessToken 2. Unirest方式 Maven依赖 核心代码 3. okhttp3方式 Mav ...
最新文章
- android 跳转到应用市场
- lodash(一)数组
- 安装Oracle 10g sys,system 密码忘记设置解决办法
- 第5周实践项目1 顺序栈建立的算法库
- java核心标签库,16.JSTL标签库(我的JavaEE笔记)
- mysql批量生成修改表和列注释语句
- No virtual method diskCacheStrategy
- css z-index
- 微博办公李国庆:急招副总裁,提请股权激励,希望俞渝同意
- 51单片机入门教程(5)——定时器中断
- 云计算与云原生 — ETCD 数据库完全解析
- 从写作到演讲,虾米君不断尝试的 2021|年终回顾
- Thunderbolt3 方案介绍及应用案例介绍
- 简单上手理解Dav框架
- NB-IoT是什么?
- 修改我的世界服务器怪物爆率,精英生成概率以及部分能力参数设置_我的世界精英怪mod教程如何调控怪物属性和掉落物__单机攻略_跑跑车单机游戏网...
- vivado 2018.2官方下载
- matlab视网膜血管分割,视网膜血管增强与分割算法研究
- 10、类和对象:使用日期类计算相隔天数
- 智慧校园一卡通全场景解决方案(附原版PPT下载)
热门文章
- 记录排查rocketMQ-broker-JVM进程消失问题
- 使用 React Hooks实现一个返回顶部的按钮
- 应用时间序列分析清华大学出版社电子版_时间序列分析简介
- 【顶】利用分子分母有理化或者平方开方解题的典型及一道待解决的问题
- 我想是我该离开九又四分之三站台的时候了
- 如果你用String.spit(“|”)
- 人间真实:最烂代码排行榜!!!
- 计算机学院的迎新晚会,计算机学院举办迎新晚会
- 振兴会杜振国 目前传统基建板块的情况
- 3D渲染数学基础(2)向量