static RSS::FinderPattern ParseFoundFinderPattern(const BitArray& row, int rowNumber, bool right, BitArray::Range range, FinderCounters& finderCounters) { if (!range || range.begin == row.begin()) return {}; // Actually we found elements 2-5 -> Locate element 1 auto i = std::find(BitArray::ReverseIterator(range.begin), row.rend(), *range.begin); int firstCounter = range.begin - i.base(); range.begin = i.base(); // Make 'counters' hold 1-4 std::copy_backward(finderCounters.begin(), finderCounters.end() - 1, finderCounters.end()); finderCounters[0] = firstCounter; int value = RSS::ReaderHelper::ParseFinderValue(finderCounters, FINDER_PATTERNS); if (value < 0) return {}; int start = range.begin - row.begin(); int end = range.end - row.begin(); if (right) { // row is actually reversed start = row.size() - 1 - start; end = row.size() - 1 - end; } return {value, range.begin - row.begin(), range.end - row.begin(), {ResultPoint(start, rowNumber), ResultPoint(end, rowNumber)}}; }
static BitArray::Range FindFinderPattern(const BitArray& row, bool rightFinderPattern, FinderCounters& counters) { return RowReader::FindPattern( // Will encounter white first when searching for right finder pattern row.getNextSetTo(row.begin(), !rightFinderPattern), row.end(), counters, [](BitArray::Iterator, BitArray::Iterator, const FinderCounters& counters) { return RSS::ReaderHelper::IsFinderPattern(counters); }); }
static RSS::DataCharacter DecodeDataCharacter(const BitArray& row, const RSS::FinderPattern& pattern, bool outsideChar) { std::array<int, 8> counters = {}; if (outsideChar) { if (!RowReader::RecordPatternInReverse(row.begin(), row.iterAt(pattern.startPos()), counters)) return {}; } else { if (!RowReader::RecordPattern(row.iterAt(pattern.endPos() + 1), row.end(), counters)) return {}; std::reverse(counters.begin(), counters.end()); } int numModules = outsideChar ? 16 : 15; float elementWidth = static_cast<float>(std::accumulate(counters.begin(), counters.end(), 0)) / static_cast<float>(numModules); std::array<int, 4> oddCounts; std::array<int, 4> evenCounts; std::array<float, 4> oddRoundingErrors; std::array<float, 4> evenRoundingErrors; for (int i = 0; i < 8; i++) { float value = (float)counters[i] / elementWidth; int count = (int)(value + 0.5f); // Round if (count < 1) { count = 1; } else if (count > 8) { count = 8; } int offset = i / 2; if ((i & 0x01) == 0) { oddCounts[offset] = count; oddRoundingErrors[offset] = value - count; } else { evenCounts[offset] = count; evenRoundingErrors[offset] = value - count; } } if (!AdjustOddEvenCounts(outsideChar, numModules, oddCounts, evenCounts, oddRoundingErrors, evenRoundingErrors)) { return {}; } int oddSum = 0; int oddChecksumPortion = 0; for (auto it = oddCounts.rbegin(); it != oddCounts.rend(); ++it) { oddChecksumPortion *= 9; oddChecksumPortion += *it; oddSum += *it; } int evenChecksumPortion = 0; int evenSum = 0; for (auto it = evenCounts.rbegin(); it != evenCounts.rend(); ++it) { evenChecksumPortion *= 9; evenChecksumPortion += *it; evenSum += *it; } int checksumPortion = oddChecksumPortion + 3 * evenChecksumPortion; if (outsideChar) { if ((oddSum & 0x01) != 0 || oddSum > 12 || oddSum < 4) { return {}; } int group = (12 - oddSum) / 2; int oddWidest = OUTSIDE_ODD_WIDEST[group]; int evenWidest = 9 - oddWidest; int vOdd = RSS::ReaderHelper::GetRSSvalue(oddCounts, oddWidest, false); int vEven = RSS::ReaderHelper::GetRSSvalue(evenCounts, evenWidest, true); int tEven = OUTSIDE_EVEN_TOTAL_SUBSET[group]; int gSum = OUTSIDE_GSUM[group]; return {vOdd * tEven + vEven + gSum, checksumPortion}; } else { if ((evenSum & 0x01) != 0 || evenSum > 10 || evenSum < 4) { return {}; } int group = (10 - evenSum) / 2; int oddWidest = INSIDE_ODD_WIDEST[group]; int evenWidest = 9 - oddWidest; int vOdd = RSS::ReaderHelper::GetRSSvalue(oddCounts, oddWidest, true); int vEven = RSS::ReaderHelper::GetRSSvalue(evenCounts, evenWidest, false); int tOdd = INSIDE_ODD_TOTAL_SUBSET[group]; int gSum = INSIDE_GSUM[group]; return {vEven * tOdd + vOdd + gSum, checksumPortion}; } }