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);
+ }
}