首页 > 其他分享 >二维码生成器

二维码生成器

时间:2023-04-11 19:14:30浏览次数:28  
标签:int 生成器 BufferedImage param height width 二维码

主要的api

  • 生成二维码
  • 生成中间嵌套图片的二维码
  • 解析二维码

导入依赖

        <dependency>
            <groupId>com.google.zxing</groupId>
            <artifactId>core</artifactId>
            <version>3.2.1</version>
        </dependency>
        <dependency>
            <groupId>com.google.zxing</groupId>
            <artifactId>javase</artifactId>
            <version>3.4.1</version>
        </dependency>

代码

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 lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.util.List;
import java.util.*;

/**
 * 二维码生成器
 *
 * @author common
 */
@Slf4j
public class QrCodeUtil {

    private QrCodeUtil() {
        throw new UnsupportedOperationException("cannot be instantiated");
    }

    /**
     * 二维码尺寸List
     */
    public static final List<Integer> SIZE_LIST = Collections.unmodifiableList(Arrays.asList(258, 344, 430, 860, 1280));

    /**
     * 图片的默认设置
     */
    private static final int IMAGE_WIDTH = 100;
    private static final int IMAGE_HEIGHT = 100;
    private static final int IMAGE_HALF_WIDTH = IMAGE_WIDTH / 2;
    private static final int FRAME_WIDTH = 2;

    /**
     * 二维码写码器
     */
    private static MultiFormatWriter multiWriter = new MultiFormatWriter();

    /**
     * 生成中间嵌套图片的二维码(写入文件)
     *
     * @param content       二维码显示的文本
     * @param width         二维码的宽度
     * @param height        二维码的高度
     * @param srcImageInput 中间嵌套的图片流
     * @param destImagePath 二维码生成的地址
     */
    @SneakyThrows
    public static void writeScrQrCode(String content, int width, int height,
                                      InputStream srcImageInput, String destImagePath, String fileName) {
        BufferedImage srcImage = ImageIO.read(srcImageInput);
        //创建文件
        File file = createFile(destImagePath, fileName);
        // ImageIO.write 参数 1、BufferedImage 2、输出的格式 3、输出的文件
        //创建二维码
        BufferedImage image = genBarcode(content, width, height, srcImage);
        //写入文件
        ImageIO.write(image, "png", file);

    }

    /**
     * 生成中间嵌套图片的二维码(写入流)
     *
     * @param content       二维码显示的文本
     * @param width         二维码的宽度
     * @param height        二维码的高度
     * @param srcImageInput 中间嵌套的图片流
     * @param stream
     */
    @SneakyThrows
    public static void writeScrQrCode(String content, int width, int height,
                                      InputStream srcImageInput, OutputStream stream) {
        BufferedImage srcImage = ImageIO.read(srcImageInput);
        //创建二维码
        BufferedImage image = genBarcode(content, width, height, srcImage);
        //写入流
        ImageIO.write(image, "png", stream);

    }

    /**
     * 生成二维码(写到磁盘上)
     * filePath 存放图片的路径
     * fileName 图片的名称
     * info     内容
     * width    图片的宽度
     * height   图片的高度
     *
     * @return 图片路径
     */
    @SneakyThrows
    public static String writeQrCode(String filePath, String fileName, String info, int width, int height) {
        //创建文件路径
        Path path = createPath(filePath, fileName);
        //生成二维码
        Map<EncodeHintType, Object> hints = new EnumMap<>(EncodeHintType.class);
        hints.put(EncodeHintType.CHARACTER_SET, StandardCharsets.UTF_8);
        //生成矩阵
        BitMatrix bitMatrix = new MultiFormatWriter().encode(info,
                BarcodeFormat.QR_CODE, width, height, hints);
        //输出图像
        MatrixToImageWriter.writeToPath(bitMatrix, "png", path);
        return path.toString();
    }

