From ac79e7791247771760b0cc189c3eb956ba58e5a6 Mon Sep 17 00:00:00 2001 From: Looly Date: Tue, 7 Sep 2021 01:00:32 +0800 Subject: [PATCH] fix code --- CHANGELOG.md | 1 + .../qrcode/BufferedImageLuminanceSource.java | 8 +- .../cn/hutool/extra/qrcode/QrCodeUtil.java | 82 ++++++++++++++----- .../hutool/extra/qrcode/QrCodeUtilTest.java | 7 ++ 4 files changed, 73 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f547ccbb..ad50d9095 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ ### 🐞Bug修复 * 【core 】 修复ListUtil.split方法越界问题(issue#I48Q0P@Gitee) +* 【core 】 修复QrCode的isTryHarder、isPureBarcode设置无效问题(issue#1815@Github) ------------------------------------------------------------------------------------------------------------- diff --git a/hutool-extra/src/main/java/cn/hutool/extra/qrcode/BufferedImageLuminanceSource.java b/hutool-extra/src/main/java/cn/hutool/extra/qrcode/BufferedImageLuminanceSource.java index 269eda183..1b78310f9 100644 --- a/hutool-extra/src/main/java/cn/hutool/extra/qrcode/BufferedImageLuminanceSource.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/qrcode/BufferedImageLuminanceSource.java @@ -10,7 +10,7 @@ import java.awt.image.BufferedImage; * {@link BufferedImage} 图片二维码源
* 来自:http://blog.csdn.net/yangxin_blog/article/details/50850701
* 此类同样在zxing-j2se包中也有提供 - * + * * @author zxing, Looly * @since 4.0.2 */ @@ -22,7 +22,7 @@ public final class BufferedImageLuminanceSource extends LuminanceSource { /** * 构造 - * + * * @param image {@link BufferedImage} */ public BufferedImageLuminanceSource(BufferedImage image) { @@ -31,7 +31,7 @@ public final class BufferedImageLuminanceSource extends LuminanceSource { /** * 构造 - * + * * @param image {@link BufferedImage} * @param left 左边间隔 * @param top 顶部间隔 @@ -118,4 +118,4 @@ public final class BufferedImageLuminanceSource extends LuminanceSource { return new BufferedImageLuminanceSource(rotatedImage, top, sourceWidth - (left + width), getHeight(), width); } -} \ No newline at end of file +} 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 4715508e6..f9b800282 100644 --- a/hutool-extra/src/main/java/cn/hutool/extra/qrcode/QrCodeUtil.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/qrcode/QrCodeUtil.java @@ -15,6 +15,7 @@ import com.google.zxing.NotFoundException; import com.google.zxing.Result; import com.google.zxing.WriterException; import com.google.zxing.common.BitMatrix; +import com.google.zxing.common.GlobalHistogramBinarizer; import com.google.zxing.common.HybridBinarizer; import java.awt.Image; @@ -25,6 +26,7 @@ import java.io.File; import java.io.InputStream; import java.io.OutputStream; import java.util.HashMap; +import java.util.Map; /** * 基于Zxing的二维码工具类,支持: @@ -354,7 +356,9 @@ public class QrCodeUtil { } /** - * 将二维码或条形码图片解码为文本 + * 将二维码或条形码图片解码为文本
+ * 此方法会尝试使用{@link HybridBinarizer}和{@link GlobalHistogramBinarizer}两种模式解析
+ * 需要注意部分二维码如果不带logo,使用PureBarcode模式会解析失败,此时须设置此选项为false。 * * @param image {@link Image} 二维码图片 * @param isTryHarder 是否优化精度 @@ -363,32 +367,31 @@ public class QrCodeUtil { * @since 4.3.1 */ public static String decode(Image image, boolean isTryHarder, boolean isPureBarcode) { + return decode(image, buildHints(isTryHarder, isPureBarcode)); + } + + /** + * 将二维码或条形码图片解码为文本
+ * 此方法会尝试使用{@link HybridBinarizer}和{@link GlobalHistogramBinarizer}两种模式解析
+ * 需要注意部分二维码如果不带logo,使用PureBarcode模式会解析失败,此时须设置此选项为false。 + * + * @param image {@link Image} 二维码图片 + * @param hints 自定义扫码配置,包括算法、编码、复杂模式等 + * @return 解码后的文本 + * @since 5.7.12 + */ + public static String decode(Image image, Map hints) { final MultiFormatReader formatReader = new MultiFormatReader(); + formatReader.setHints(hints); final LuminanceSource source = new BufferedImageLuminanceSource(ImgUtil.toBufferedImage(image)); - final Binarizer binarizer = new HybridBinarizer(source); - final BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer); - final HashMap hints = new HashMap<>(); - hints.put(DecodeHintType.CHARACTER_SET, CharsetUtil.UTF_8); - // 优化精度 - hints.put(DecodeHintType.TRY_HARDER, isTryHarder); - // 复杂模式,开启PURE_BARCODE模式 - hints.put(DecodeHintType.PURE_BARCODE, isPureBarcode); - Result result; - try { - result = formatReader.decode(binaryBitmap, hints); - } catch (NotFoundException e) { - // 报错尝试关闭复杂模式 - hints.remove(DecodeHintType.PURE_BARCODE); - try { - result = formatReader.decode(binaryBitmap, hints); - } catch (NotFoundException e1) { - throw new QrCodeException(e1); - } + Result result = _decode(formatReader, new HybridBinarizer(source)); + if (null == result) { + result = _decode(formatReader, new GlobalHistogramBinarizer(source)); } - return result.getText(); + return null != result ? result.getText() : null; } /** @@ -415,4 +418,41 @@ public class QrCodeUtil { } return image; } + + /** + * 创建解码选项 + * + * @param isTryHarder 是否优化精度 + * @param isPureBarcode 是否使用复杂模式,扫描带logo的二维码设为true + * @return 选项Map + */ + private static Map buildHints(boolean isTryHarder, boolean isPureBarcode) { + final HashMap hints = new HashMap<>(); + hints.put(DecodeHintType.CHARACTER_SET, CharsetUtil.UTF_8); + + // 优化精度 + if (isTryHarder) { + hints.put(DecodeHintType.TRY_HARDER, true); + } + // 复杂模式,开启PURE_BARCODE模式 + if (isPureBarcode) { + hints.put(DecodeHintType.PURE_BARCODE, true); + } + return hints; + } + + /** + * 解码多种类型的码,包括二维码和条形码 + * + * @param formatReader {@link MultiFormatReader} + * @param binarizer {@link Binarizer} + * @return {@link Result} + */ + private static Result _decode(MultiFormatReader formatReader, Binarizer binarizer) { + try { + return formatReader.decodeWithState(new BinaryBitmap(binarizer)); + } catch (NotFoundException e) { + return null; + } + } } 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 500492af2..331416ac2 100644 --- a/hutool-extra/src/test/java/cn/hutool/extra/qrcode/QrCodeUtilTest.java +++ b/hutool-extra/src/test/java/cn/hutool/extra/qrcode/QrCodeUtilTest.java @@ -1,6 +1,7 @@ package cn.hutool.extra.qrcode; 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 com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; @@ -80,4 +81,10 @@ public class QrCodeUtilTest { Assert.assertNotNull(base641); } + @Test + @Ignore + public void decodeTest3(){ + final String decode = QrCodeUtil.decode(ImgUtil.read("d:/test/qr_a.png"), true, true); + Console.log(decode); + } }