ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

zxing绘制条形码总结

2021-07-08 19:30:59  阅读:221  来源: 互联网

标签:条形码 String int image param zxing static new 绘制


基本使用

首先工程中导入zxing的依赖,如下:

<dependency>
   <groupId>com.google.zxing</groupId>
    <artifactId>core</artifactId>
    <version>3.3.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.google.zxing/javase -->
<dependency>
    <groupId>com.google.zxing</groupId>
    <artifactId>javase</artifactId>
    <version>3.3.3</version>
</dependency>

接着编写生成条形码的工具类,代码演示如下:

package com.example.demo.utils;

import java.awt.*;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import java.util.Random;

import javax.imageio.ImageIO;

import org.springframework.util.StringUtils;

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.oned.Code128Writer;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;

/**
 * 类描述: 二维码生成工具类
 *
 * @author jianweiwang
 * @version v1.0
 * @link wjw@choicesoft.com.cn
 * @date 2019/4/1 11:00
 **/
public class BarcodeUtils {
    private static final String CHARSET = "utf-8";
    private static final String FORMAT = "JPG";
    /**
     * 条形码宽度
     */
    private static final int WIDTH = 220;
    /**
     * 条形码高度
     */
    private static final int HEIGHT = 80;

    /**
     * 字体大小
     */
    private static final int FONT_SIZE = 28;

    /**
     * 加文字 条形码
     */
    private static final int WORD_HEIGHT = HEIGHT + FONT_SIZE;

    /**
     * 二维码尺寸
     */
    private static final int QR_CODE_SIZE = 300;
    /**
     * LOGO宽度
     */
    private static final int LOGO_WIDTH = 60;
    /**
     * LOGO高度
     */
    private static final int LOGO_HEIGHT = 60;

    /**
     * 设置 条形码参数
     */
    private static Map<EncodeHintType, Object> hints = new HashMap<>(5);

    static {
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
        hints.put(EncodeHintType.CHARACTER_SET, CHARSET);
        hints.put(EncodeHintType.MARGIN, 1);
    }

