From ea06be85e9d0f2a437475c30c8046d476a6b2f0e Mon Sep 17 00:00:00 2001 From: TomXin <766781886@qq.com> Date: Sun, 21 Aug 2022 23:31:18 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E7=94=9F=E6=88=90AsciiArt?= =?UTF-8?q?=E5=AD=97=E7=AC=A6=E7=94=BB=E4=BA=8C=E7=BB=B4=E7=A0=81=E3=80=81?= =?UTF-8?q?SVG=E4=BA=8C=E7=BB=B4=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cn/hutool/extra/qrcode/QrCodeUtil.java | 137 +++++++++++++----- .../java/cn/hutool/extra/qrcode/QrConfig.java | 2 +- .../hutool/extra/qrcode/QrCodeUtilTest.java | 44 +++++- 3 files changed, 135 insertions(+), 48 deletions(-) diff --git a/hutool-extra/src/main/java/cn/hutool/extra/qrcode/QrCodeUtil.java b/hutool-extra/src/main/java/cn/hutool/extra/qrcode/QrCodeUtil.java index 287af4595..75448c727 100755 --- a/hutool-extra/src/main/java/cn/hutool/extra/qrcode/QrCodeUtil.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/qrcode/QrCodeUtil.java @@ -3,20 +3,15 @@ package cn.hutool.extra.qrcode; import cn.hutool.core.codec.Base64; import cn.hutool.core.img.Img; import cn.hutool.core.img.ImgUtil; -import cn.hutool.core.lang.ansi.*; +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.IoUtil; +import cn.hutool.core.lang.ansi.Ansi8BitColor; +import cn.hutool.core.lang.ansi.AnsiElement; +import cn.hutool.core.lang.ansi.AnsiEncoder; import cn.hutool.core.util.CharsetUtil; import cn.hutool.core.util.NumberUtil; import cn.hutool.core.util.StrUtil; -import com.google.zxing.BarcodeFormat; -import com.google.zxing.Binarizer; -import com.google.zxing.BinaryBitmap; -import com.google.zxing.DecodeHintType; -import com.google.zxing.LuminanceSource; -import com.google.zxing.MultiFormatReader; -import com.google.zxing.MultiFormatWriter; -import com.google.zxing.NotFoundException; -import com.google.zxing.Result; -import com.google.zxing.WriterException; +import com.google.zxing.*; import com.google.zxing.common.BitMatrix; import com.google.zxing.common.GlobalHistogramBinarizer; import com.google.zxing.common.HybridBinarizer; @@ -27,6 +22,7 @@ import java.io.ByteArrayOutputStream; import java.io.File; import java.io.InputStream; import java.io.OutputStream; +import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; @@ -42,6 +38,9 @@ import java.util.Map; */ public class QrCodeUtil { + public static final String QR_TYPE_SVG = "svg";// SVG矢量图格式 + public static final String QR_TYPE_TXT = "txt";// Ascii Art字符画文本 + /** * 生成代 logo 图片的 Base64 编码格式的二维码,以 String 形式表示 * @@ -186,8 +185,22 @@ public class QrCodeUtil { * @return 目标文件 */ public static File generate(String content, int width, int height, File targetFile) { - final BufferedImage image = generate(content, width, height); - ImgUtil.write(image, targetFile); + String extName = FileUtil.extName(targetFile); + switch (extName) { + case QR_TYPE_SVG: + String svg = generateAsSvg(content, new QrConfig(width, height)); + FileUtil.writeString(svg, targetFile, StandardCharsets.UTF_8); + break; + case QR_TYPE_TXT: + String txt = generateAsAsciiArt(content, new QrConfig(width, height)); + FileUtil.writeString(txt, targetFile, StandardCharsets.UTF_8); + break; + default: + final BufferedImage image = generate(content, width, height); + ImgUtil.write(image, targetFile); + break; + } + return targetFile; } @@ -201,23 +214,48 @@ public class QrCodeUtil { * @since 4.1.2 */ public static File generate(String content, QrConfig config, File targetFile) { - final BufferedImage image = generate(content, config); - ImgUtil.write(image, targetFile); + String extName = FileUtil.extName(targetFile); + switch (extName) { + case QR_TYPE_SVG: + final String svg = generateAsSvg(content, config); + FileUtil.writeString(svg, targetFile, StandardCharsets.UTF_8); + break; + case QR_TYPE_TXT: + final String txt = generateAsAsciiArt(content, config); + FileUtil.writeString(txt, targetFile, StandardCharsets.UTF_8); + break; + default: + final BufferedImage image = generate(content, config); + ImgUtil.write(image, targetFile); + break; + } return targetFile; } /** * 生成二维码到输出流 * - * @param content 文本内容 - * @param width 宽度 - * @param height 高度 - * @param imageType 图片类型(图片扩展名),见{@link ImgUtil} - * @param out 目标流 + * @param content 文本内容 + * @param width 宽度 + * @param height 高度 + * @param targetType 类型(图片扩展名),见{@link #QR_TYPE_SVG}、 {@link #QR_TYPE_TXT}、{@link ImgUtil} + * @param out 目标流 */ - public static void generate(String content, int width, int height, String imageType, OutputStream out) { - final BufferedImage image = generate(content, width, height); - ImgUtil.write(image, imageType, out); + public static void generate(String content, int width, int height, String targetType, OutputStream out) { + switch (targetType) { + case QR_TYPE_SVG: + final String svg = generateAsSvg(content, new QrConfig(width, height)); + IoUtil.writeUtf8(out, false, svg); + break; + case QR_TYPE_TXT: + final String txt = generateAsAsciiArt(content, new QrConfig(width, height)); + IoUtil.writeUtf8(out, false, txt); + break; + default: + final BufferedImage image = generate(content, width, height); + ImgUtil.write(image, targetType, out); + break; + } } /** @@ -225,13 +263,25 @@ public class QrCodeUtil { * * @param content 文本内容 * @param config 二维码配置,包括长、宽、边距、颜色等 - * @param imageType 图片类型(图片扩展名),见{@link ImgUtil} + * @param targetType 类型(图片扩展名),见{@link #QR_TYPE_SVG}、 {@link #QR_TYPE_TXT}、{@link ImgUtil} * @param out 目标流 * @since 4.1.2 */ - public static void generate(String content, QrConfig config, String imageType, OutputStream out) { - final BufferedImage image = generate(content, config); - ImgUtil.write(image, imageType, out); + public static void generate(String content, QrConfig config, String targetType, OutputStream out) { + switch (targetType) { + case QR_TYPE_SVG: + final String svg = generateAsSvg(content, config); + IoUtil.writeUtf8(out, false, svg); + break; + case QR_TYPE_TXT: + final String txt = generateAsAsciiArt(content, config); + IoUtil.writeUtf8(out, false, txt); + break; + default: + final BufferedImage image = generate(content, config); + ImgUtil.write(image, targetType, out); + break; + } } /** @@ -479,7 +529,7 @@ public class QrCodeUtil { * @since 5.8.6 */ public static String toSVG(BitMatrix matrix, QrConfig qrConfig) { - return toSVG(matrix, qrConfig.getForeColor(), qrConfig.getBackColor(), qrConfig.img, qrConfig.getRatio()); + return toSVG(matrix, qrConfig.foreColor, qrConfig.backColor, qrConfig.img, qrConfig.getRatio()); } /** @@ -524,16 +574,24 @@ public class QrCodeUtil { logoY = (qrHeight - logoHeight) / 2; } + Color fore = new Color(foreColor, true); - Color back = new Color(backColor, true); - return "\n" + - " \n" + - (StrUtil.isBlank(logoBase64) ? "" : "\n") + - ""; + + StringBuilder result = StrUtil.builder(); + result.append("\n"); + result.append(" \n"); + if (StrUtil.isNotBlank(logoBase64)) { + result.append("\n"); + } + result.append(""); + return result.toString(); } /** @@ -547,8 +605,9 @@ public class QrCodeUtil { int width = bitMatrix.getWidth(); int height = bitMatrix.getHeight(); - AnsiElement foreground = Ansi8BitColor.foreground(rgbToAnsi8BitValue(qrConfig.getForeColor())); - AnsiElement background = Ansi8BitColor.background(rgbToAnsi8BitValue(qrConfig.getBackColor())); + + AnsiElement foreground = qrConfig.foreColor == null ? null : Ansi8BitColor.foreground(rgbToAnsi8BitValue(qrConfig.foreColor)); + AnsiElement background = qrConfig.backColor == null ? null : Ansi8BitColor.background(rgbToAnsi8BitValue(qrConfig.backColor)); StringBuilder builder = new StringBuilder(); for (int i = 0; i <= height; i += 2) { diff --git a/hutool-extra/src/main/java/cn/hutool/extra/qrcode/QrConfig.java b/hutool-extra/src/main/java/cn/hutool/extra/qrcode/QrConfig.java index 91675cc16..4d5a388d8 100755 --- a/hutool-extra/src/main/java/cn/hutool/extra/qrcode/QrConfig.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/qrcode/QrConfig.java @@ -30,7 +30,7 @@ public class QrConfig { /** 长 */ protected int height; /** 前景色(二维码颜色) */ - protected int foreColor = BLACK; + protected Integer foreColor = BLACK; /** 背景色,默认白色,null表示透明 */ protected Integer backColor = WHITE; /** 边距1~4 */ diff --git a/hutool-extra/src/test/java/cn/hutool/extra/qrcode/QrCodeUtilTest.java b/hutool-extra/src/test/java/cn/hutool/extra/qrcode/QrCodeUtilTest.java index 799e23361..ab07bde11 100755 --- a/hutool-extra/src/test/java/cn/hutool/extra/qrcode/QrCodeUtilTest.java +++ b/hutool-extra/src/test/java/cn/hutool/extra/qrcode/QrCodeUtilTest.java @@ -4,19 +4,19 @@ import cn.hutool.core.codec.Base64; import cn.hutool.core.img.ImgUtil; import cn.hutool.core.io.FileUtil; import cn.hutool.core.lang.Console; -import cn.hutool.core.lang.ansi.Ansi8BitColor; -import cn.hutool.core.lang.ansi.AnsiEncoder; import com.google.zxing.BarcodeFormat; -import com.google.zxing.common.BitMatrix; import com.google.zxing.datamatrix.encoder.SymbolShapeHint; import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; import org.junit.Assert; import org.junit.Ignore; import org.junit.Test; -import java.awt.Color; +import java.awt.*; import java.awt.image.BufferedImage; +import java.io.BufferedOutputStream; +import java.io.BufferedReader; import java.io.File; +import java.io.IOException; import java.nio.charset.StandardCharsets; /** @@ -41,7 +41,7 @@ public class QrCodeUtilTest { // 背景色透明 config.setBackColor(null); config.setErrorCorrection(ErrorCorrectionLevel.H); - String path = FileUtil.isWindows() ? "d:/test/qrcodeCustom.png" : "~/Desktop/hutool/qrcodeCustom.png"; + String path = FileUtil.isWindows() ? "d:/test/qrcodeCustom.txt" : "~/Desktop/hutool/qrcodeCustom.svg"; QrCodeUtil.generate("https://hutool.cn/", config, FileUtil.touch(path)); } @@ -120,14 +120,13 @@ public class QrCodeUtilTest { .setMargin(1); String svg = QrCodeUtil.generateAsSvg("https://hutool.cn/", qrConfig); Assert.assertNotNull(svg); - FileUtil.writeString(svg, "d:/test/qr.svg", StandardCharsets.UTF_8); } @Test public void generateAsciiArtTest() { QrConfig qrConfig = QrConfig.create() - .setForeColor(new Color(0,255,0)) - .setBackColor(new Color(0,0,0)) + .setForeColor(new Color(255,0,255)) + .setBackColor(new Color(0,255,0)) .setWidth(0) .setHeight(0).setMargin(1); String asciiArt = QrCodeUtil.generateAsAsciiArt("https://hutool.cn/",qrConfig); @@ -135,4 +134,33 @@ public class QrCodeUtilTest { System.out.println(asciiArt); } + @Test + public void generateToFileTest() { + QrConfig qrConfig = QrConfig.create() + .setForeColor(Color.BLUE) + .setBackColor(new Color(0,200,255)) + .setWidth(0) + .setHeight(0).setMargin(1); + File qrFile = QrCodeUtil.generate("https://hutool.cn/", qrConfig, FileUtil.touch("d:/test/ascii_art_qr_code.txt")); + BufferedReader reader = FileUtil.getReader(qrFile, StandardCharsets.UTF_8); + reader.lines().forEach(System.out::println); + } + + @Test + public void generateToStreamTest() { + QrConfig qrConfig = QrConfig.create() + .setForeColor(Color.BLUE) + .setBackColor(new Color(0,200,255)) + .setWidth(0) + .setHeight(0).setMargin(1); + String filepath = "d:/test/qr_stream_to_txt.txt"; + try (BufferedOutputStream outputStream = FileUtil.getOutputStream(filepath)) { + QrCodeUtil.generate("https://hutool.cn/", qrConfig,"txt", outputStream); + }catch (IOException e){ + e.printStackTrace(); + } + BufferedReader reader = FileUtil.getReader(filepath, StandardCharsets.UTF_8); + reader.lines().forEach(System.out::println); + } + }