From e2bb215387b0d5e77986962ceca4f002f978f6a7 Mon Sep 17 00:00:00 2001 From: Looly Date: Fri, 24 May 2024 17:22:17 +0800 Subject: [PATCH] add svg support --- .../hutool/extra/qrcode/QrCodeUtil.java | 130 ++++++++++++------ 1 file changed, 87 insertions(+), 43 deletions(-) diff --git a/hutool-extra/src/main/java/org/dromara/hutool/extra/qrcode/QrCodeUtil.java b/hutool-extra/src/main/java/org/dromara/hutool/extra/qrcode/QrCodeUtil.java index fffefb71a..d195abf7f 100644 --- a/hutool-extra/src/main/java/org/dromara/hutool/extra/qrcode/QrCodeUtil.java +++ b/hutool-extra/src/main/java/org/dromara/hutool/extra/qrcode/QrCodeUtil.java @@ -12,13 +12,18 @@ package org.dromara.hutool.extra.qrcode; -import org.dromara.hutool.core.util.ObjUtil; -import org.dromara.hutool.swing.img.ImgUtil; 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; @@ -58,16 +63,23 @@ public class QrCodeUtil { * * @param content 内容 * @param qrConfig 二维码配置,包括宽度、高度、边距、颜色等 - * @param imageType 图片类型(图片扩展名),见{@link ImgUtil} + * @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) { - BufferedImage img = null; - try{ - img = generate(content, qrConfig); - return ImgUtil.toBase64DataUri(img, imageType); - } finally { - ImgUtil.flush(img); + 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); + } } } @@ -104,20 +116,13 @@ public class QrCodeUtil { * 生成二维码到文件,二维码图片格式取决于文件的扩展名 * * @param content 文本内容 - * @param width 宽度 - * @param height 高度 + * @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) { - BufferedImage image = null; - try{ - image = generate(content, width, height); - ImgUtil.write(image, targetFile); - } finally { - ImgUtil.flush(image); - } - return targetFile; + return generate(content, QrConfig.of(width, height), targetFile); } /** @@ -130,13 +135,24 @@ public class QrCodeUtil { * @since 4.1.2 */ public static File generate(final String content, final QrConfig config, final File targetFile) { - BufferedImage image = null; - try{ - image = generate(content, config); - ImgUtil.write(image, targetFile); - } finally { - ImgUtil.flush(image); + 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; } @@ -144,19 +160,13 @@ public class QrCodeUtil { * 生成二维码到输出流 * * @param content 文本内容 - * @param width 宽度 - * @param height 高度 - * @param imageType 图片类型(图片扩展名),见{@link ImgUtil} + * @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) { - BufferedImage img = null; - try{ - img = generate(content, width, height); - ImgUtil.write(img, imageType, out); - } finally { - ImgUtil.flush(img); - } + generate(content, QrConfig.of(width, height), imageType, out); } /** @@ -169,12 +179,21 @@ public class QrCodeUtil { * @since 4.1.2 */ public static void generate(final String content, final QrConfig config, final String imageType, final OutputStream out) { - BufferedImage image = null; - try{ - image = generate(content, config); - ImgUtil.write(image, imageType, out); - } finally { - ImgUtil.flush(image); + 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); + } } } @@ -227,7 +246,7 @@ public class QrCodeUtil { */ public static String decode(final InputStream qrCodeInputstream) { BufferedImage image = null; - try{ + try { image = ImgUtil.read(qrCodeInputstream); return decode(image); } finally { @@ -243,7 +262,7 @@ public class QrCodeUtil { */ public static String decode(final File qrCodeFile) { BufferedImage image = null; - try{ + try { image = ImgUtil.read(qrCodeFile); return decode(image); } finally { @@ -359,4 +378,29 @@ public class QrCodeUtil { 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 }