package com.ruoyi.service.impl;
|
|
import com.google.zxing.BarcodeFormat;
|
import com.google.zxing.EncodeHintType;
|
import com.google.zxing.WriterException;
|
import com.google.zxing.common.BitMatrix;
|
import com.google.zxing.oned.Code128Writer;
|
import com.google.zxing.oned.Code39Writer;
|
import org.krysalis.barcode4j.impl.code128.Code128Bean;
|
import org.krysalis.barcode4j.output.bitmap.BitmapCanvasProvider;
|
import org.springframework.stereotype.Service;
|
|
import javax.imageio.ImageIO;
|
import java.awt.*;
|
import java.awt.image.BufferedImage;
|
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayOutputStream;
|
import java.io.IOException;
|
import java.lang.reflect.Method;
|
import java.util.HashMap;
|
import java.util.Map;
|
|
@Service
|
|
public class BarcodeService {
|
/**
|
* 添加文字到条码(优化版本)
|
*/
|
private void addTextToBarcode(Graphics2D g2d, String text, int width, int barcodeHeight) {
|
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
|
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
|
|
// 使用更清晰的字体
|
Font font = new Font("Tahoma", Font.PLAIN, 45);
|
g2d.setFont(font);
|
g2d.setColor(Color.BLACK);
|
|
// 计算文字位置
|
FontMetrics fm = g2d.getFontMetrics();
|
int textWidth = fm.stringWidth(text);
|
int textHeight = fm.getHeight();
|
|
// 居中对齐
|
int x = (width - textWidth) / 2;
|
int y = barcodeHeight + textHeight - fm.getDescent(); // 精确垂直居中
|
|
// 绘制文字
|
g2d.drawString(text, x, y);
|
}
|
public byte[] generateBarcodeImage(String barcodeText) {
|
try {
|
BarcodeFormat format = BarcodeFormat.CODE_39;
|
Code39Writer writer = new Code39Writer();
|
|
// 编码参数 - 设置边距为0
|
Map<EncodeHintType, Object> hints = new HashMap<>();
|
hints.put(EncodeHintType.MARGIN, 0); // 关键:设置边距为0
|
|
// 生成 BitMatrix(纯条码,无文字)
|
// 注意:即使设置了MARGIN=0,ZXing可能仍会保留最小边距
|
BitMatrix matrix = writer.encode(barcodeText, format, 1300, 141, hints);
|
|
// 方案1.1:直接裁剪白边
|
return generateBarcodeWithCroppedMargin(matrix, barcodeText);
|
}
|
catch (IOException e) {
|
throw new RuntimeException("Error generating barcode", e);
|
} catch (WriterException e) {
|
throw new RuntimeException(e);
|
}
|
}
|
|
private byte[] generateBarcodeWithCroppedMargin(BitMatrix matrix, String barcodeText) throws IOException {
|
int width = matrix.getWidth();
|
int height = matrix.getHeight();
|
|
// 找到条码的实际边界
|
int left = findLeftBoundary(matrix);
|
int right = findRightBoundary(matrix);
|
int top = findTopBoundary(matrix);
|
int bottom = findBottomBoundary(matrix);
|
|
// 计算条码的实际宽度和高度
|
int barcodeWidth = right - left + 1;
|
int barcodeHeight = bottom - top + 1;
|
|
// 计算文字区域高度
|
int textAreaHeight = 30 + 27;
|
|
// 创建最终图像(精确尺寸)
|
BufferedImage finalImage = new BufferedImage(
|
barcodeWidth,
|
barcodeHeight + textAreaHeight,
|
BufferedImage.TYPE_BYTE_BINARY
|
);
|
|
Graphics2D g2d = finalImage.createGraphics();
|
|
// 白色背景
|
g2d.setColor(Color.WHITE);
|
g2d.fillRect(0, 0, barcodeWidth, barcodeHeight + textAreaHeight);
|
|
// 绘制条码(只绘制有效部分)
|
g2d.setColor(Color.BLACK);
|
for (int x = left; x <= right; x++) {
|
for (int y = top; y <= bottom; y++) {
|
if (matrix.get(x, y)) {
|
g2d.fillRect(x - left, y - top, 1, 1);
|
}
|
}
|
}
|
|
// 添加自定义文字
|
addTextToBarcode(g2d, barcodeText, barcodeWidth, barcodeHeight);
|
|
g2d.dispose();
|
|
// 保存
|
ByteArrayOutputStream resultStream = new ByteArrayOutputStream();
|
ImageIO.write(finalImage, "png", resultStream);
|
|
return resultStream.toByteArray();
|
}
|
|
// 辅助方法:找到条码的边界
|
private int findLeftBoundary(BitMatrix matrix) {
|
int width = matrix.getWidth();
|
int height = matrix.getHeight();
|
|
for (int x = 0; x < width; x++) {
|
for (int y = 0; y < height; y++) {
|
if (matrix.get(x, y)) {
|
return x;
|
}
|
}
|
}
|
return 0;
|
}
|
|
private int findRightBoundary(BitMatrix matrix) {
|
int width = matrix.getWidth();
|
int height = matrix.getHeight();
|
|
for (int x = width - 1; x >= 0; x--) {
|
for (int y = 0; y < height; y++) {
|
if (matrix.get(x, y)) {
|
return x;
|
}
|
}
|
}
|
return width - 1;
|
}
|
|
private int findTopBoundary(BitMatrix matrix) {
|
int width = matrix.getWidth();
|
int height = matrix.getHeight();
|
|
for (int y = 0; y < height; y++) {
|
for (int x = 0; x < width; x++) {
|
if (matrix.get(x, y)) {
|
return y;
|
}
|
}
|
}
|
return 0;
|
}
|
|
private int findBottomBoundary(BitMatrix matrix) {
|
int width = matrix.getWidth();
|
int height = matrix.getHeight();
|
|
for (int y = height - 1; y >= 0; y--) {
|
for (int x = 0; x < width; x++) {
|
if (matrix.get(x, y)) {
|
return y;
|
}
|
}
|
}
|
return height - 1;
|
}
|
|
|
|
|
public byte[] generateBarcodeImage1(String barcodeText) {
|
try {
|
// 使用 BitMatrix 生成纯条码,不包含任何文字
|
BarcodeFormat format = BarcodeFormat.CODE_39; // 根据您的条码类型
|
|
// 创建编码器
|
Code39Writer writer = new Code39Writer();
|
|
// 编码参数
|
Map<EncodeHintType, Object> hints = new HashMap<>();
|
hints.put(EncodeHintType.MARGIN, 0); // 无边框
|
|
// 生成 BitMatrix(纯条码,无文字)
|
BitMatrix matrix = writer.encode(barcodeText, format, 1128, 199, hints);
|
|
int width = matrix.getWidth();
|
int height = matrix.getHeight();
|
|
// 计算文字区域
|
int textAreaHeight = 30 + 10;
|
|
// 创建最终图像
|
BufferedImage finalImage = new BufferedImage(
|
width,
|
height + textAreaHeight,
|
BufferedImage.TYPE_BYTE_BINARY
|
);
|
|
Graphics2D g2d = finalImage.createGraphics();
|
|
// 白色背景
|
g2d.setColor(Color.WHITE);
|
g2d.fillRect(0, 0, width, height + textAreaHeight);
|
|
// 绘制条码(从 BitMatrix)
|
g2d.setColor(Color.BLACK);
|
for (int x = 0; x < width; x++) {
|
for (int y = 0; y < height; y++) {
|
if (matrix.get(x, y)) {
|
g2d.fillRect(x, y, 1, 1);
|
}
|
}
|
}
|
|
// 添加自定义文字
|
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
|
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
|
g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
|
|
Font font = new Font("Tahoma", Font.PLAIN, 18);
|
g2d.setFont(font);
|
|
FontMetrics fm = g2d.getFontMetrics();
|
int textWidth = fm.stringWidth(barcodeText);
|
int x = (width - textWidth) / 2;
|
int y = height + 30 - 5; // 调整垂直位置
|
|
g2d.drawString(barcodeText, x, y);
|
g2d.dispose();
|
|
// 保存
|
ByteArrayOutputStream resultStream = new ByteArrayOutputStream();
|
ImageIO.write(finalImage, "png", resultStream);
|
|
return resultStream.toByteArray();
|
// return outputStream.toByteArray();
|
} catch (IOException e) {
|
throw new RuntimeException("Error generating barcode", e);
|
} catch (WriterException e) {
|
throw new RuntimeException(e);
|
}
|
}
|
|
|
|
|
public byte[] generateBarcodeImageScarn(String barcodeText) {
|
try {
|
// 使用 BitMatrix 生成纯条码,不包含任何文字
|
BarcodeFormat format = BarcodeFormat.CODE_39; // 根据您的条码类型
|
|
// 创建编码器
|
Code39Writer writer = new Code39Writer();
|
|
// 编码参数
|
Map<EncodeHintType, Object> hints = new HashMap<>();
|
hints.put(EncodeHintType.MARGIN, 0); // 无边框
|
|
// 生成 BitMatrix(纯条码,无文字)
|
BitMatrix matrix = writer.encode(barcodeText, format, 230, 63, hints);
|
|
int width = matrix.getWidth();
|
int height = matrix.getHeight();
|
|
// 计算文字区域
|
int textAreaHeight = 30 + 10;
|
|
// 创建最终图像
|
BufferedImage finalImage = new BufferedImage(
|
width,
|
height + textAreaHeight,
|
BufferedImage.TYPE_BYTE_BINARY
|
);
|
|
Graphics2D g2d = finalImage.createGraphics();
|
|
// 白色背景
|
g2d.setColor(Color.WHITE);
|
g2d.fillRect(0, 0, width, height + textAreaHeight);
|
|
// 绘制条码(从 BitMatrix)
|
g2d.setColor(Color.BLACK);
|
for (int x = 0; x < width; x++) {
|
for (int y = 0; y < height; y++) {
|
if (matrix.get(x, y)) {
|
g2d.fillRect(x, y, 1, 1);
|
}
|
}
|
}
|
|
// 添加自定义文字
|
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
|
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
|
g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
|
|
Font font = new Font("Tahoma", Font.PLAIN, 18);
|
g2d.setFont(font);
|
|
FontMetrics fm = g2d.getFontMetrics();
|
int textWidth = fm.stringWidth(barcodeText);
|
int x = (width - textWidth) / 2;
|
int y = height + 30 - 5; // 调整垂直位置
|
|
g2d.drawString(barcodeText, x, y);
|
g2d.dispose();
|
|
// 保存
|
ByteArrayOutputStream resultStream = new ByteArrayOutputStream();
|
ImageIO.write(finalImage, "png", resultStream);
|
|
return resultStream.toByteArray();
|
// return outputStream.toByteArray();
|
} catch (IOException e) {
|
throw new RuntimeException("Error generating barcode", e);
|
} catch (WriterException e) {
|
throw new RuntimeException(e);
|
}
|
}
|
}
|