    /**
     * 生成二维码图片(写到流中)
     *
     * @param stream 流
     * @param info   内容
     * @param width  宽
     * @param height 高
     */
    @SneakyThrows
    public static void writeQrCode(OutputStream stream, String info, int width, int height) {
        //生成二维码
        EnumMap<EncodeHintType, Object> hints = new EnumMap<>(EncodeHintType.class);
        hints.put(EncodeHintType.CHARACTER_SET, StandardCharsets.UTF_8);
        hints.put(EncodeHintType.MARGIN, 0);
        //生成矩阵
        BitMatrix bitMatrix = new MultiFormatWriter().encode(info,
                BarcodeFormat.QR_CODE, width, height, hints);
        //去白边
        bitMatrix = deleteWhite(bitMatrix);
        BufferedImage bi = MatrixToImageWriter.toBufferedImage(bitMatrix);
        //调整大小
        bi = zoomInImage(bi, width, height);
        //输出图像
        ImageIO.write(bi, "png", stream);
    }

    /**
     * 解析二维码
     */
    public static String decodeQrCode(InputStream inputStream) {
        try {
            BufferedImage image = ImageIO.read(inputStream);
            LuminanceSource source = new BufferedImageLuminanceSource(image);
            Binarizer binarizer = new HybridBinarizer(source);
            BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer);
            EnumMap<DecodeHintType, Object> hints = new EnumMap<>(DecodeHintType.class);
            hints.put(DecodeHintType.CHARACTER_SET, StandardCharsets.UTF_8);

            // 对图像进行解码
            Result result = new MultiFormatReader().decode(binaryBitmap, hints);
            log.info("图片中内容:{}", result.getText());
            return result.getText();
        } catch (Exception e) {
            log.warn("解析二维码失败,异常信息:{}", e.getMessage());
            throw new IllegalArgumentException("解析二维码失败");
        }

    }

    /**
     * 去除白边
     *
     * @param matrix 矩阵
     * @return
     */
    private static BitMatrix deleteWhite(BitMatrix matrix) {
        int[] rec = matrix.getEnclosingRectangle();
        int resWidth = rec[2] + 1;
        int resHeight = rec[3] + 1;

        BitMatrix resMatrix = new BitMatrix(resWidth, resHeight);
        resMatrix.clear();
        for (int i = 0; i < resWidth; i++) {
            for (int j = 0; j < resHeight; j++) {
                if (matrix.get(i + rec[0], j + rec[1])) {
                    resMatrix.set(i, j);
                }
            }
        }
        return resMatrix;
    }

    /**
     * 将图像调整为指定的宽度和高度
     *
     * @param originalImage 员图像
     * @param width         新的宽度
     * @param height        新的高度
     * @return 调整后的图像
     */
    private static BufferedImage zoomInImage(BufferedImage originalImage, int width, int height) {
        BufferedImage newImage = new BufferedImage(width, height, originalImage.getType());
        Graphics g = newImage.getGraphics();
        g.drawImage(originalImage, 0, 0, width, height, null);
        g.dispose();
        return newImage;
    }

    private static File createFile(String path, String fileName) {
        File dir = new File(path);
        if (!dir.exists()) {
            boolean result = dir.mkdirs();
            log.info("mkdirs result:{}", result);
        }
        return new File(path + fileName);
    }

    /**
     * 创建文件路径
     *
     * @param filePath 路径
     * @param fileName 文件名
     * @return
     */
    private static Path createPath(String filePath, String fileName) {
        Path path = FileSystems.getDefault().getPath(filePath, fileName);
        File dir = new File(filePath);
        if (!dir.exists()) {
            boolean result = dir.mkdirs();
            log.info("mkdirs result:{}", result);
        }
        return path;
    }

    /**
     * 补白
     *
     * @param destImage 原图片
     * @param height    高
     * @param width     宽
     * @return
     */
    private static BufferedImage repairWhite(Image destImage, int height,
                                             int width) {
        BufferedImage image = new BufferedImage(width, height,
                BufferedImage.TYPE_INT_RGB);
        Graphics2D graphic = image.createGraphics();
        graphic.setColor(Color.white);
        graphic.fillRect(0, 0, width, height);
        if (width == destImage.getWidth(null)) {
            graphic.drawImage(destImage, 0, (height - destImage
                            .getHeight(null)) / 2, destImage.getWidth(null),
                    destImage.getHeight(null), Color.white, null);
        } else {
            graphic.drawImage(destImage,
                    (width - destImage.getWidth(null)) / 2, 0, destImage
                            .getWidth(null), destImage.getHeight(null),
                    Color.white, null);
        }
        graphic.dispose();
        return image;
    }

    /**
     * 生成带有中间嵌套图片的二维码
     *
     * @param content  内容
     * @param width    宽
     * @param height   高
     * @param srcImage 中间图片
     * @return
     */
    @SneakyThrows
    private static BufferedImage genBarcode(String content, int width,
                                            int height, BufferedImage srcImage) {
        // 缩放中间嵌套的图片
        BufferedImage scaleImage = scale(srcImage, IMAGE_HEIGHT, IMAGE_WIDTH, false);

        int[] srcPixels = scaleImage.getRGB(0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, null, 0, IMAGE_WIDTH);
        // 设置二维码生成的参数
        Map<EncodeHintType, Object> hint = new EnumMap<>(EncodeHintType.class);
        hint.put(EncodeHintType.CHARACTER_SET, StandardCharsets.UTF_8);
        hint.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
        hint.put(EncodeHintType.MARGIN, 1);

        // 生成二维码
        BitMatrix matrix = multiWriter.encode(content, BarcodeFormat.QR_CODE,
                width, height, hint);

        int[] pixels = new int[width * height];

        int halfW = matrix.getWidth() / 2;
        int halfH = matrix.getHeight() / 2;
        // 设置嵌套图片的边框大小
        int[] frame = {halfW - IMAGE_HALF_WIDTH - FRAME_WIDTH, halfW + IMAGE_HALF_WIDTH + FRAME_WIDTH,
                halfH - IMAGE_HALF_WIDTH - FRAME_WIDTH, halfH + IMAGE_HALF_WIDTH + FRAME_WIDTH};

        for (int y = 0; y < matrix.getHeight(); y++) {
            for (int x = 0; x < matrix.getWidth(); x++) {
                if (x > frame[0] && x < frame[1] && y > frame[2] && y < frame[3]) {
                    // 填充嵌套图片
                    pixels[y * width + x] = srcPixels[(y - halfH + IMAGE_HALF_WIDTH) * IMAGE_WIDTH + x - halfW + IMAGE_HALF_WIDTH];
                } else if (x <= frame[0] || x >= frame[1] || y <= frame[2] || y >= frame[3]) {
                    // 填充二维码
                    pixels[y * width + x] = matrix.get(x, y) ? 0xff000000 : 0xffffffff;
                }
            }
        }

        return createImage(width, height, pixels);
    }

    /**
     * 将像素数组转换为BufferedImage对象
     *
     * @param width  宽
     * @param height 高
     * @param pixels 像素数组
     * @return
     */
    private static BufferedImage createImage(int width, int height, int[] pixels) {
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        image.setRGB(0, 0, width, height, pixels, 0, width);
        return image;
    }

    /**
     * 把传入的原始图像按高度和宽度进行缩放,生成符合要求的图标
     *
     * @param originalImage 源文件
     * @param height        目标高度
     * @param width         目标宽度
     * @param hasFiller     比例不对时是否需要补白:true为补白; false为不补白;
     */
    @SneakyThrows
    public static BufferedImage scale(BufferedImage originalImage, int height,
                                      int width, boolean hasFiller) {
        // 缩放比例
        double ratio;

        Image destImage = originalImage.getScaledInstance(width, height,
                Image.SCALE_SMOOTH);
        // 计算比例
        if ((originalImage.getHeight() > height) || (originalImage.getWidth() > width)) {
            if (originalImage.getHeight() > originalImage.getWidth()) {
                ratio = (double) height
                        / originalImage.getHeight();
            } else {
                ratio = (double) width
                        / originalImage.getWidth();
            }
            AffineTransformOp op = new AffineTransformOp(AffineTransform
                    .getScaleInstance(ratio, ratio), null);
            destImage = op.filter(originalImage, null);
        }
        // 补白
        if (hasFiller) {
            return repairWhite(destImage, height, width);
        }
        return (BufferedImage) destImage;
    }

    @SneakyThrows
    @SuppressWarnings("all")
    public static void main(String[] args) {
        //生成中间镶嵌图片的二维码
        String content = "https://www.cnblogs.com/lyn8100/";
        int width = 300;
        int height = 300;
        InputStream scrImageInput = new FileInputStream(new File("E:\\project\\scr.png"));
        String path = "E:\\project\\";
        String fileName = "testQrCode2.jpg";
        writeScrQrCode(content, width, height, scrImageInput, path, fileName);

        //解析二维码
//        InputStream scrImageInput = new FileInputStream(new File("E:\\project\\testQrCode.jpg"));
//        //"E:\\project\\testQrCode.jpg"
//        System.out.println(decodeQrCode(scrImageInput));
    }

}

