decodeRow method
Attempts to decode a one-dimensional barcode format given a single row of an image.
@param rowNumber row number from top of the row @param row the black/white pixel data of the row @param hints decode hints @return Result containing encoded string and start/end of barcode @throws NotFoundException if no potential barcode is found @throws ChecksumException if a potential barcode is found but does not pass its checksum @throws FormatException if a potential barcode is found but format is invalid
Implementation
@override
Result decodeRow(
int rowNumber,
BitArray row,
DecodeHint? hints,
) {
_counters.fillRange(0, _counters.length, 0);
_setCounters(row);
final startOffset = _findStartPattern();
int nextStart = startOffset;
_decodeRowResult.clear();
do {
final charOffset = _toNarrowWidePattern(nextStart);
if (charOffset == -1) {
throw NotFoundException.instance;
}
// Hack: We store the position in the alphabet table into a
// StringBuffer, so that we can access the decoded patterns in
// validatePattern. We'll translate to the actual characters later.
_decodeRowResult.writeCharCode(charOffset);
nextStart += 8;
// Stop as soon as we see the end character.
if (_decodeRowResult.length > 1 &&
_startendEncoding
.contains(String.fromCharCode(alphaBet[charOffset]))) {
break;
}
} while (nextStart <
_counterLength); // no fixed end pattern so keep on reading while data is available
// Look for whitespace after pattern:
final trailingWhitespace = _counters[nextStart - 1];
int lastPatternSize = 0;
for (int i = -8; i < -1; i++) {
lastPatternSize += _counters[nextStart + i];
}
// We need to see whitespace equal to 50% of the last pattern size,
// otherwise this is probably a false positive. The exception is if we are
// at the end of the row. (I.e. the barcode barely fits.)
if (nextStart < _counterLength &&
trailingWhitespace < lastPatternSize / 2) {
throw NotFoundException.instance;
}
_validatePattern(startOffset);
// Translate character table offsets to actual characters.
for (int i = 0; i < _decodeRowResult.length; i++) {
_decodeRowResult.setCharAt(i, alphaBet[_decodeRowResult.codePointAt(i)]);
}
// Ensure a valid start and end character
final startchar = _decodeRowResult.charAt(0);
if (!_startendEncoding.contains(startchar)) {
throw NotFoundException.instance;
}
final endchar = _decodeRowResult.charAt(_decodeRowResult.length - 1);
if (!_startendEncoding.contains(endchar)) {
throw NotFoundException.instance;
}
// remove stop/start characters character and check if a long enough string is contained
if (_decodeRowResult.length <= _minCharacterLength) {
// Almost surely a false positive ( start + stop + at least 1 character)
throw NotFoundException.instance;
}
if (!(hints?.returnCodabarStartEnd ?? false)) {
_decodeRowResult.deleteCharAt(_decodeRowResult.length - 1);
_decodeRowResult.deleteCharAt(0);
}
int runningCount = 0;
for (int i = 0; i < startOffset; i++) {
runningCount += _counters[i];
}
final left = runningCount.toDouble();
for (int i = startOffset; i < nextStart - 1; i++) {
runningCount += _counters[i];
}
final right = runningCount.toDouble();
final result = Result(
_decodeRowResult.toString(),
null,
[
ResultPoint(left, rowNumber.toDouble()),
ResultPoint(right, rowNumber.toDouble()),
],
BarcodeFormat.codabar,
);
result.putMetadata(ResultMetadataType.symbologyIdentifier, ']F0');
return result;
}