    /**
     * 生成 图片缓冲
     *
     * @param vaNumber VA 码
     * @return 返回BufferedImage
     * @author fxbin
     */
    public static BufferedImage getBarCode(String vaNumber) {
        try {
            Code128Writer writer = new Code128Writer();
            // 编码内容, 编码类型, 宽度, 高度, 设置参数
            BitMatrix bitMatrix = writer.encode(vaNumber, BarcodeFormat.CODE_128, WIDTH, HEIGHT, hints);
            return MatrixToImageWriter.toBufferedImage(bitMatrix);
        } catch (WriterException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 把带logo的二维码下面加上文字
     *
     * @param image 条形码图片
     * @param words 文字
     * @return 返回BufferedImage
     * @author fxbin
     */
    public static BufferedImage insertWords(BufferedImage image, String words) {
        // 新的图片,把带logo的二维码下面加上文字
        if (!StringUtils.isEmpty(words)) {
            BufferedImage outImage = new BufferedImage(WIDTH, WORD_HEIGHT, BufferedImage.TYPE_INT_RGB);
            Graphics2D g2d = outImage.createGraphics();
            // 抗锯齿
            setGraphics2D(g2d);
            // 设置白色
            setColorWhite(g2d);
            // 画条形码到新的面板
            g2d.drawImage(image, 0, 0, image.getWidth(), image.getHeight(), null);
            // 画文字到新的面板
            g2d.setColor(Color.BLACK);
            // 字体、字型、字号
            g2d.setFont(new Font("黑体", Font.PLAIN, FONT_SIZE));
            //设置条形码下面的文本的纵坐标
            int wordStartY = HEIGHT + 21;
            //-------------------------计算条形码的左边距,即左边空白的距离------------------------
            String content=words.substring(1,words.length()-1);
            int inputWidth = new Code128Writer().encode(content).length;
            int fullWidth = inputWidth + 1;
            int outputWidth = Math.max(WIDTH, fullWidth);
            int multiple = outputWidth / fullWidth;
            int leftPadding = (outputWidth - (inputWidth * multiple)) / 2;
            int x = leftPadding;
			//-----------------------计算条形码的左边距,即左边空白的距离----------------------

            String[] split = words.split("");
            int len = split.length;
            int step = new Long(Math.round(WIDTH - leftPadding * 2) / words.length()).intValue();
            for (int i = 0; i < len; i++) {
                g2d.drawString(split[i], x, wordStartY);
                x = x + step;
            }
            outImage.flush();
            return outImage;
        }
        return null;
    }


    /**
     * 设置 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) {
        g2d.setColor(Color.WHITE);
        // 填充整个屏幕
        g2d.fillRect(0, 0, 600, 600);
        // 设置笔刷
        g2d.setColor(Color.BLACK);
    }

    private static BufferedImage createImage(String content, String logoPath, boolean needCompress) throws Exception {
        BitMatrix bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, QR_CODE_SIZE, QR_CODE_SIZE,
                hints);
        int width = bitMatrix.getWidth();
        int height = bitMatrix.getHeight();
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                image.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);
            }
        }
        if (logoPath == null || "".equals(logoPath)) {
            return image;
        }
        // 插入图片
        BarcodeUtils.insertImage(image, logoPath, needCompress);
        return image;
    }

    /**
     * 插入LOGO
     *
     * @param source       二维码图片
     * @param logoPath     LOGO图片地址
     * @param needCompress 是否压缩
     * @throws Exception
     */
    private static void insertImage(BufferedImage source, String logoPath, boolean needCompress) throws Exception {
        File file = new File(logoPath);
        if (!file.exists()) {
            throw new Exception("logo file not found.");
        }
        Image src = ImageIO.read(new File(logoPath));
        int width = src.getWidth(null);
        int height = src.getHeight(null);
        // 是否压缩LOGO
        if (needCompress) {
            if (width > LOGO_WIDTH) {
                width = LOGO_WIDTH;
            }
            if (height > LOGO_HEIGHT) {
                height = LOGO_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;
        }
        // 插入LOGO
        Graphics2D graph = source.createGraphics();
        int x = (QR_CODE_SIZE - width) / 2;
        int y = (QR_CODE_SIZE - height) / 2;
        graph.drawImage(src, x, y, width, height, null);
        Shape shape = new RoundRectangle2D.Float(x, y, width, width, 6, 6);
        graph.setStroke(new BasicStroke(3f));
        graph.draw(shape);
        graph.dispose();
    }

    /**
     * 生成二维码(内嵌LOGO) 二维码文件名随机,文件名可能会有重复
     *
     * @param content      内容
     * @param logoPath     LOGO地址
     * @param destPath     存放目录
     * @param needCompress 是否压缩LOGO
     */
    private static String encode(String content, String logoPath, String destPath, boolean needCompress)
            throws Exception {
        BufferedImage image = BarcodeUtils.createImage(content, logoPath, needCompress);
        mkdir(destPath);
        String fileName = new Random().nextInt(99999999) + "." + FORMAT.toLowerCase();
        ImageIO.write(image, FORMAT, new File(destPath + "/" + fileName));
        return fileName;
    }

    /**
     * 生成二维码(内嵌LOGO) 调用者指定二维码文件名
     *
     * @param content      内容
     * @param logoPath     LOGO地址
     * @param destPath     存放目录
     * @param fileName     二维码文件名
     * @param needCompress 是否压缩LOGO
     * @throws Exception
     */
    private static String encode(String content, String logoPath, String destPath, String fileName,
                                 boolean needCompress) throws Exception {
        BufferedImage image = BarcodeUtils.createImage(content, logoPath, needCompress);
        mkdir(destPath);
        fileName = fileName.substring(0, fileName.indexOf(".") > 0 ? fileName.indexOf(".") : fileName.length()) + "."
                + FORMAT.toLowerCase();
        ImageIO.write(image, FORMAT, new File(destPath + "/" + fileName));
        return fileName;
    }

    /**
     * 生成二维码(内嵌LOGO)
     *
     * @param content  内容
     * @param logoPath LOGO地址
     * @param destPath 存储地址
     */
    public static String encode(String content, String logoPath, String destPath) throws Exception {
        return BarcodeUtils.encode(content, logoPath, destPath, false);
    }

    /**
     * 生成二维码
     *
     * @param content  内容
     * @param destPath 存储地址
     * @throws Exception
     */
    public static String encode(String content, String destPath) throws Exception {
        return BarcodeUtils.encode(content, null, destPath, false);
    }

    /**
     * 生成二维码(内嵌LOGO)
     *
     * @param content      内容
     * @param logoPath     LOGO地址
     * @param output       输出流
     * @param needCompress 是否压缩LOGO
     */
    private static void encode(String content, String logoPath, OutputStream output, boolean needCompress)
            throws Exception {
        BufferedImage image = BarcodeUtils.createImage(content, logoPath, needCompress);
        ImageIO.write(image, FORMAT, output);
    }

    /**
     * 生成二维码
     *
     * @param content 内容
     * @param output  输出流
     */
    public static void encode(String content, OutputStream output) throws Exception {
        BarcodeUtils.encode(content, null, output, false);
    }

    /**
     * 当文件夹不存在时,mkdirs会自动创建多层目录,区别于mkdir. (mkdir如果父目录不存在则会抛出异常)
     *
     * @param destPath 存放目录
     */
    private static void mkdir(String destPath) {
        File file = new File(destPath);
        if (!file.exists() && !file.isDirectory()) {
            file.mkdirs();
        }
    }

    /**
     * 解析二维码
     *
     * @param file 二维码图片
     */
    private static String decode(File file) throws Exception {
        BufferedImage image;
        image = ImageIO.read(file);
        if (image == null) {
            return null;
        }
        BufferedImageLuminanceSource source = new BufferedImageLuminanceSource(image);
        BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
        Result result;
        Hashtable<DecodeHintType, Object> hints = new Hashtable<DecodeHintType, Object>();
        hints.put(DecodeHintType.CHARACTER_SET, CHARSET);
        result = new MultiFormatReader().decode(bitmap, hints);
        return result.getText();
    }

    /**
     * 解析二维码
     *
     * @param path 二维码图片地址
     */
    public static String decode(String path) throws Exception {
        return BarcodeUtils.decode(new File(path));
    }

    public static void main(String[] args) throws Exception {
        // 条形码
        BufferedImage image = insertWords(getBarCode("89607"), "*89607*");
        assert image != null;
        ImageIO.write(image, "jpg", new File("barcode.jpg"));
        // 二维码
        // String text = "http://localhost:8083/communication/distribution?qrid=54999";
        // 不含Logo
        // BarcodeUtils.encode(text, null, "C:\\\\Users\\\\ThinkPad\\\\Pictures", true);
        // 含Logo,不指定二维码图片名
        // BarcodeUtils.encode(text, "e:\\csdn.jpg", "e:\\", true);
        // 含Logo,指定二维码图片名
        // BarcodeUtils.encode(text, "C:\\Users\\ThinkPad\\Pictures\\mail-unread.png",
        // "C:\\Users\\ThinkPad\\Pictures", "qrcode", true);
    }
}

注意点

如果想要设置条形码周围的空白区域大小,需要通过参数如下:

 /**
     * hints 设置 条形码参数
     */
    private static Map<EncodeHintType, Object> hints = new HashMap<>(5);

    static {
        //设置留白大小
        hints.put(EncodeHintType.MARGIN, 1);
    }
public static BufferedImage getBarCode(String vaNumber) {
        try {
            Code128Writer writer = new Code128Writer();
            // 编码内容, 编码类型, 宽度, 高度, 设置参数
            BitMatrix bitMatrix = writer.encode(vaNumber, BarcodeFormat.CODE_128, WIDTH, HEIGHT, hints);
            return MatrixToImageWriter.toBufferedImage(bitMatrix);
        } catch (WriterException e) {
            e.printStackTrace();
        }
        return null;
    }

但是这里有一坑,认为设置了留白大小之后,但是往往留白的大小会出乎意料。

下面通过分析zxing工具中的源码如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
通过上述源码分析可知,如果想要设置条形码下方的展示内容与条形码两端对齐,需要知道变量leftPadding(条形码左边距的值),简单代码如下:

public static BufferedImage insertWords(BufferedImage image, String words) {
        // 新的图片,把带logo的二维码下面加上文字
        if (!StringUtils.isEmpty(words)) {
            BufferedImage outImage = new BufferedImage(WIDTH, WORD_HEIGHT, BufferedImage.TYPE_INT_RGB);
            Graphics2D g2d = outImage.createGraphics();
            // 抗锯齿
            setGraphics2D(g2d);
            // 设置白色
            setColorWhite(g2d);
            // 画条形码到新的面板
            g2d.drawImage(image, 0, 0, image.getWidth(), image.getHeight(), null);
            // 画文字到新的面板
            g2d.setColor(Color.BLACK);
            // 字体、字型、字号
            g2d.setFont(new Font("黑体", Font.PLAIN, FONT_SIZE));
            int wordStartY = HEIGHT + 21;
            String content=words.substring(1,words.length()-1);
            int inputWidth = new Code128Writer().encode(content).length;
            int fullWidth = inputWidth + 1;
            int outputWidth = Math.max(WIDTH, fullWidth);
            int multiple = outputWidth / fullWidth;
            int leftPadding = (outputWidth - (inputWidth * multiple)) / 2;
            int x = leftPadding;
            String[] split = words.split("");
            int len = split.length;
            int step = new Long(Math.round(WIDTH - leftPadding * 2) / words.length()).intValue();
            for (int i = 0; i < len; i++) {
                g2d.drawString(split[i], x, wordStartY);
                x = x + step;
            }
            outImage.flush();
            return outImage;
        }
        return null;
    }

演示效果大致如下图所示
在这里插入图片描述

标签:条形码,String,int,image,param,zxing,static,new,绘制
来源: https://blog.csdn.net/weixin_48276298/article/details/118580151

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有