This commit is contained in:
Looly 2021-09-07 01:00:32 +08:00
parent 36cf627f3d
commit ac79e77912
4 changed files with 73 additions and 25 deletions

View File

@ -17,6 +17,7 @@
### 🐞Bug修复
* 【core 】 修复ListUtil.split方法越界问题issue#I48Q0P@Gitee
* 【core 】 修复QrCode的isTryHarder、isPureBarcode设置无效问题issue#1815@Github
-------------------------------------------------------------------------------------------------------------

View File

@ -10,7 +10,7 @@ import java.awt.image.BufferedImage;
* {@link BufferedImage} 图片二维码源<br>
* 来自http://blog.csdn.net/yangxin_blog/article/details/50850701<br>
* 此类同样在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);
}
}
}

View File

@ -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 {
}
/**
* 将二维码或条形码图片解码为文本
* 将二维码或条形码图片解码为文本<br>
* 此方法会尝试使用{@link HybridBinarizer}{@link GlobalHistogramBinarizer}两种模式解析<br>
* 需要注意部分二维码如果不带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));
}
/**
* 将二维码或条形码图片解码为文本<br>
* 此方法会尝试使用{@link HybridBinarizer}{@link GlobalHistogramBinarizer}两种模式解析<br>
* 需要注意部分二维码如果不带logo使用PureBarcode模式会解析失败此时须设置此选项为false
*
* @param image {@link Image} 二维码图片
* @param hints 自定义扫码配置包括算法编码复杂模式等
* @return 解码后的文本
* @since 5.7.12
*/
public static String decode(Image image, Map<DecodeHintType, Object> 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<DecodeHintType, Object> 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<DecodeHintType, Object> buildHints(boolean isTryHarder, boolean isPureBarcode) {
final HashMap<DecodeHintType, Object> 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;
}
}
}

View File

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