国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

java生成、識(shí)別條形碼和二維碼

這篇具有很好參考價(jià)值的文章主要介紹了java生成、識(shí)別條形碼和二維碼。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

一、概述

  • 使用 zxing 開源庫

    • Zxing主要是Google出品的,用于識(shí)別一維碼和二維碼的第三方庫
    • 主要類:
    • BitMatrix 位圖矩陣
    • MultiFormatWriter 位圖編寫器
    • MatrixToImageWriter 寫入圖片
  • 可以生成、識(shí)別條形碼和二維碼

  • 內(nèi)置三種尺寸:enum Size {SMALL, MIDDLE, BIG}

  • 依賴

<dependency>
    <groupId>com.google.zxing</groupId>
    <artifactId>javase</artifactId>
    <version>3.5.1</version>
</dependency>
<dependency>
    <groupId>com.google.zxing</groupId>
    <artifactId>core</artifactId>
    <version>3.5.1</version>
</dependency>
<!-- web -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>2.6.7</version>
</dependency>
<dependency>
    <groupId>commons-lang</groupId>
    <artifactId>commons-lang</artifactId>
    <version>2.6</version>
</dependency>

二、效果圖

java生成、識(shí)別條形碼和二維碼

三、條形碼

  • 將寬度不等的多個(gè)黑條和白條,按照一定的編碼規(guī)則排序,用以表達(dá)一組信息的圖像標(biāo)識(shí)符
  • 通常代表一串?dāng)?shù)字 / 字母,每一位有特殊含義
  • 一般數(shù)據(jù)容量30個(gè)數(shù)字 / 字母

1、生成簡(jiǎn)單條形碼(無文字)

/**
 * 生成簡(jiǎn)單條形碼(無文字)
 *
 * @param content
 * @param width
 * @param height
 * @return
*/
public static BufferedImage create(String content, int width, int height) {
    // 定義位圖矩陣BitMatrix
    BitMatrix matrix = null;

    try {
        // 定義二維碼參數(shù)
        Map<EncodeHintType, Object> hints = new HashMap<>(3);
        // 設(shè)置編碼
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
        // 設(shè)置容錯(cuò)等級(jí)
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
        // 設(shè)置邊距,默認(rèn)為5
        hints.put(EncodeHintType.MARGIN, 3);

        // 使用code_128格式進(jìn)行編碼生成條形碼
        MultiFormatWriter writer = new MultiFormatWriter();
        matrix = writer.encode(content, BarcodeFormat.CODE_128, width, height, hints);
    } catch (WriterException e) {
        e.printStackTrace();
        //throw new RuntimeException("條形碼內(nèi)容寫入失敗");
    }

    return MatrixToImageWriter.toBufferedImage(matrix);
}

2、生成條形碼(含文字)

  • 生成條形碼(含文字)
/**
 * 生成條形碼(含文字)
 * ****************************************************
 * ----------------------------------------------
 * |                         2023-06-10 10:55   |
 * |                                            |
 * |            商品名稱 /超出不顯示/              |
 * |                                            |
 * |    | || ||| | || |||| | | | ||| | | ||     |
 * |    | || ||| | || |||| | | | ||| | | ||     |
 * |    | || ||| | || |||| | | | ||| | | ||     |
 * |    | || ||| | || |||| | | | ||| | | ||     |
 * |               13800000000                  |
 * ----------------------------------------------
 * ===================================================
 * 1、日期:頂部右側(cè)
 * 2、商品名稱:居中
 * 3、條形碼:商品名稱下方,且居中
 * 4、條碼內(nèi)容:條形碼下方,且居中
 * *****************************************************
 *
 * @param codeImage     條形碼圖片
 * @param bottomStr     底部文字
 * @param titleStr      標(biāo)題文字
 * @param topRightStr   右上角文字
 * @param pictureWidth  圖片寬度
 * @param pictureHeight 圖片高度
 * @param margin        邊距
 * @param fontSize      字體大小
 * @return 條形碼圖片
 */
private static BufferedImage createWithWords(
    BufferedImage codeImage,
    String bottomStr,
    String titleStr,
    String topRightStr,
    int pictureWidth,
    int pictureHeight,
    int margin,
    int fontSize) {
    BufferedImage picImage = new BufferedImage(pictureWidth, pictureHeight, BufferedImage.TYPE_INT_RGB);

    Graphics2D g2d = picImage.createGraphics();
    // 抗鋸齒
    setGraphics2D(g2d);
    // 設(shè)置白色
    setColorWhite(g2d, picImage.getWidth(), picImage.getHeight());

    // 條形碼默認(rèn)居中顯示
    int codeStartX = (pictureWidth - codeImage.getWidth()) / 2;
    int codeStartY = (pictureHeight - codeImage.getHeight()) / 2 + 2 * margin;
    // 畫條形碼到新的面板
    g2d.drawImage(codeImage, codeStartX, codeStartY, codeImage.getWidth(), codeImage.getHeight(), null);

    // 給條碼上下各畫一條線
    // 設(shè)置顏色
    g2d.setColor(Color.LIGHT_GRAY);
    int y1 = 2 * margin + codeImage.getHeight();
    int y2 = 2 * margin + 2 * codeImage.getHeight();
    g2d.drawLine(0, y1, pictureWidth, y1);
    g2d.drawLine(0, y2, pictureWidth, y2);

    // 畫文字到新的面板
    g2d.setColor(Color.BLACK);
    // 字體、字型、字號(hào)
    g2d.setFont(new Font("微軟雅黑", Font.PLAIN, fontSize));
    // 文字與條形碼之間的間隔
    int wordAndCodeSpacing = 3;

    // 底部文字(居中)
    if (StringUtils.isNotEmpty(bottomStr)) {
        // 文字長(zhǎng)度
        int strWidth = g2d.getFontMetrics().stringWidth(bottomStr);
        // 文字X軸開始坐標(biāo)
        int strStartX = (pictureWidth - strWidth) / 2;
        if (strStartX < margin) {
            strStartX = margin;
        }
        // 文字Y軸開始坐標(biāo)
        int strStartY = codeStartY + codeImage.getHeight() + fontSize + wordAndCodeSpacing;
        // 畫文字
        g2d.drawString(bottomStr, strStartX, strStartY);
    }

    // 右上角文字
    if (StringUtils.isNotEmpty(topRightStr)) {
        // 文字長(zhǎng)度
        int strWidth = g2d.getFontMetrics().stringWidth(topRightStr);
        // 文字X軸開始坐標(biāo)
        int strStartX = pictureWidth - strWidth - margin;
        // 文字Y軸開始坐標(biāo)
        int strStartY = margin + fontSize;
        // 畫文字
        g2d.drawString(topRightStr, strStartX, strStartY);
    }

    // 標(biāo)題文字(居中)
    if (StringUtils.isNotEmpty(titleStr)) {
    	if (titleStr.length() > 11) {
            titleStr = titleStr.substring(0, 11);
        }
        // 字體、字型、字號(hào)
        int fs = (int) Math.ceil(fontSize * 1.5);
        g2d.setFont(new Font("微軟雅黑", Font.PLAIN, fs));
        // 文字長(zhǎng)度
        int strWidth = g2d.getFontMetrics().stringWidth(titleStr);
        // 文字X軸開始坐標(biāo)
        int strStartX = (pictureWidth - strWidth) / 2;
        if (strStartX < margin) {
            strStartX = margin;
        }
        // 文字Y軸開始坐標(biāo)
        int strStartY = codeStartY - margin;
        // 畫文字
        g2d.drawString(titleStr, strStartX, strStartY);
    }

    g2d.dispose();
    picImage.flush();

    return picImage;
}
  • 設(shè)置 Graphics2D 屬性 (抗鋸齒)
/**
 * 設(shè)置 Graphics2D 屬性 (抗鋸齒)
 *
 * @param g2d Graphics2D提供對(duì)幾何形狀、坐標(biāo)轉(zhuǎn)換、顏色管理和文本布局更為復(fù)雜的控制
 */
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);
}
  • 設(shè)置背景為白色
/**
 * 設(shè)置背景為白色
 *
 * @param g2d Graphics2D提供對(duì)幾何形狀、坐標(biāo)轉(zhuǎn)換、顏色管理和文本布局更為復(fù)雜的控制
 */
private static void setColorWhite(Graphics2D g2d, int width, int height) {
    g2d.setColor(Color.WHITE);
    // 填充整個(gè)屏幕
    g2d.fillRect(0, 0, width, height);
    // 設(shè)置筆刷
    g2d.setColor(Color.BLACK);
}
  • 創(chuàng)建小號(hào)條形碼(250x150)
