优化QrCodeUtil

This commit is contained in:
TomXin 2022-08-27 16:01:18 +08:00
parent 4e53873d81
commit e78273af7f
2 changed files with 35 additions and 44 deletions

View File

@ -5,11 +5,11 @@ import cn.hutool.core.img.Img;
import cn.hutool.core.img.ImgUtil; import cn.hutool.core.img.ImgUtil;
import cn.hutool.core.io.FileUtil; import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil; import cn.hutool.core.io.IoUtil;
import cn.hutool.core.lang.ansi.Ansi8BitColor; import cn.hutool.core.lang.ansi.AnsiColorWrapper;
import cn.hutool.core.lang.ansi.AnsiColors;
import cn.hutool.core.lang.ansi.AnsiElement; import cn.hutool.core.lang.ansi.AnsiElement;
import cn.hutool.core.lang.ansi.AnsiEncoder; import cn.hutool.core.lang.ansi.AnsiEncoder;
import cn.hutool.core.util.CharsetUtil; import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil; import cn.hutool.core.util.URLUtil;
import com.google.zxing.*; import com.google.zxing.*;
@ -41,6 +41,7 @@ public class QrCodeUtil {
public static final String QR_TYPE_SVG = "svg";// SVG矢量图格式 public static final String QR_TYPE_SVG = "svg";// SVG矢量图格式
public static final String QR_TYPE_TXT = "txt";// Ascii Art字符画文本 public static final String QR_TYPE_TXT = "txt";// Ascii Art字符画文本
private static final AnsiColors ansiColors= new AnsiColors(AnsiColors.BitDepth.EIGHT);
/** /**
* 生成代 logo 图片的 Base64 编码格式的二维码 String 形式表示 * 生成代 logo 图片的 Base64 编码格式的二维码 String 形式表示
@ -631,8 +632,8 @@ public class QrCodeUtil {
final int height = bitMatrix.getHeight(); final int height = bitMatrix.getHeight();
final AnsiElement foreground = qrConfig.foreColor == null ? null : Ansi8BitColor.foreground(rgbToAnsi8BitValue(qrConfig.foreColor)); final AnsiElement foreground = qrConfig.foreColor == null ? null : rgbToAnsi8BitElement(qrConfig.foreColor, AnsiColorWrapper.ForeOrBack.FORE);
final AnsiElement background = qrConfig.backColor == null ? null : Ansi8BitColor.background(rgbToAnsi8BitValue(qrConfig.backColor)); final AnsiElement background = qrConfig.backColor == null ? null : rgbToAnsi8BitElement(qrConfig.backColor, AnsiColorWrapper.ForeOrBack.BACK);
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
for (int i = 0; i <= height; i += 2) { for (int i = 0; i <= height; i += 2) {
@ -655,26 +656,16 @@ public class QrCodeUtil {
return builder.toString(); return builder.toString();
} }
/** /* *//**
* rgb转Ansi8Bit值 * rgb转AnsiElement
* *
* @param rgb rgb颜色值 * @param rgb rgb颜色值
* @return Ansi8bit颜色值 * @param foreOrBack 前景or背景
* @return AnsiElement
* @since 5.8.6 * @since 5.8.6
*/ */
private static int rgbToAnsi8BitValue(int rgb) { private static AnsiElement rgbToAnsi8BitElement(int rgb,AnsiColorWrapper.ForeOrBack foreOrBack) {
final int r = (rgb >> 16) & 0xff; return ansiColors.findClosest(new Color(rgb)).toAnsiElement(foreOrBack);
final int g = (rgb >> 8) & 0xff;
final int b = (rgb) & 0xff;
final int l;
if (r == g && g == b) {
final int i = (int) (NumberUtil.div(NumberUtil.mul(r - 10.625, 23), (255 - 10.625), 0));
l = i >= 0 ? 232 + i : 0;
} else {
l = 16 + (int) (36 * NumberUtil.div(NumberUtil.mul(r, 5), 255, 0)) + (int) (6.0 * (g / 256.0 * 6.0)) + (int) (b / 256.0 * 6.0);
}
return l;
} }

View File

@ -3,11 +3,11 @@ package cn.hutool.extra.qrcode;
import cn.hutool.core.codec.Base64; import cn.hutool.core.codec.Base64;
import cn.hutool.core.img.ImgUtil; import cn.hutool.core.img.ImgUtil;
import cn.hutool.core.io.FileUtil; import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.Console; import cn.hutool.core.lang.Console;
import com.google.zxing.BarcodeFormat; import com.google.zxing.BarcodeFormat;
import com.google.zxing.datamatrix.encoder.SymbolShapeHint; import com.google.zxing.datamatrix.encoder.SymbolShapeHint;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import org.junit.Assert;
import org.junit.Ignore; import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
@ -29,7 +29,7 @@ public class QrCodeUtilTest {
@Test @Test
public void generateTest() { public void generateTest() {
final BufferedImage image = QrCodeUtil.generate("https://hutool.cn/", 300, 300); final BufferedImage image = QrCodeUtil.generate("https://hutool.cn/", 300, 300);
Assert.assertNotNull(image); Assert.notNull(image);
} }
@Test @Test
@ -72,7 +72,7 @@ public class QrCodeUtilTest {
@Ignore @Ignore
public void decodeTest() { public void decodeTest() {
final String decode = QrCodeUtil.decode(FileUtil.file("d:/test/pic/qr.png")); final String decode = QrCodeUtil.decode(FileUtil.file("d:/test/pic/qr.png"));
Console.log(decode); //Console.log(decode);
} }
@Test @Test
@ -80,13 +80,13 @@ public class QrCodeUtilTest {
public void decodeTest2() { public void decodeTest2() {
// 条形码 // 条形码
final String decode = QrCodeUtil.decode(FileUtil.file("d:/test/90.png")); final String decode = QrCodeUtil.decode(FileUtil.file("d:/test/90.png"));
Console.log(decode); //Console.log(decode);
} }
@Test @Test
public void generateAsBase64Test() { public void generateAsBase64Test() {
final String base64 = QrCodeUtil.generateAsBase64("https://hutool.cn/", new QrConfig(400, 400), "png"); final String base64 = QrCodeUtil.generateAsBase64("https://hutool.cn/", new QrConfig(400, 400), "png");
Assert.assertNotNull(base64); Assert.notNull(base64);
} }
@Test @Test
@ -96,27 +96,27 @@ public class QrCodeUtilTest {
new File("d:/test/qr.png")); new File("d:/test/qr.png"));
final String encode = Base64.encode(bytes); final String encode = Base64.encode(bytes);
final String base641 = QrCodeUtil.generateAsBase64("https://hutool.cn/", new QrConfig(400, 400), "png", encode); final String base641 = QrCodeUtil.generateAsBase64("https://hutool.cn/", new QrConfig(400, 400), "png", encode);
Assert.assertNotNull(base641); Assert.notNull(base641);
} }
@Test @Test
public void generateAsBase64Test3() { public void generateAsBase64Test3() {
final String base64 = QrCodeUtil.generateAsBase64("https://hutool.cn/", new QrConfig(400, 400), "svg"); final String base64 = QrCodeUtil.generateAsBase64("https://hutool.cn/", new QrConfig(400, 400), "svg");
Assert.assertNotNull(base64); Assert.notNull(base64);
System.out.println(base64); //Console.log(base64);
} }
@Test @Test
@Ignore @Ignore
public void decodeTest3() { public void decodeTest3() {
final String decode = QrCodeUtil.decode(ImgUtil.read("d:/test/qr_a.png"), false, true); final String decode = QrCodeUtil.decode(ImgUtil.read("d:/test/qr_a.png"), false, true);
Console.log(decode); //Console.log(decode);
} }
@Test @Test
public void pdf417Test() { public void pdf417Test() {
final BufferedImage image = QrCodeUtil.generate("content111", BarcodeFormat.PDF_417, QrConfig.create()); final BufferedImage image = QrCodeUtil.generate("content111", BarcodeFormat.PDF_417, QrConfig.create());
Assert.assertNotNull(image); Assert.notNull(image);
} }
@Test @Test
@ -124,11 +124,11 @@ public class QrCodeUtilTest {
final QrConfig qrConfig = QrConfig.create(); final QrConfig qrConfig = QrConfig.create();
qrConfig.setShapeHint(SymbolShapeHint.FORCE_RECTANGLE); qrConfig.setShapeHint(SymbolShapeHint.FORCE_RECTANGLE);
final BufferedImage image = QrCodeUtil.generate("content111", BarcodeFormat.DATA_MATRIX, qrConfig); final BufferedImage image = QrCodeUtil.generate("content111", BarcodeFormat.DATA_MATRIX, qrConfig);
Assert.assertNotNull(image); Assert.notNull(image);
final QrConfig config = QrConfig.create(); final QrConfig config = QrConfig.create();
config.setShapeHint(SymbolShapeHint.FORCE_SQUARE); config.setShapeHint(SymbolShapeHint.FORCE_SQUARE);
final BufferedImage imageSquare = QrCodeUtil.generate("content111", BarcodeFormat.DATA_MATRIX, qrConfig); final BufferedImage imageSquare = QrCodeUtil.generate("content111", BarcodeFormat.DATA_MATRIX, qrConfig);
Assert.assertNotNull(imageSquare); Assert.notNull(imageSquare);
} }
@Test @Test
@ -142,7 +142,7 @@ public class QrCodeUtilTest {
.setErrorCorrection(ErrorCorrectionLevel.M) .setErrorCorrection(ErrorCorrectionLevel.M)
.setMargin(1); .setMargin(1);
final String svg = QrCodeUtil.generateAsSvg("https://hutool.cn/", qrConfig); final String svg = QrCodeUtil.generateAsSvg("https://hutool.cn/", qrConfig);
Assert.assertNotNull(svg); Assert.notNull(svg);
FileUtil.writeString(svg, FileUtil.touch("d:/test/hutool_qr.svg"),StandardCharsets.UTF_8); FileUtil.writeString(svg, FileUtil.touch("d:/test/hutool_qr.svg"),StandardCharsets.UTF_8);
} }
@ -154,8 +154,8 @@ public class QrCodeUtilTest {
.setWidth(0) .setWidth(0)
.setHeight(0).setMargin(1); .setHeight(0).setMargin(1);
final String asciiArt = QrCodeUtil.generateAsAsciiArt("https://hutool.cn/",qrConfig); final String asciiArt = QrCodeUtil.generateAsAsciiArt("https://hutool.cn/",qrConfig);
Assert.assertNotNull(asciiArt); Assert.notNull(asciiArt);
//Console.log(asciiArt); Console.log(asciiArt);
} }
@Test @Test
@ -166,7 +166,7 @@ public class QrCodeUtilTest {
.setWidth(0) .setWidth(0)
.setHeight(0).setMargin(1); .setHeight(0).setMargin(1);
final String asciiArt = QrCodeUtil.generateAsAsciiArt("https://hutool.cn/",qrConfig); final String asciiArt = QrCodeUtil.generateAsAsciiArt("https://hutool.cn/",qrConfig);
Assert.assertNotNull(asciiArt); Assert.notNull(asciiArt);
//Console.log(asciiArt); //Console.log(asciiArt);
} }
@ -180,8 +180,8 @@ public class QrCodeUtilTest {
.setWidth(0) .setWidth(0)
.setHeight(0).setMargin(1); .setHeight(0).setMargin(1);
final File qrFile = QrCodeUtil.generate("https://hutool.cn/", qrConfig, FileUtil.touch("d:/test/ascii_art_qr_code.txt")); final File qrFile = QrCodeUtil.generate("https://hutool.cn/", qrConfig, FileUtil.touch("d:/test/ascii_art_qr_code.txt"));
final BufferedReader reader = FileUtil.getReader(qrFile, StandardCharsets.UTF_8); //final BufferedReader reader = FileUtil.getReader(qrFile, StandardCharsets.UTF_8);
reader.lines().forEach(System.out::println); //reader.lines().forEach(Console::log);
} }
@Test @Test
@ -198,21 +198,21 @@ public class QrCodeUtilTest {
}catch (final IOException e){ }catch (final IOException e){
e.printStackTrace(); e.printStackTrace();
} }
final BufferedReader reader = FileUtil.getReader(filepath, StandardCharsets.UTF_8); //final BufferedReader reader = FileUtil.getReader(filepath, StandardCharsets.UTF_8);
reader.lines().forEach(System.out::println); //reader.lines().forEach(Console::log);
} }
@Test @Test
@Ignore @Ignore
public void comparePngAndAsciiArtTest() { public void comparePngAndSvgAndAsciiArtTest() {
final QrConfig qrConfig = QrConfig.create() final QrConfig qrConfig = QrConfig.create()
.setForeColor(null) .setForeColor(null)
.setBackColor(null) .setBackColor(null)
.setWidth(0) .setWidth(0)
.setHeight(0).setMargin(1); .setHeight(0).setMargin(1);
QrCodeUtil.generate("https://hutool.cn", qrConfig, FileUtil.touch("d:/test/compare/default.jpg")); QrCodeUtil.generate("https://hutool.cn", qrConfig, FileUtil.touch("d:/test/compare/config_null_color.jpg"));
QrCodeUtil.generate("https://hutool.cn", qrConfig, FileUtil.touch("d:/test/compare/default.txt")); QrCodeUtil.generate("https://hutool.cn", qrConfig, FileUtil.touch("d:/test/compare/config_null_color.txt"));
QrCodeUtil.generate("https://hutool.cn", qrConfig, FileUtil.touch("d:/test/compare/default.png")); QrCodeUtil.generate("https://hutool.cn", qrConfig, FileUtil.touch("d:/test/compare/config_null_color.png"));
} }
} }