001package top.cenze.utils;
002
003import cn.hutool.core.util.StrUtil;
004import com.google.zxing.BarcodeFormat;
005import com.google.zxing.EncodeHintType;
006import com.google.zxing.MultiFormatWriter;
007import com.google.zxing.WriterException;
008import com.google.zxing.client.j2se.MatrixToImageWriter;
009import com.google.zxing.common.BitMatrix;
010import com.google.zxing.oned.Code128Writer;
011
012import java.awt.*;
013import java.awt.image.BufferedImage;
014import java.util.HashMap;
015import java.util.Map;
016
017/**
018 * 条形码工具类
019 */
020public class BarCodeUtil {
021    /** 条形码宽度 */
022    private static final int WIDTH = 390;
023
024    /** 条形码高度 */
025    private static final int HEIGHT = 50;
026
027    /** 加文字 条形码 */
028    private static final int WORDHEIGHT = 75;
029
030    /**
031     * 设置 条形码参数
032     */
033    private static Map<EncodeHintType, Object> hints = new HashMap<EncodeHintType, Object>() {
034        private static final long serialVersionUID = 1L;
035        {
036            // 设置编码方式
037            put(EncodeHintType.CHARACTER_SET, "utf-8");
038        }
039    };
040
041    /**
042     * 生成 图片缓冲
043     * @author fxbin
044     * @param vaNumber  VA 码
045     * @return 返回BufferedImage
046     */
047    public static BufferedImage getBarCode(String vaNumber){
048        return getBarCode(vaNumber, WIDTH, HEIGHT);
049    }
050
051    /**
052     * 生成 图片缓冲
053     * @author fxbin
054     * @param vaNumber  VA 码
055     * @return 返回BufferedImage
056     */
057    public static BufferedImage getBarCode(String vaNumber, int width, int height){
058        try {
059            Code128Writer writer = new Code128Writer();
060            if (0 == width) {
061                width = writer.encode(vaNumber).length; // 为了无边距,需设置宽度为条码自动生成规则的宽度
062            }
063            if (0 == height) {
064                height = HEIGHT;
065            }
066            //条码放大倍数
067            int codeMultiples = 1;
068            //获取条码内容的宽,不含两边距,当EncodeHintType.MARGIN为0时即为条码宽度
069            int codeWidth = width * codeMultiples;
070
071            // 图像数据转换,使用了矩阵转换 参数顺序分别为:编码内容,编码类型,生成图片宽度,生成图片高度,设置参数
072            BitMatrix bitMatrix = new MultiFormatWriter().encode(vaNumber,
073                    BarcodeFormat.CODE_128, codeWidth, height, hints);
074
075            // 编码内容, 编码类型, 宽度, 高度, 设置参数
076//            BitMatrix bitMatrix = writer.encode(vaNumber, BarcodeFormat.CODE_128, width, height, hints);
077            return MatrixToImageWriter.toBufferedImage(bitMatrix);
078        } catch (WriterException e) {
079            e.printStackTrace();
080        }
081        return null;
082    }
083
084    /**
085     * 把带logo的二维码下面加上文字
086     * @author fxbin
087     * @param image  条形码图片
088     * @param words  文字
089     * @return 返回BufferedImage
090     */
091    public static BufferedImage insertWords(BufferedImage image, String words){
092        // 新的图片,把带logo的二维码下面加上文字
093        if (StrUtil.isEmpty(words)) {
094            return null;
095        }
096
097        BufferedImage outImage = new BufferedImage(WIDTH, WORDHEIGHT, BufferedImage.TYPE_INT_RGB);
098
099        Graphics2D g2d = outImage.createGraphics();
100
101        // 抗锯齿
102        setGraphics2D(g2d);
103        // 设置白色
104        setColorWhite(g2d);
105
106        // 画条形码到新的面板
107        g2d.drawImage(image, 0, 0, image.getWidth(), image.getHeight(), null);
108        // 画文字到新的面板
109        Color color=new Color(0, 0, 0);
110        g2d.setColor(color);
111        // 字体、字型、字号
112        g2d.setFont(new Font("微软雅黑", Font.PLAIN, 18));
113        //文字长度
114        int strWidth = g2d.getFontMetrics().stringWidth(words);
115        //总长度减去文字长度的一半  (居中显示)
116        int wordStartX=(WIDTH - strWidth) / 2;
117        //height + (outImage.getHeight() - height) / 2 + 12
118        int wordStartY=HEIGHT+20;
119
120        // 画文字
121        g2d.drawString(words, wordStartX, wordStartY);
122        g2d.dispose();
123        outImage.flush();
124        return outImage;
125    }
126
127    /**
128     * 设置 Graphics2D 属性  (抗锯齿)
129     * @param g2d  Graphics2D提供对几何形状、坐标转换、颜色管理和文本布局更为复杂的控制
130     */
131    private static void setGraphics2D(Graphics2D g2d){
132        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
133        g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_DEFAULT);
134        Stroke s = new BasicStroke(1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER);
135        g2d.setStroke(s);
136    }
137
138    /**
139     * 设置背景为白色
140     * @param g2d Graphics2D提供对几何形状、坐标转换、颜色管理和文本布局更为复杂的控制
141     */
142    private static void setColorWhite(Graphics2D g2d){
143        g2d.setColor(Color.WHITE);
144        //填充整个屏幕
145        g2d.fillRect(0,0,600,600);
146        //设置笔刷
147        g2d.setColor(Color.BLACK);
148    }
149
150//    public static void main(String[] args)  {
151//        BufferedImage image = insertWords(getBarCode("XXXXX"), "XXXXX");
152//        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
153//        try {
154//            ImageIO.write(image, "png", outputStream);
155//            //转Base64
156//            System.out.println(Base64.encodeBase64String(outputStream.toByteArray()));
157//        } catch (IOException e) {
158//            e.printStackTrace();
159//        }
160//    }
161}