findMulti method

List<FinderPatternInfo> findMulti(
  1. DecodeHint? hints
)

Implementation

List<FinderPatternInfo> findMulti(DecodeHint? hints) {
  final tryHarder = hints?.tryHarder ?? false;
  final maxI = image.height;
  final maxJ = image.width;
  // We are looking for black/white/black/white/black modules in
  // 1:1:3:1:1 ratio; this tracks the number of such modules seen so far

  // Let's assume that the maximum version QR Code we support takes up 1/4 the height of the
  // image, and then account for the center being 3 modules in size. This gives the smallest
  // number of pixels the center could be, so skip this often. When trying harder, look for all
  // QR versions regardless of how dense they are.
  int iSkip = (3 * maxI) ~/ (4 * FinderPatternFinder.maxModules);
  if (iSkip < FinderPatternFinder.minSkip || tryHarder) {
    iSkip = FinderPatternFinder.minSkip;
  }

  final stateCount = [0, 0, 0, 0, 0];
  for (int i = iSkip - 1; i < maxI; i += iSkip) {
    // Get a row of black/white values
    FinderPatternFinder.doClearCounts(stateCount);
    int currentState = 0;
    for (int j = 0; j < maxJ; j++) {
      if (image.get(j, i)) {
        // Black pixel
        if ((currentState & 1) == 1) {
          // Counting white pixels
          currentState++;
        }
        stateCount[currentState]++;
      } else {
        // White pixel
        if ((currentState & 1) == 0) {
          // Counting black pixels
          if (currentState == 4) {
            // A winner?
            if (FinderPatternFinder.foundPatternCross(stateCount) &&
                handlePossibleCenter(stateCount, i, j)) {
              // Yes
              // Clear state to start looking again
              currentState = 0;
              FinderPatternFinder.doClearCounts(stateCount);
            } else {
              // No, shift counts back by two
              FinderPatternFinder.doShiftCounts2(stateCount);
              currentState = 3;
            }
          } else {
            stateCount[++currentState]++;
          }
        } else {
          // Counting white pixels
          stateCount[currentState]++;
        }
      }
    } // for j=...

    if (FinderPatternFinder.foundPatternCross(stateCount)) {
      handlePossibleCenter(stateCount, i, maxJ);
    }
  } // for i=iSkip-1 ...
  final patternInfo = _selectMultipleBestPatterns();
  final result = <FinderPatternInfo>[];
  for (List<FinderPattern> pattern in patternInfo) {
    ResultPoint.orderBestPatterns(pattern);
    result.add(FinderPatternInfo(pattern));
  }

  if (result.isEmpty) {
    return _emptyResultArray;
  } else {
    return result.toList();
  }
}