标签:int,生成器,BufferedImage,param,height,width,二维码
From: https://www.cnblogs.com/lyn8100/p/17307313.html

相关文章

  • 36.QR二维码检测
    二维码被广泛的应用在我们日常生活中,比如微信和支付宝支付、火车票、商品标识等。二维码的出现极大的方便了我们日常的生活,同时也能将信息较为隐蔽的传输。二维码种类多种多样,有QRCode、DataMatrix、CodeOne等,日常生活中常用的二维码是QR二维码,该二维码样式以及每部分的作......
  • 活动预约报名二维码的制作分享
    随着互联网的普及,越来越多的企业和组织开始采用预约报名二维码作为活动或服务的报名渠道。预约报名二维码目前正广泛应用于各种场景,如展会、活动、讲座、课程等。比如将二维码设计在海报上,通过线下或线上的形式发送给意向客户,客户自行扫码便能查看详细的活动介绍、时间及规则等内容......
  • MyBatisPlus——代码生成器
    代码生成器快速生成各项代码步骤创建Generator类,并创建main方法创建代码生成器AutoGeneratorautoGenerator=newAutoGenerator();连接要生成实体类的数据库DataSourceConfigdataSource=newDataSourceConfig();dataSource.setDriverName(......
  • 全网最详细中英文ChatGPT-GPT-4示例文档-文章大纲智能生成器从0到1快速入门——官网推
    目录Introduce简介setting设置Prompt提示Sampleresponse回复样本APIrequest接口请求python接口请求示例node.js接口请求示例curl命令示例json格式示例其它资料下载ChatGPT是目前最先进的AI聊天机器人,它能够理解图片和文字,生成流畅和有趣的回答。如果你想跟上AI时代的潮流......
  • 生成器、协程
    生成器、协程目录生成器、协程1协程和生成器2生成器Generator2.1列表生成式2.2生成器2.3斐波拉契数列(Fibonacci)2.3.1斐波拉契数列函数写法2.3.2yield方式生成斐波拉契数列函数2.4yield生成器返回值特点2.5yieldfrom3协程3.1协程介绍3.1.1存在yield函数运行过程3.1......
  • mybatis-plus 生成器
    依赖<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-generator</artifactId><version>3.4.1</version></dependency><dependency>......
  • 微信生成带参数二维码,跳转公众号
    classWxfollow{protected$appid='wxf1d959b99f33b156';protected$secret='248f3a560604555ec96215c085cb2723';protected$url="";protected$access_tokens="";publicfunction__con......
  • (第六篇)__iter__、__next__及for循环执行原理(可迭代对象、迭代器、生成器)
    摘要:只要有__iter__,那么这个对象就是可迭代对象,若对象有__iter__和__next__两种方法,则这个对象为迭代器对象。一、概念什么是迭代?迭代就是重复,但是每一次重复都与上一次有关联,这就是迭代。"""这不是迭代,这是简单的重复"""whileTrue:print(1)"""这是迭代。每一......
  • c#OpenQA.Selenium截图二维码
    c#OpenQA.Selenium如何给指定元素截图,比如截图获取二维码,1.获取指定元素节点 varimage=driver.FindElementById("CheckCode");2.使用ITakesScreenshot获取截图并保存 Screenshotscreenshot=((ITakesScreenshot)image).GetScreenshot(); screenshot.SaveAsFile(Login......
  • swoft 获取微信零时二维码 并上传阿里云oss aliyun-oss
      1、获取access_token、两个小时门票过期重新获取publicfunctionAccessToken(){$time=time();$key="wx68065208096access_token";$accessData=DB::table('db_wx_token')->where('key',$key)->value(�......