条码支持二维码

This commit is contained in:
DESKTOP-J7ED0MB\yinjinlu 2022-10-17 22:00:50 +08:00
parent 9663752099
commit adbe071c05
4 changed files with 202 additions and 33 deletions

View File

@ -144,6 +144,12 @@
<version>2.0</version> <version>2.0</version>
</dependency> </dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.3.3</version>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -184,4 +184,12 @@ public class UserConstants
public static final String VIRTUAL_WS ="XBKKQ_VIRTUAL"; public static final String VIRTUAL_WS ="XBKKQ_VIRTUAL";
public static final String VIRTUAL_WA ="XBKKW_VIRTUAL"; public static final String VIRTUAL_WA ="XBKKW_VIRTUAL";
/**
* 条码类型
*/
public static final String QR_CODE = "QR_CODE";
public static final String EAN_CODE = "EAN_CODE";
public static final String UPC_CODE = "UPC_CODE";
public static final String CODE39_CODE = "CODE39_CODE";
} }

View File

@ -1,59 +1,102 @@
package com.ktg.common.utils.barcode; package com.ktg.common.utils.barcode;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import com.ktg.common.constant.UserConstants;
import com.ktg.common.utils.StringUtils; import com.ktg.common.utils.StringUtils;
import org.krysalis.barcode4j.impl.AbstractBarcodeBean;
import org.krysalis.barcode4j.impl.code39.Code39Bean; import org.krysalis.barcode4j.impl.code39.Code39Bean;
import org.krysalis.barcode4j.impl.upcean.EAN13Bean;
import org.krysalis.barcode4j.impl.upcean.UPCABean;
import org.krysalis.barcode4j.output.bitmap.BitmapCanvasProvider; import org.krysalis.barcode4j.output.bitmap.BitmapCanvasProvider;
import org.krysalis.barcode4j.tools.UnitConv; import org.krysalis.barcode4j.tools.UnitConv;
import java.io.ByteArrayOutputStream; import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.io.FileNotFoundException; import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.util.Map;
import java.io.File; import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
public class BarcodeUtil { public class BarcodeUtil {
private static final String CHARSET = "utf-8";
public static File generateFile(String msg, String path) { private static final String FORMAT_NAME = "PNG";
// 二维码尺寸长宽尺寸一致
private static final int QRCODE_SIZE = 300;
// 二维码内部logo的宽和高
private static final int WIDTH = 60;
private static final int HEIGHT = 60;
public static File generateBarCode(String msg, String barCodeFormat, String path) {
File file = new File(path); File file = new File(path);
try { try {
generate(msg, new FileOutputStream(file)); if(StringUtils.isEmpty(msg)){
} catch (FileNotFoundException e) { throw new RuntimeException("条码内容不能为空!");
throw new RuntimeException(e); }
} //检查父级目录是否存在不存在先新建
File parentFile = file.getParentFile();
if(!parentFile.exists()){
parentFile.mkdirs();
}
/*
* 生成条码
*/
if(UserConstants.QR_CODE.equals(barCodeFormat)){
//生成二维码
generateQRCode(msg, null, file.getAbsolutePath(), false);
}else{
//生成一维码
generateLineCode(msg, barCodeFormat, file.getAbsolutePath());
}
}catch (Exception e) {
throw new RuntimeException("生成条码发生错误:"+e.getMessage());
}
return file; return file;
} }
/**
public static byte[] generate(String msg) { * 生成一维条形码
ByteArrayOutputStream ous = new ByteArrayOutputStream(); * @param msg 条形码的内容
generate(msg, ous); * @param barCodeFormat 条形码格式 see {@link UserConstants}
return ous.toByteArray(); * @param destFilePath 条形码存储的路径
} * @throws Exception
*/
public static void generateLineCode(String msg,String barCodeFormat,String destFilePath) throws Exception {
public static void generate(String msg, OutputStream ous) { AbstractBarcodeBean bean = null;
if (StringUtils.isEmpty(msg) || ous == null) { if(UserConstants.EAN_CODE.equals(barCodeFormat)){
return; bean = new EAN13Bean();
} }else if(UserConstants.CODE39_CODE.equals(barCodeFormat)){
bean = new Code39Bean();
Code39Bean bean = new Code39Bean(); }else if(UserConstants.UPC_CODE.equals(barCodeFormat)){
bean = new UPCABean();
}else{
throw new Exception("不支持的条码类型!");
}
// 精细度 // 精细度
final int dpi = 150; final int dpi = 150;
// module宽度 if (bean instanceof Code39Bean) {
final double moduleWidth = UnitConv.in2mm(1.0f / dpi); Code39Bean codeBean = (Code39Bean) bean;
// module宽度
final double moduleWidth = UnitConv.in2mm(1.0f / dpi);
// 配置对象 // 配置对象
bean.setModuleWidth(moduleWidth); bean.setModuleWidth(moduleWidth);
bean.setWideFactor(3); codeBean.setWideFactor(3);
bean.doQuietZone(false); bean.doQuietZone(false);
}
String format = "image/png"; String format = "image/png";
try { try {
// 输出到流 // 输出到流
BitmapCanvasProvider canvas = new BitmapCanvasProvider(ous, format, dpi, BitmapCanvasProvider canvas = new BitmapCanvasProvider(new FileOutputStream(destFilePath), format, dpi,
BufferedImage.TYPE_BYTE_BINARY, false, 0); BufferedImage.TYPE_BYTE_BINARY, false, 0);
// 生成条形码 // 生成条形码
@ -65,4 +108,110 @@ public class BarcodeUtil {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} }
/**
* 生成带logo二维码并保存到磁盘
*
* @param content 二维码的内容
* @param imgPath 二维码内部插入的图片路径如果不需要可以传空
* @param destFilePath 整个二维码存储的路径
* @param needCompress 二维码内部插入的图片是否需要压缩的标识
* @throws Exception 异常
*/
public static void generateQRCode(String content, String imgPath, String destFilePath, boolean needCompress) throws Exception {
BufferedImage image = createQrCode(content, imgPath, needCompress);
ImageIO.write(image, FORMAT_NAME, new File(destFilePath));
}
/**
* 生成二维码图片
*
* @param content 二维码内容
* @param imagePath 二维码内部图片路径,如果不需要可以传空
* @param needCompress 二维码内部图片是否需要压缩标识
* @return 二维码图片
* @throws WriterException 异常
*/
private static BufferedImage createQrCode(String content,String imagePath,boolean needCompress) throws WriterException, IOException {
/**
* EncodeHintType 编码提示类型 枚举类型:
* CHARACTER_SET: 设置字符编码类型 "UTF-8" QR_CODE类型默认的编码格式 "ISO-8859-1"
* MARGIN: 设置二维码边距单位像素值越小二维码距离四周越近
* ERROR_CORRECTION: 设置误差校正
* ErrorCorrectionLevel误差校正等级L = ~7% correctionM = ~15% correctionQ = ~25% correctionH = ~30% correction
* 不设置时默认为 L 等级等级不一样生成的图案不同但扫描的结果是一样的
*/
Map<EncodeHintType, Object> hints = new ConcurrentHashMap<>(3);
hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
hints.put(EncodeHintType.CHARACTER_SET, CHARSET);
hints.put(EncodeHintType.MARGIN, 1);
//加密生成二维码的矩阵对象 二维的0 1 然后根据特定的值选择属性
BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, QRCODE_SIZE, QRCODE_SIZE, hints);
int width = bitMatrix.getWidth();
int height = bitMatrix.getHeight();
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
//设置二维码的黑色0xFF000000 和白色0xFFFFFFFF
image.setRGB(i, j, bitMatrix.get(i, j) ? 0xFF000000 : 0xFFFFFFFF);
}
}
if (StringUtils.isBlank(imagePath)) {
return image;
}
//插入小图标 logo
insertImage(image, imagePath, needCompress);
return image;
}
/**
* 将logo插入二维码中间
*
* @param source 生成的二位码存储对象
* @param imagePath 二维码内部图片的路径
* 一般的业务场景会把插入的小logo放到oss生成url
* @param needCompress 二维码内部图片是否需要压缩
* @throws IOException 异常
*/
private static void insertImage(BufferedImage source, String imagePath, boolean needCompress) throws IOException {
File file = new File(imagePath);
if (!file.exists()) {
//可以自定义抛出异常
throw new RuntimeException("文件路径不存在:" + imagePath);
}
//这里修改ImageIO.read() 内可以接受Url InputStream File ImageInputStream
Image src = ImageIO.read(file);
int width = src.getWidth(null);
int height = src.getHeight(null);
//是否压缩
if (needCompress) {
if (width > WIDTH) {
width = WIDTH;
}
if (height > HEIGHT) {
height = HEIGHT;
}
Image image = src.getScaledInstance(width, height, Image.SCALE_SMOOTH);
BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics g = tag.getGraphics();
g.drawImage(image, 0, 0, null);
g.dispose();
src = image;
}
Graphics2D graphics = source.createGraphics();
int x = (QRCODE_SIZE - width) / 2;
int y = (QRCODE_SIZE - height) / 2;
graphics.drawImage(src,x,y,width,height,null);
Shape shape = new RoundRectangle2D.Float(x, y, width, width, 6, 6);
graphics.setStroke(new BasicStroke(3f));
graphics.draw(shape);
graphics.dispose();
}
public static void main(String[] args) {
String msg="item12345678";
String EANmsg="012345678901";
String UPCmsg="12345678901";
String path = "D:/test/barcode/"+UUID.randomUUID()+".png";
generateBarCode(msg, UserConstants.QR_CODE, path);
}
} }

View File

@ -116,7 +116,8 @@ public class WmBarcodeServiceImpl implements IWmBarcodeService
@Override @Override
public String generateBarcode(WmBarcode wmBarcode) { public String generateBarcode(WmBarcode wmBarcode) {
File buf = BarcodeUtil.generateFile(wmBarcode.getBarcodeContent(),"./tmp/barcode/"+wmBarcode.getBarcodeContent()+".png"); File buf = BarcodeUtil.generateBarCode(wmBarcode.getBarcodeContent(), wmBarcode.getBarcodeFormart(),
"./tmp/barcode/" + wmBarcode.getBarcodeContent() + ".png");
MultipartFile file = FileUtils.getMultipartFile(buf); MultipartFile file = FileUtils.getMultipartFile(buf);
String fileName = null; String fileName = null;
try { try {
@ -124,6 +125,11 @@ public class WmBarcodeServiceImpl implements IWmBarcodeService
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
return null; return null;
}finally{
//删除掉临时文件
if(buf!=null && buf.exists()){
FileUtils.deleteFile(buf.getAbsolutePath());
}
} }
return fileName; return fileName;
} }