Google Zxing解析二维码时出现com.google.zxing.NotFoundException错误


如题,对某些内容进行解析时造成NotFoundException异常,而在对大多数内容进行解析时不会造成错误。

首先来看一看解析的代码

    BufferedImage image = ImageIO.read(new File(path));
        if (image == null) {
            return null;
        }
        BarcodeLuminanceSource source = new BarcodeLuminanceSource(image);
        BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
        Hashtable<DecodeHintType, Object> hints = new Hashtable<DecodeHintType, Object>();
        hints.put(DecodeHintType.CHARACTER_SET, controler.getEncode());
        Result result = new MultiFormatReader().decode(bitmap, hints);
        String code = result.getText();
        byte[] bytes = IOUtils.toByteArray(new FileInputStream(new File(path)));
        ByteArrayInputStream bais = new ByteArrayInputStream(bytes);

其中BarcodeLuminanceSource是自定义的一个继承自LuminanceSource类,代码从网上借鉴来的。

当执行到new MulitiFormatReader().decode(bitmap,hints)就会报错。

比如在对内容【http://192.168.0.102:9080/rencongums】进行编码解码会报错,而对【http://localhost:9080/rencongums】进行编码解码就不会报错。

 最开始还以为是自定义BarcodeLuminanceSource的问题,于是换成了

<!-- https://mvnrepository.com/artifact/com.google.zxing/javase -->
<dependency>
    <groupId>com.google.zxing</groupId>
    <artifactId>javase</artifactId>
    <version>3.2.1</version>
</dependency>

中的BufferedImageLuminanceSource,但是依然没有解决问题,于是又以为是添加了Logo的原因,去除之后依然会抛出异常。目前还没有查明原因。

根据打断点进去会发现,调用decode的时候会有如下几个Decoder

  readers.add(new MultiFormatOneDReader(hints));
      readers.add(new QRCodeReader());
      readers.add(new DataMatrixReader());
      readers.add(new AztecReader());
      readers.add(new PDF417Reader());
      readers.add(new MaxiCodeReader());

而其中此处需要的是DataMatrixReader(),打进去就是会用到 public Result decode(BinaryBitmap image, Map<DecodeHintType,?> hints)这个方法

如图所示:

public Result decode(BinaryBitmap image, Map<DecodeHintType,?> hints)
      throws NotFoundException, ChecksumException, FormatException {
    DecoderResult decoderResult;
    ResultPoint[] points;
    if (hints != null && hints.containsKey(DecodeHintType.PURE_BARCODE)) {
      BitMatrix bits = extractPureBits(image.getBlackMatrix());
      decoderResult = decoder.decode(bits);
      points = NO_POINTS;
    } else {
      DetectorResult detectorResult = new Detector(image.getBlackMatrix()).detect();
      decoderResult = decoder.decode(detectorResult.getBits());
      points = detectorResult.getPoints();
    }
    Result result = new Result(decoderResult.getText(), decoderResult.getRawBytes(), points,
        BarcodeFormat.DATA_MATRIX);
    List<byte[]> byteSegments = decoderResult.getByteSegments();
    if (byteSegments != null) {
      result.putMetadata(ResultMetadataType.BYTE_SEGMENTS, byteSegments);
    }
    String ecLevel = decoderResult.getECLevel();
    if (ecLevel != null) {
      result.putMetadata(ResultMetadataType.ERROR_CORRECTION_LEVEL, ecLevel);
    }
    return result;
  }

里面就调用了decoder.decode(bits);方法

如下图所示:

public DecoderResult decode(BitMatrix bits) throws FormatException, ChecksumException {

    // Construct a parser and read version, error-correction level
    BitMatrixParser parser = new BitMatrixParser(bits);
    Version version = parser.getVersion();

    // Read codewords
    byte[] codewords = parser.readCodewords();
    // Separate into data blocks
    DataBlock[] dataBlocks = DataBlock.getDataBlocks(codewords, version);

    int dataBlocksCount = dataBlocks.length;

    // Count total number of data bytes
    int totalBytes = 0;
    for (DataBlock db : dataBlocks) {
      totalBytes += db.getNumDataCodewords();
    }
    byte[] resultBytes = new byte[totalBytes];

    // Error-correct and copy data blocks together into a stream of bytes
    for (int j = 0; j < dataBlocksCount; j++) {
      DataBlock dataBlock = dataBlocks[j];
      byte[] codewordBytes = dataBlock.getCodewords();
      int numDataCodewords = dataBlock.getNumDataCodewords();
      correctErrors(codewordBytes, numDataCodewords);
      for (int i = 0; i < numDataCodewords; i++) {
        // De-interlace data blocks.
        resultBytes[i * dataBlocksCount + j] = codewordBytes[i];
      }
    }

    // Decode the contents of that stream of bytes
    return DecodedBitStreamParser.decode(resultBytes);
  }

里面可以看到调用了 correctErrors(codewordBytes, numDataCodewords);方法

private void correctErrors(byte[] codewordBytes, int numDataCodewords) throws ChecksumException {
    int numCodewords = codewordBytes.length;
    // First read into an array of ints
    int[] codewordsInts = new int[numCodewords];
    for (int i = 0; i < numCodewords; i++) {
      codewordsInts[i] = codewordBytes[i] & 0xFF;
    }
    int numECCodewords = codewordBytes.length - numDataCodewords;
    try {
      rsDecoder.decode(codewordsInts, numECCodewords);
    } catch (ReedSolomonException ignored) {
      throw ChecksumException.getChecksumInstance();
    }
    // Copy back into array of bytes -- only need to worry about the bytes that were data
    // We don't care about errors in the error-correction codewords
    for (int i = 0; i < numDataCodewords; i++) {
      codewordBytes[i] = (byte) codewordsInts[i];
    }
  }

显然对于某些特殊的字符串来说完全可能由于checksum不通过而造成抛出异常,因此这是zxing包的问题。

 

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM