fei
1 天以前 9b1b0782ecb77d6ee958774da94606478482b063
archiveManager/src/main/java/com/ruoyi/service/impl/BarcodeService.java
@@ -1,34 +1,336 @@
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 {
    public byte[] generateBarcodeImage(String barcodeText) {
    /**
     * 添加文字到条码(优化版本)
     */
    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 {
            Code128Bean barcodeGenerator = new Code128Bean();
            final int dpi = 160;
            barcodeGenerator.setModuleWidth(0.58);
            barcodeGenerator.setBarHeight(14.2); // 设置条形码高度为64
            barcodeGenerator.doQuietZone(false);
            BarcodeFormat format = BarcodeFormat.CODE_39;
            Code39Writer writer = new Code39Writer();
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            BitmapCanvasProvider canvas = new BitmapCanvasProvider(
                    outputStream, "image/png", dpi, BufferedImage.TYPE_BYTE_BINARY, false, 0);
            // 编码参数 - 设置边距为0
            Map<EncodeHintType, Object> hints = new HashMap<>();
            hints.put(EncodeHintType.MARGIN, 0); // 关键:设置边距为0
            barcodeGenerator.generateBarcode(canvas, barcodeText);
            canvas.finish();
            // 生成 BitMatrix(纯条码,无文字)
            // 注意:即使设置了MARGIN=0,ZXing可能仍会保留最小边距
            BitMatrix matrix = writer.encode(barcodeText, format, 1300, 141, hints);
            return outputStream.toByteArray();
            // 方案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);
        }
    }
}