/**
 * 創(chuàng)建小號(hào)條形碼(250x150)
 *
 * @param code
 * @param name
 * @return
 */
private static BufferedImage createSmallWithWords(@NonNull String code, @NonNull String name) {
    // 條形碼底部?jī)?nèi)容
    String bottomStr = code;
    // 條形碼左上角內(nèi)容
    //String topLeftStr = name.length() < 11 ? name : name.substring(0, 11);
    String topLeftStr = name;
    // 條形碼右上角內(nèi)容
    DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
    String topRightStr = dtf.format(LocalDateTime.now());

    // 生成條形碼
    BufferedImage barCodeImage = create(bottomStr, 250, 50);

    return createWithWords(
        barCodeImage,
        bottomStr,
        topLeftStr,
        topRightStr,
        250,
        150,
        10,
        14);
}
  • 創(chuàng)建中號(hào)條形碼(350x210)
/**
 * 創(chuàng)建中號(hào)條形碼(350x210)
 *
 * @param code
 * @param name
 * @return
 */
private static BufferedImage createMiddleWithWords(@NonNull String code, @NonNull String name) {
    // 條形碼底部?jī)?nèi)容
    String bottomStr = code;
    // 條形碼左上角內(nèi)容
    //String topLeftStr = name.length() < 11 ? name : name.substring(0, 11);
    String topLeftStr = name;
    // 條形碼右上角內(nèi)容
    DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
    String topRightStr = dtf.format(LocalDateTime.now());

    // 生成條形碼
    BufferedImage barCodeImage = create(bottomStr, 350, 70);

    return createWithWords(
        barCodeImage,
        bottomStr,
        topLeftStr,
        topRightStr,
        350,
        210,
        14,
        20);
}
  • 創(chuàng)建大號(hào)條形碼(500x300)
/**
 * 創(chuàng)建大號(hào)條形碼(500x300)
 *
 * @param code
 * @param name
 * @return
 */
private static BufferedImage createBigWithWords(@NonNull String code, @NonNull String name) {
    // 條形碼底部?jī)?nèi)容
    String bottomStr = code;
    // 條形碼左上角內(nèi)容
    //String topLeftStr = name.length() < 11 ? name : name.substring(0, 11);
    String topLeftStr = name;
    // 條形碼右上角內(nèi)容
    DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
    String topRightStr = dtf.format(LocalDateTime.now());

    // 生成條形碼
    BufferedImage barCodeImage = create(bottomStr, 500, 100);

    return createWithWords(
        barCodeImage,
        bottomStr,
        topLeftStr,
        topRightStr,
        500,
        300,
        20,
        28);
}
  • 創(chuàng)建內(nèi)置尺寸(小/中/大)條形碼
/**
 * 生成條形碼(帶文字)
 *
 * @param code 編碼內(nèi)容
 * @param name 名稱
 * @param size 規(guī)格:小中大
 * @return
 */
public static BufferedImage createWithWords(
    @NonNull String code,
    @NonNull String name,
    @NonNull Size size
) {
    switch (size) {
        case SMALL:
            return createSmallWithWords(code, name);
        case MIDDLE:
            return createMiddleWithWords(code, name);
        case BIG:
        default:
            return createBigWithWords(code, name);
    }
}

四、二維碼

  • 用某種特定幾何圖形按一定規(guī)律在平面(二維方向上)分布的黑白相間的圖形記錄數(shù)據(jù)符號(hào)信息
  • 比一維條形碼能存儲(chǔ)更多信息,表示更多數(shù)據(jù)類型
  • 能夠存儲(chǔ)數(shù)字 / 字母 / 漢字 / 圖片等信息
  • 可存儲(chǔ)幾百到幾十KB字符

1、生成指定尺寸二維碼

/**
 * 生成二維碼(正方形)
 * @param content
 * @param sideLength 邊長(zhǎng)(px)
 * @return
 */
