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