public override Result decodeRow(int rowNumber, BitArray row, IDictionary <DecodeHintType, object> hints) { for (var index = 0; index < counters.Length; index++) { counters[index] = 0; } if (!setCounters(row)) { return(null); } int startOffset = findStartPattern(); if (startOffset < 0) { return(null); } int nextStart = startOffset; decodeRowResult.Length = 0; do { int charOffset = toNarrowWidePattern(nextStart); if (charOffset == -1) { return(null); } // Hack: We store the position in the alphabet table into a // StringBuilder, so that we can access the decoded patterns in // validatePattern. We'll translate to the actual characters later. decodeRowResult.Append((char)charOffset); nextStart += 8; // Stop as soon as we see the end character. if (decodeRowResult.Length > 1 && arrayContains(STARTEND_ENCODING, ALPHABET[charOffset])) { break; } } while (nextStart < counterLength); // no fixed end pattern so keep on reading while data is available // Look for whitespace after pattern: int 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) { return(null); } if (!validatePattern(startOffset)) { return(null); } // Translate character table offsets to actual characters. for (int i = 0; i < decodeRowResult.Length; i++) { decodeRowResult[i] = ALPHABET[decodeRowResult[i]]; } // Ensure a valid start and end character char startchar = decodeRowResult[0]; if (!arrayContains(STARTEND_ENCODING, startchar)) { return(null); } char endchar = decodeRowResult[decodeRowResult.Length - 1]; if (!arrayContains(STARTEND_ENCODING, endchar)) { return(null); } // remove stop/start characters character and check if a long enough string is contained if (decodeRowResult.Length <= MIN_CHARACTER_LENGTH) { // Almost surely a false positive ( start + stop + at least 1 character) return(null); } if (!SupportClass.GetValue(hints, DecodeHintType.RETURN_CODABAR_START_END, false)) { decodeRowResult.Remove(decodeRowResult.Length - 1, 1); decodeRowResult.Remove(0, 1); } int runningCount = 0; for (int i = 0; i < startOffset; i++) { runningCount += counters[i]; } float left = runningCount; for (int i = startOffset; i < nextStart - 1; i++) { runningCount += counters[i]; } float right = runningCount; var resultPointCallback = SupportClass.GetValue(hints, DecodeHintType.NEED_RESULT_POINT_CALLBACK, (ResultPointCallback)null); if (resultPointCallback != null) { resultPointCallback(new ResultPoint(left, rowNumber)); resultPointCallback(new ResultPoint(right, rowNumber)); } return(new Result( decodeRowResult.ToString(), null, new[] { new ResultPoint(left, rowNumber), new ResultPoint(right, rowNumber) }, BarcodeFormat.CODABAR)); }