findMulti method
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();
}
}