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