public static BufferedImage create(String content, int sideLength) {
    BitMatrix matrix = null;
    // 定義二維碼參數(shù)
    Map<EncodeHintType, Object> hints = new HashMap<>(3);
    // 設(shè)置編碼
    hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
    // 設(shè)置容錯(cuò)等級(jí)
    hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
    // 設(shè)置邊距,默認(rèn)為5
    hints.put(EncodeHintType.MARGIN, 3);

    try {
        matrix = new MultiFormatWriter()
            .encode(content, BarcodeFormat.QR_CODE, sideLength, sideLength, hints);
    } catch (Exception e) {
        e.printStackTrace();
        //throw new RuntimeException("條形碼內(nèi)容寫入失敗");
    }
    return MatrixToImageWriter.toBufferedImage(matrix);
}

2、生成內(nèi)置尺寸(小/中/大)二維碼

小號(hào):250px;中號(hào):350px;大號(hào):500px;

public static BufferedImage create(String content, Size size) {
    switch (size) {
        case SMALL:
            return create(content, 250);
        case MIDDLE:
            return create(content, 350);
        case BIG:
        default:
            return create(content, 500);
    }
}

五、保存

  • 存入文件
/**
 * 存入文件
 *
 * @param barCodeImage
 * @return 文件名
 */
public static String toFile(BufferedImage barCodeImage) {
    String fileName = getFileName();
    boolean isWrite = false;
    try {
        FileOutputStream outputStream = new FileOutputStream(new File(getImageDir(), fileName));
        isWrite = ImageIO.write(barCodeImage, "png", outputStream);
    } catch (IOException e) {
        e.printStackTrace();
    }

    if (isWrite) {
        return fileName;
    }
    return "";
}
  • 存放目錄
/**
 * 得到圖片存放目錄
 * 類路徑下的image文件夾
 *
 * @return
 */
private static String getImageDir() {
    String imageDir = "";
    Resource resource = new ClassPathResource("");
    try {
        String _dir = resource.getFile().getAbsolutePath();
        File file = new File(_dir, "image");
        if (!file.exists()) {
            file.mkdirs();
        }
        imageDir = file.getAbsolutePath();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return imageDir;
}
  • 文件名
/**
 * 生成文件名
 * 當(dāng)前時(shí)間戳 + 兩位隨機(jī)數(shù)
 *
 * @return
 */
private static String getFileName() {
    // 當(dāng)前時(shí)間戳
    long second = Instant.now().getEpochSecond();

    // 兩位隨機(jī)數(shù)
    ThreadLocalRandom r = ThreadLocalRandom.current();
    int rand = r.nextInt(10, 99);

    return new StringBuffer().append(second).append(rand).append(".png").toString();
}

六、識(shí)別

/**
 * 識(shí)別圖形碼(條形碼/二維碼)
 * ***********************************************
 * ------ 條形碼 ----------------------------------
 * 可以識(shí)別內(nèi)容:手機(jī)號(hào)、純數(shù)字、字母數(shù)字、網(wǎng)址(中大號(hào))
 * 識(shí)別不了小號(hào)(250x150)含文字的網(wǎng)址條形碼
 * 存儲(chǔ)網(wǎng)址時(shí)用二維碼,不要使用條形碼
 * ***********************************************
 * ------ 二維碼 ----------------------------------
 * 比條形碼有優(yōu)勢(shì);能識(shí)別三種尺寸的網(wǎng)址二維碼
 * ***********************************************
 *
 * @param imageCode 圖形碼文件
 * @return void
 */
public static String scan(File imageCode) {
    String text = "";
    try {
        BufferedImage image = ImageIO.read(imageCode);
        if (image == null) {
            return text;
        }
        LuminanceSource source = new BufferedImageLuminanceSource(image);
        BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));

        Map<DecodeHintType, Object> hints = new HashMap<>(3);
        hints.put(DecodeHintType.CHARACTER_SET, "UTF-8");
        hints.put(DecodeHintType.PURE_BARCODE, Boolean.TRUE);
        hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
        Result result = new MultiFormatReader().decode(bitmap, hints);
        text = result.getText();
    } catch (Exception e) {
        e.printStackTrace();
        System.out.println("無法識(shí)別");
    }
    return text;
}

public static String scan(String fileName) {
    return scan(new File(getImageDir(), fileName));
}

public static String scan(String fileName, String fileParent) {
    return scan(new File(fileParent, fileName));
}

七、測(cè)試類

package com.tuwer.util;

/**
 * <p>描述...</p>
 *
 * @author 土味兒
 * @version 1.0
 * @Date 2023/6/10
 */
public class ImageCodeTest {
    public static void main(String[] args) {
        cr();
        //sc();
    }

    /**
     * 創(chuàng)建
     */
    private static void cr() {
        //String code = "13800000000";
        String code = "1667320863285510145";
        //String code = "abcdefg123456789012";
        //String code = "http://www.baidu.com";
        String title = "商品名稱(超出不顯示)";
        System.out.println(ImageCodeUtil.toFile(ImageCodeUtil.BarCode.createWithWords(code, title, ImageCodeUtil.Size.SMALL)));
        System.out.println(ImageCodeUtil.toFile(ImageCodeUtil.BarCode.createWithWords(code, title, ImageCodeUtil.Size.MIDDLE)));
        System.out.println(ImageCodeUtil.toFile(ImageCodeUtil.BarCode.createWithWords(code, title, ImageCodeUtil.Size.BIG)));

        //System.out.println(toFile(QrCode.create(code, 500)));
        //System.out.println(ImageCodeUtil.toFile(ImageCodeUtil.QrCode.create(code, ImageCodeUtil.Size.SMALL)));
        //System.out.println(ImageCodeUtil.toFile(ImageCodeUtil.QrCode.create(code, ImageCodeUtil.Size.MIDDLE)));
        //System.out.println(ImageCodeUtil.toFile(ImageCodeUtil.QrCode.create(code, ImageCodeUtil.Size.BIG)));
    }

    /**
     * 識(shí)別
     */
    private static void sc() {
        // 掃描
        // 13800000000
        //String[] fs = {"168636218096.png", "168636218180.png", "168636218127.png"};

        // 1667320863285510145
        //String[] fs = {"168636260651.png", "168636260766.png", "168636260794.png"};

        // abcdefg123456789012
        //String[] fs = {"168636320566.png", "168636320750.png", "168636320743.png"};

        // http://www.baidu.com
        String[] fs = {"168636738387.png", "168636738545.png", "168636738539.png"};

        for (String f : fs) {
            System.out.println("-----------------");
            System.out.println(ImageCodeUtil.scan(f));
        }
    }
}

八、完整源碼

package com.tuwer.util;

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.qrcode.decoder.ErrorCorrectionLevel;
import org.apache.commons.lang.StringUtils;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.lang.NonNull;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ThreadLocalRandom;

/**
 * <p>圖形碼工具類</p>
 *
 * @author 土味兒
 * @version 1.0
 * @Date 2023/6/9
 */
public class ImageCodeUtil {
    /**
     * 尺寸
     */
    enum Size {SMALL, MIDDLE, BIG}

    // ====================== 條形碼內(nèi)部類 ========================

    /**
     * 條形碼
     */
    public static class BarCode {
        /**
         * 生成簡(jiǎn)單條形碼(無文字)
         *
         * @param content
         * @param width
         * @param height
         * @return
         */
        public static BufferedImage create(String content, int width, int height) {
            // 定義位圖矩陣BitMatrix
            BitMatrix matrix = null;

            try {
                // 定義二維碼參數(shù)
                Map<EncodeHintType, Object> hints = new HashMap<>(3);
                // 設(shè)置編碼
                hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
                // 設(shè)置容錯(cuò)等級(jí)
                hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
                // 設(shè)置邊距,默認(rèn)為5
                hints.put(EncodeHintType.MARGIN, 3);

                // 使用code_128格式進(jìn)行編碼生成條形碼
                MultiFormatWriter writer = new MultiFormatWriter();
                matrix = writer.encode(content, BarcodeFormat.CODE_128, width, height, hints);
            } catch (WriterException e) {
                e.printStackTrace();
                //throw new RuntimeException("條形碼內(nèi)容寫入失敗");
            }

            return MatrixToImageWriter.toBufferedImage(matrix);
        }

        /**
         * 生成條形碼(含文字)
         * ****************************************************
         * ----------------------------------------------
         * |                         2023-06-10 10:55   |
         * |                                            |
         * |            商品名稱 /超出不顯示/              |
         * |                                            |
         * |    | || ||| | || |||| | | | ||| | | ||     |
         * |    | || ||| | || |||| | | | ||| | | ||     |
         * |    | || ||| | || |||| | | | ||| | | ||     |
         * |    | || ||| | || |||| | | | ||| | | ||     |
         * |               13800000000                  |
         * ----------------------------------------------
         * ===================================================
         * 1、日期:頂部右側(cè)
         * 2、商品名稱:居中
         * 3、條形碼:商品名稱下方,且居中
         * 4、條碼內(nèi)容:條形碼下方,且居中
         * *****************************************************
         *
         * @param codeImage     條形碼圖片
         * @param bottomStr     底部文字
         * @param titleStr      標(biāo)題文字
         * @param topRightStr   右上角文字
         * @param pictureWidth  圖片寬度
         * @param pictureHeight 圖片高度
         * @param margin        邊距
         * @param fontSize      字體大小
         * @return 條形碼圖片
         */
        private static BufferedImage createWithWords(
                BufferedImage codeImage,
                String bottomStr,
                String titleStr,
                String topRightStr,
                int pictureWidth,
                int pictureHeight,
                int margin,
                int fontSize) {
            BufferedImage picImage = new BufferedImage(pictureWidth, pictureHeight, BufferedImage.TYPE_INT_RGB);

            Graphics2D g2d = picImage.createGraphics();
            // 抗鋸齒
            setGraphics2D(g2d);
            // 設(shè)置白色
            setColorWhite(g2d, picImage.getWidth(), picImage.getHeight());

            // 條形碼默認(rèn)居中顯示
            int codeStartX = (pictureWidth - codeImage.getWidth()) / 2;
            int codeStartY = (pictureHeight - codeImage.getHeight()) / 2 + 2 * margin;
            // 畫條形碼到新的面板
            g2d.drawImage(codeImage, codeStartX, codeStartY, codeImage.getWidth(), codeImage.getHeight(), null);

            // 給條碼上下各畫一條線
            // 設(shè)置顏色
            g2d.setColor(Color.LIGHT_GRAY);
            int y1 = 2 * margin + codeImage.getHeight();
            int y2 = 2 * margin + 2 * codeImage.getHeight();
            g2d.drawLine(0, y1, pictureWidth, y1);
            g2d.drawLine(0, y2, pictureWidth, y2);

            // 畫文字到新的面板
            g2d.setColor(Color.BLACK);
            // 字體、字型、字號(hào)
            g2d.setFont(new Font("微軟雅黑", Font.PLAIN, fontSize));
            // 文字與條形碼之間的間隔
            int wordAndCodeSpacing = 3;

            // 底部文字(居中)
            if (StringUtils.isNotEmpty(bottomStr)) {
                // 文字長(zhǎng)度
                int strWidth = g2d.getFontMetrics().stringWidth(bottomStr);
                // 文字X軸開始坐標(biāo)
                int strStartX = (pictureWidth - strWidth) / 2;
                if (strStartX < margin) {
                    strStartX = margin;
                }
                // 文字Y軸開始坐標(biāo)
                int strStartY = codeStartY + codeImage.getHeight() + fontSize + wordAndCodeSpacing;
                // 畫文字
                g2d.drawString(bottomStr, strStartX, strStartY);
            }

            // 右上角文字
            if (StringUtils.isNotEmpty(topRightStr)) {
                // 文字長(zhǎng)度
                int strWidth = g2d.getFontMetrics().stringWidth(topRightStr);
                // 文字X軸開始坐標(biāo)
                int strStartX = pictureWidth - strWidth - margin;
                // 文字Y軸開始坐標(biāo)
                int strStartY = margin + fontSize;
                // 畫文字
                g2d.drawString(topRightStr, strStartX, strStartY);
            }

            // 標(biāo)題文字(居中)
            if (StringUtils.isNotEmpty(titleStr)) {
                // 字體、字型、字號(hào)
                int fs = (int) Math.ceil(fontSize * 1.5);
                g2d.setFont(new Font("微軟雅黑", Font.PLAIN, fs));
                // 文字長(zhǎng)度
                int strWidth = g2d.getFontMetrics().stringWidth(titleStr);
                // 文字X軸開始坐標(biāo)
                int strStartX = (pictureWidth - strWidth) / 2;
                if (strStartX < margin) {
                    strStartX = margin;
                }
                // 文字Y軸開始坐標(biāo)
                int strStartY = codeStartY - margin;
                // 畫文字
                g2d.drawString(titleStr, strStartX, strStartY);
            }

            g2d.dispose();
            picImage.flush();

            return picImage;
        }

