All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.dromara.hutool.extra.qrcode.QrCodeUtil Maven / Gradle / Ivy

There is a newer version: 6.0.0.M3
Show newest version
/*
 * Copyright (c) 2013-2024 Hutool Team and hutool.cn
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.dromara.hutool.extra.qrcode;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.DecodeHintType;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.GlobalHistogramBinarizer;
import com.google.zxing.common.HybridBinarizer;
import org.dromara.hutool.core.codec.binary.Base64;
import org.dromara.hutool.core.io.IoUtil;
import org.dromara.hutool.core.io.file.FileNameUtil;
import org.dromara.hutool.core.io.file.FileUtil;
import org.dromara.hutool.core.net.url.UrlUtil;
import org.dromara.hutool.core.util.ObjUtil;
import org.dromara.hutool.swing.img.ImgUtil;

import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Map;

/**
 * 基于Zxing的二维码工具类,支持:
 * 
    *
  • 二维码生成和识别,见{@link BarcodeFormat#QR_CODE}
  • *
  • 条形码生成和识别,见{@link BarcodeFormat#CODE_39}等很多标准格式
  • *
* * @author looly * @since 4.0.2 */ public class QrCodeUtil { /** * SVG矢量图格式 */ public static final String QR_TYPE_SVG = "svg"; /** * Ascii Art字符画文本 */ public static final String QR_TYPE_TXT = "txt"; /** * 生成 Base64 编码格式的二维码,以 String 形式表示 * *

* 输出格式为: data:image/[type];base64,[data] *

* * @param content 内容 * @param qrConfig 二维码配置,包括宽度、高度、边距、颜色等 * @param imageType 类型(图片扩展名),见{@link #QR_TYPE_SVG}、 {@link #QR_TYPE_TXT}、{@link ImgUtil} * @return 图片 Base64 编码字符串 */ public static String generateAsBase64DataUri(final String content, final QrConfig qrConfig, final String imageType) { switch (imageType) { case QR_TYPE_SVG: return svgToBase64DataUri(generateAsSvg(content, qrConfig)); case QR_TYPE_TXT: return txtToBase64DataUri(generateAsAsciiArt(content, qrConfig)); default: BufferedImage img = null; try { img = generate(content, qrConfig); return ImgUtil.toBase64DataUri(img, imageType); } finally { ImgUtil.flush(img); } } } /** * 生成PNG格式的二维码图片,以byte[]形式表示 * * @param content 内容 * @param width 宽度 * @param height 高度 * @return 图片的byte[] * @since 4.0.10 */ public static byte[] generatePng(final String content, final int width, final int height) { final ByteArrayOutputStream out = new ByteArrayOutputStream(); generate(content, width, height, ImgUtil.IMAGE_TYPE_PNG, out); return out.toByteArray(); } /** * 生成PNG格式的二维码图片,以byte[]形式表示 * * @param content 内容 * @param config 二维码配置,包括宽度、高度、边距、颜色等 * @return 图片的byte[] * @since 4.1.2 */ public static byte[] generatePng(final String content, final QrConfig config) { final ByteArrayOutputStream out = new ByteArrayOutputStream(); generate(content, config, ImgUtil.IMAGE_TYPE_PNG, out); return out.toByteArray(); } /** * 生成二维码到文件,二维码图片格式取决于文件的扩展名 * * @param content 文本内容 * @param width 宽度(单位:类型为一般图片或SVG时,单位是像素,类型为 Ascii Art 字符画时,单位是字符▄或▀的大小) * @param height 高度(单位:类型为一般图片或SVG时,单位是像素,类型为 Ascii Art 字符画时,单位是字符▄或▀的大小) * @param targetFile 目标文件,扩展名决定输出格式 * @return 目标文件 */ public static File generate(final String content, final int width, final int height, final File targetFile) { return generate(content, QrConfig.of(width, height), targetFile); } /** * 生成二维码到文件,二维码图片格式取决于文件的扩展名 * * @param content 文本内容 * @param config 二维码配置,包括宽度、高度、边距、颜色等 * @param targetFile 目标文件,扩展名决定输出格式 * @return 目标文件 * @since 4.1.2 */ public static File generate(final String content, final QrConfig config, final File targetFile) { final String extName = FileNameUtil.extName(targetFile); switch (extName) { case QR_TYPE_SVG: FileUtil.writeUtf8String(generateAsSvg(content, config), targetFile); break; case QR_TYPE_TXT: FileUtil.writeUtf8String(generateAsAsciiArt(content, config), targetFile); break; default: BufferedImage image = null; try { image = generate(content, config); ImgUtil.write(image, targetFile); } finally { ImgUtil.flush(image); } } return targetFile; } /** * 生成二维码到输出流 * * @param content 文本内容 * @param width 宽度(单位:类型为一般图片或SVG时,单位是像素,类型为 Ascii Art 字符画时,单位是字符▄或▀的大小) * @param height 高度(单位:类型为一般图片或SVG时,单位是像素,类型为 Ascii Art 字符画时,单位是字符▄或▀的大小) * @param imageType 类型(图片扩展名),见{@link #QR_TYPE_SVG}、 {@link #QR_TYPE_TXT}、{@link ImgUtil} * @param out 目标流 */ public static void generate(final String content, final int width, final int height, final String imageType, final OutputStream out) { generate(content, QrConfig.of(width, height), imageType, out); } /** * 生成二维码到输出流 * * @param content 文本内容 * @param config 二维码配置,包括宽度、高度、边距、颜色等 * @param imageType 图片类型(图片扩展名),见{@link ImgUtil} * @param out 目标流 * @since 4.1.2 */ public static void generate(final String content, final QrConfig config, final String imageType, final OutputStream out) { switch (imageType) { case QR_TYPE_SVG: IoUtil.writeUtf8(out, false, generateAsSvg(content, config)); break; case QR_TYPE_TXT: IoUtil.writeUtf8(out, false, generateAsAsciiArt(content, config)); break; default: BufferedImage img = null; try { img = generate(content, config); ImgUtil.write(img, imageType, out); } finally { ImgUtil.flush(img); } } } /** * 生成二维码图片 * * @param content 文本内容 * @param width 宽度 * @param height 高度 * @return 二维码图片(黑白) */ public static BufferedImage generate(final String content, final int width, final int height) { return generate(content, QrConfig.of(width, height)); } /** * 生成二维码或条形码图片
* 只有二维码时QrConfig中的图片才有效 * * @param content 文本内容 * @param config 二维码配置,包括宽度、高度、边距、颜色等 * @return 二维码图片(黑白) * @since 4.1.14 */ public static BufferedImage generate(final String content, final QrConfig config) { return new QrImage(content, ObjUtil.defaultIfNull(config, QrConfig::new)); } // ------------------------------------------------------------------------------------------------------------------- encode /** * 将文本内容编码为条形码或二维码 * * @param content 文本内容 * @param config 二维码配置,包括宽度、高度、边距、颜色、格式等 * @return {@link BitMatrix} * @since 4.1.2 */ public static BitMatrix encode(final CharSequence content, final QrConfig config) { return QrEncoder.of(config).encode(content); } // ------------------------------------------------------------------------------------------------------------------- decode /** * 解码二维码或条形码图片为文本 * * @param qrCodeInputstream 二维码输入流 * @return 解码文本 */ public static String decode(final InputStream qrCodeInputstream) { BufferedImage image = null; try { image = ImgUtil.read(qrCodeInputstream); return decode(image); } finally { ImgUtil.flush(image); } } /** * 解码二维码或条形码图片为文本 * * @param qrCodeFile 二维码文件 * @return 解码文本 */ public static String decode(final File qrCodeFile) { BufferedImage image = null; try { image = ImgUtil.read(qrCodeFile); return decode(image); } finally { ImgUtil.flush(image); } } /** * 将二维码或条形码图片解码为文本 * * @param image {@link Image} 二维码图片 * @return 解码后的文本 */ public static String decode(final Image image) { return decode(image, true, false); } /** * 将二维码或条形码图片解码为文本
* 此方法会尝试使用{@link HybridBinarizer}和{@link GlobalHistogramBinarizer}两种模式解析
* 需要注意部分二维码如果不带logo,使用PureBarcode模式会解析失败,此时须设置此选项为false。 * * @param image {@link Image} 二维码图片 * @param isTryHarder 是否优化精度 * @param isPureBarcode 是否使用复杂模式,扫描带logo的二维码设为true * @return 解码后的文本 * @since 4.3.1 */ public static String decode(final Image image, final boolean isTryHarder, final boolean isPureBarcode) { return QrDecoder.of(isTryHarder, isPureBarcode).decode(image); } /** * 将二维码或条形码图片解码为文本
* 此方法会尝试使用{@link HybridBinarizer}和{@link GlobalHistogramBinarizer}两种模式解析
* 需要注意部分二维码如果不带logo,使用PureBarcode模式会解析失败,此时须设置此选项为false。 * * @param image {@link Image} 二维码图片 * @param hints 自定义扫码配置,包括算法、编码、复杂模式等 * @return 解码后的文本 * @since 5.7.12 */ public static String decode(final Image image, final Map hints) { return QrDecoder.of(hints).decode(image); } /** * BitMatrix转BufferedImage * * @param matrix BitMatrix * @param foreColor 前景色 * @param backColor 背景色(null表示透明背景) * @return BufferedImage * @since 4.1.2 */ public static BufferedImage toImage(final BitMatrix matrix, final int foreColor, final Integer backColor) { final int width = matrix.getWidth(); final int height = matrix.getHeight(); final BufferedImage image = new BufferedImage(width, height, null == backColor ? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB); for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { if (matrix.get(x, y)) { image.setRGB(x, y, foreColor); } else if (null != backColor) { image.setRGB(x, y, backColor); } } } return image; } /** * @param content 内容 * @param qrConfig 二维码配置,包括宽度、高度、边距、颜色等 * @return SVG矢量图(字符串) * @since 5.8.6 */ public static String generateAsSvg(final String content, final QrConfig qrConfig) { return toSVG(encode(content, qrConfig), qrConfig); } /** * BitMatrix转SVG(字符串) * * @param matrix BitMatrix * @param config {@link QrConfig} * @return SVG矢量图(字符串) */ public static String toSVG(final BitMatrix matrix, final QrConfig config) { return new QrSVG(matrix, config).toString(); } /** * 生成ASCII Art字符画形式的二维码 * * @param content 内容 * @param qrConfig 二维码配置,仅宽度、高度、边距配置有效 * @return ASCII Art字符画形式的二维码 * @since 5.8.6 */ public static String generateAsAsciiArt(final String content, final QrConfig qrConfig) { return toAsciiArt(encode(content, qrConfig), qrConfig); } /** * BitMatrix转ASCII Art字符画形式的二维码 * * @param bitMatrix BitMatrix * @param qrConfig QR设置 * @return ASCII Art字符画形式的二维码 * @since 5.8.6 */ public static String toAsciiArt(final BitMatrix bitMatrix, final QrConfig qrConfig) { return new QrAsciiArt(bitMatrix, qrConfig).toString(); } // region ----- Private Methods /** * 将文本转换为Base64编码的Data URI。 * * @param txt 需要转换为Base64编码Data URI的文本。 * @return 转换后的Base64编码Data URI字符串。 */ private static String txtToBase64DataUri(final String txt) { return UrlUtil.getDataUriBase64("text/plain", Base64.encode(txt)); } /** * 将SVG字符串转换为Base64数据URI格式。 *

此方法通过将SVG内容编码为Base64,并将其封装在数据URI中,以便于在HTML或CSS中直接嵌入SVG图像。

* * @param svg SVG图像的内容,为字符串形式。 * @return 转换后的Base64数据URI字符串,可用于直接在HTML或CSS中显示SVG图像。 */ private static String svgToBase64DataUri(final String svg) { return UrlUtil.getDataUriBase64("image/svg+xml", Base64.encode(svg)); } // endregion }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy