decodeRow method

  1. @override
Result decodeRow(
  1. int rowNumber,
  2. BitArray row,
  3. DecodeHint? hints
)
override

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;
}