        /**
         * 設(shè)置 Graphics2D 屬性 (抗鋸齒)
         *
         * @param g2d Graphics2D提供對(duì)幾何形狀、坐標(biāo)轉(zhuǎn)換、顏色管理和文本布局更為復(fù)雜的控制
         */
        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);
        }

        /**
         * 設(shè)置背景為白色
         *
         * @param g2d Graphics2D提供對(duì)幾何形狀、坐標(biāo)轉(zhuǎn)換、顏色管理和文本布局更為復(fù)雜的控制
         */
        private static void setColorWhite(Graphics2D g2d, int width, int height) {
            g2d.setColor(Color.WHITE);
            // 填充整個(gè)屏幕
            g2d.fillRect(0, 0, width, height);
            // 設(shè)置筆刷
            g2d.setColor(Color.BLACK);
        }

        /**
         * 創(chuàng)建小號(hào)條形碼(250x150)
         *
         * @param code
         * @param name
         * @return
         */
        private static BufferedImage createSmallWithWords(@NonNull String code, @NonNull String name) {
            // 條形碼底部?jī)?nèi)容
            String bottomStr = code;
            // 條形碼左上角內(nèi)容
            //String topLeftStr = name.length() < 11 ? name : name.substring(0, 11);
            String topLeftStr = name;
            // 條形碼右上角內(nèi)容
            DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
            String topRightStr = dtf.format(LocalDateTime.now());

            // 生成條形碼
            BufferedImage barCodeImage = create(bottomStr, 250, 50);

            return createWithWords(
                    barCodeImage,
                    bottomStr,
                    topLeftStr,
                    topRightStr,
                    250,
                    150,
                    10,
                    14);
        }

        /**
         * 創(chuàng)建中號(hào)條形碼(350x210)
         *
         * @param code
         * @param name
         * @return
         */
        private static BufferedImage createMiddleWithWords(@NonNull String code, @NonNull String name) {
            // 條形碼底部?jī)?nèi)容
            String bottomStr = code;
            // 條形碼左上角內(nèi)容
            //String topLeftStr = name.length() < 11 ? name : name.substring(0, 11);
            String topLeftStr = name;
            // 條形碼右上角內(nèi)容
            DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
            String topRightStr = dtf.format(LocalDateTime.now());

            // 生成條形碼
            BufferedImage barCodeImage = create(bottomStr, 350, 70);

            return createWithWords(
                    barCodeImage,
                    bottomStr,
                    topLeftStr,
                    topRightStr,
                    350,
                    210,
                    14,
                    20);
        }

        /**
         * 創(chuàng)建大號(hào)條形碼(500x300)
         *
         * @param code
         * @param name
         * @return
         */
        private static BufferedImage createBigWithWords(@NonNull String code, @NonNull String name) {
            // 條形碼底部?jī)?nèi)容
            String bottomStr = code;
            // 條形碼左上角內(nèi)容
            //String topLeftStr = name.length() < 11 ? name : name.substring(0, 11);
            String topLeftStr = name;
            // 條形碼右上角內(nèi)容
            DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
            String topRightStr = dtf.format(LocalDateTime.now());

            // 生成條形碼
            BufferedImage barCodeImage = create(bottomStr, 500, 100);

            return createWithWords(
                    barCodeImage,
                    bottomStr,
                    topLeftStr,
                    topRightStr,
                    500,
                    300,
                    20,
                    28);
        }

        /**
         * 生成條形碼(帶文字)
         *
         * @param code 編碼內(nèi)容
         * @param name 名稱
         * @param size 規(guī)格:小中大
         * @return
         */
        public static BufferedImage createWithWords(
                @NonNull String code,
                @NonNull String name,
                @NonNull Size size
        ) {
            switch (size) {
                case SMALL:
                    return createSmallWithWords(code, name);
                case MIDDLE:
                    return createMiddleWithWords(code, name);
                case BIG:
                default:
                    return createBigWithWords(code, name);
            }
        }
    }

    // ====================== 二維碼內(nèi)部類 ========================

    /**
     * 二維碼
     */
    public static class QrCode {
        /**
         * 生成二維碼(正方形)
         *
         * @param content
         * @param sideLength 邊長(zhǎng)(px)
         * @return
         */
        public static BufferedImage create(String content, int sideLength) {
            BitMatrix matrix = null;
            // 定義二維碼參數(shù)
            Map<EncodeHintType, Object> hints = new HashMap<>(3);
            // 設(shè)置編碼
            hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
            // 設(shè)置容錯(cuò)等級(jí)
            hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
            // 設(shè)置邊距,默認(rèn)為5
            hints.put(EncodeHintType.MARGIN, 3);

            try {
                matrix = new MultiFormatWriter()
                        .encode(content, BarcodeFormat.QR_CODE, sideLength, sideLength, hints);
            } catch (Exception e) {
                e.printStackTrace();
                //throw new RuntimeException("條形碼內(nèi)容寫入失敗");
            }
            return MatrixToImageWriter.toBufferedImage(matrix);
        }

        public static BufferedImage create(String content, Size size) {
            switch (size) {
                case SMALL:
                    return create(content, 250);
                case MIDDLE:
                    return create(content, 350);
                case BIG:
                default:
                    return create(content, 500);
            }
        }
    }

    // ======================== 存入文件 =========================

    /**
     * 存入文件
     *
     * @param barCodeImage
     * @return 文件名
     */
    public static String toFile(BufferedImage barCodeImage) {
        String fileName = getFileName();
        boolean isWrite = false;
        try {
            FileOutputStream outputStream = new FileOutputStream(new File(getImageDir(), fileName));
            isWrite = ImageIO.write(barCodeImage, "png", outputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }

        if (isWrite) {
            return fileName;
        }
        return "";
    }

    /**
     * 得到圖片存放目錄
     * 類路徑下的image文件夾
     *
     * @return
     */
    private static String getImageDir() {
        String imageDir = "";
        Resource resource = new ClassPathResource("");
        try {
            String _dir = resource.getFile().getAbsolutePath();
            File file = new File(_dir, "image");
            if (!file.exists()) {
                file.mkdirs();
            }
            imageDir = file.getAbsolutePath();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return imageDir;
    }

    /**
     * 生成文件名
     * 當(dāng)前時(shí)間戳 + 兩位隨機(jī)數(shù)
     *
     * @return
     */
    private static String getFileName() {
        // 當(dāng)前時(shí)間戳
        long second = Instant.now().getEpochSecond();

        // 兩位隨機(jī)數(shù)
        ThreadLocalRandom r = ThreadLocalRandom.current();
        int rand = r.nextInt(10, 99);

        return new StringBuffer().append(second).append(rand).append(".png").toString();
    }

    // ======================= 識(shí)別圖形碼 ========================

    /**
     * 識(shí)別圖形碼(條形碼/二維碼)
     * ***********************************************
     * ------ 條形碼 ----------------------------------
     * 可以識(shí)別內(nèi)容:手機(jī)號(hào)、純數(shù)字、字母數(shù)字、網(wǎng)址(中大號(hào))
     * 識(shí)別不了小號(hào)(250x150)含文字的網(wǎng)址條形碼
     * 存儲(chǔ)網(wǎng)址時(shí)用二維碼,不要使用條形碼
     * ***********************************************
     * ------ 二維碼 ----------------------------------
     * 比條形碼有優(yōu)勢(shì);能識(shí)別三種尺寸的網(wǎng)址二維碼
     * ***********************************************
     *
     * @param imageCode 圖形碼文件
     * @return void
     */
    public static String scan(File imageCode) {
        String text = "";
        try {
            BufferedImage image = ImageIO.read(imageCode);
            if (image == null) {
                return text;
            }
            LuminanceSource source = new BufferedImageLuminanceSource(image);
            BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));

            Map<DecodeHintType, Object> hints = new HashMap<>(3);
            hints.put(DecodeHintType.CHARACTER_SET, "UTF-8");
            hints.put(DecodeHintType.PURE_BARCODE, Boolean.TRUE);
            hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE);
            Result result = new MultiFormatReader().decode(bitmap, hints);
            text = result.getText();
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("無法識(shí)別");
        }
        return text;
    }

    public static String scan(String fileName) {
        return scan(new File(getImageDir(), fileName));
    }

    public static String scan(String fileName, String fileParent) {
        return scan(new File(fileParent, fileName));
    }
}

參考自:Java生成讀取條形碼及二維碼文章來源地址http://www.zghlxwxcb.cn/news/detail-478075.html

到了這里,關(guān)于java生成、識(shí)別條形碼和二維碼的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包