From 8fb2f81841de9161c813e6473a0e48f62c2ff2b8 Mon Sep 17 00:00:00 2001 From: axxel Date: Tue, 22 Oct 2024 11:04:30 +0200 Subject: [PATCH 01/11] ITF: support shorter ITF symbols (2, 3 or 4 depending on heuristic) If we are looking only for ITF symbols, the minimum length is now 4 instead of 6. If the symbol covers the whole image, this gets halved, so 2 or 3 respectively. This fixes #853 without introducing any false positive for our sample data-set. --- core/src/oned/ODITFReader.cpp | 13 ++++++++----- test/blackbox/BlackboxTestRunner.cpp | 6 +++--- test/samples/itf-1/#853.png | Bin 0 -> 178 bytes test/samples/itf-1/#853.txt | 1 + 4 files changed, 12 insertions(+), 8 deletions(-) create mode 100644 test/samples/itf-1/#853.png create mode 100644 test/samples/itf-1/#853.txt diff --git a/core/src/oned/ODITFReader.cpp b/core/src/oned/ODITFReader.cpp index 96b9d67e55..8f677ea9a4 100644 --- a/core/src/oned/ODITFReader.cpp +++ b/core/src/oned/ODITFReader.cpp @@ -15,7 +15,7 @@ namespace ZXing::OneD { Barcode ITFReader::decodePattern(int rowNumber, PatternView& next, std::unique_ptr&) const { - const int minCharCount = 6; + const int minCharCount = _opts.formats().count() == 1 ? 4 : 6; // if we are only looking for ITF, we accept shorter symbols const int minQuietZone = 6; // spec requires 10 next = FindLeftGuard(next, 4 + minCharCount/2 + 3, FixedPattern<4, 4>{1, 1, 1, 1}, minQuietZone); @@ -33,6 +33,8 @@ Barcode ITFReader::decodePattern(int rowNumber, PatternView& next, std::unique_p constexpr int weights[] = {1, 2, 4, 7, 0}; int xStart = next.pixelsInFront(); + bool startsAtFirstBar = next.isAtFirstBar(); + next = next.subView(4, 10); std::string txt; @@ -62,17 +64,18 @@ Barcode ITFReader::decodePattern(int rowNumber, PatternView& next, std::unique_p next = next.subView(0, 3); - if (Size(txt) < minCharCount || !next.isValid()) - return {}; - // Check quiet zone size - if (!(next.isAtLastBar() || next[3] > minQuietZone * (threshold.bar + threshold.space) / 3)) + if (!next.isValid() || !(next.isAtLastBar() || next[3] > minQuietZone * (threshold.bar + threshold.space) / 3)) return {}; // Check stop pattern if (next[0] < threshold[0] || next[1] > threshold[1] || next[2] > threshold[2]) return {}; + // Check min length depending on whether the code covers the complete image or not + if (Size(txt) < (startsAtFirstBar && next.isAtLastBar() ? (minCharCount / 2) : minCharCount)) + return {}; + Error error = _opts.validateITFCheckSum() && !GTIN::IsCheckDigitValid(txt) ? ChecksumError() : Error(); // Symbology identifier ISO/IEC 16390:2007 Annex C Table C.1 diff --git a/test/blackbox/BlackboxTestRunner.cpp b/test/blackbox/BlackboxTestRunner.cpp index 93d4ce9905..5e35d9448b 100644 --- a/test/blackbox/BlackboxTestRunner.cpp +++ b/test/blackbox/BlackboxTestRunner.cpp @@ -464,9 +464,9 @@ int runBlackBoxTests(const fs::path& testPathPrefix, const std::set { 3, 5, 180 }, }, ReaderOptions().setEanAddOnSymbol(EanAddOnSymbol::Require)); - runTests("itf-1", "ITF", 11, { - { 10, 11, 0 }, - { 10, 11, 180 }, + runTests("itf-1", "ITF", 12, { + { 11, 12, 0 }, + { 11, 12, 180 }, }); runTests("itf-2", "ITF", 6, { diff --git a/test/samples/itf-1/#853.png b/test/samples/itf-1/#853.png new file mode 100644 index 0000000000000000000000000000000000000000..50342a035a408a76f192c39a00adea278a5cf4d1 GIT binary patch literal 178 zcmeAS@N?(olHy`uVBq!ia0vp^{XlHW#0(@^V*-SM6k~CayA#8@b22Z19L@rd$YKTt zZlDCWFeAgPIT9ej0G|-o|Ns93nLmE~Sk*df9gyYZ>Eak-ar*74jl2v79L$cv7nY>Y z@0q})e{zbT_5zR0KfgXTq_17&e!@?Jvqd(-s#>A;u=&m96F}gCy2+|toVzYts&4U) STHypVjlt8^&t;ucLK6UETsb-b literal 0 HcmV?d00001 diff --git a/test/samples/itf-1/#853.txt b/test/samples/itf-1/#853.txt new file mode 100644 index 0000000000..fc0a24477e --- /dev/null +++ b/test/samples/itf-1/#853.txt @@ -0,0 +1 @@ +1515 \ No newline at end of file From 2d08a8d9bcf6751f4361584dc54adc7177e23bc8 Mon Sep 17 00:00:00 2001 From: Wiktor Perskawiec Date: Tue, 22 Oct 2024 18:07:16 +0200 Subject: [PATCH 02/11] README: fix typos --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1704b4d91b..2fb0031c8f 100644 --- a/README.md +++ b/README.md @@ -47,8 +47,8 @@ Thanks a lot for your contribution! [Note:] * DataBar used to be called RSS. - * DataBar, DX Film Edge, MaxiCode, Micro QR Code and rMQR Code are not supported for writing. - * Building with only C++17 (see [CMakeLists.txt](https://github.com/zxing-cpp/zxing-cpp/blob/d4b0f502775857f257d13efd25fb840ece1bca3e/CMakeLists.txt#L45)) changes the behaviour of the library: it then lacks support for DataBarLimited and multi-symbol and position independent detection for DataMatrix. + * DataBar, DX Film Edge, MaxiCode, Micro QR Code, and rMQR Code are not supported for writing. + * Building with only C++17 (see [CMakeLists.txt](https://github.com/zxing-cpp/zxing-cpp/blob/d4b0f502775857f257d13efd25fb840ece1bca3e/CMakeLists.txt#L45)) changes the behavior of the library: it then lacks support for DataBarLimited and multi-symbol and position independent detection for DataMatrix. ## Getting Started @@ -79,7 +79,7 @@ int main(int argc, char** argv) ``` To see the full capability of the API, have a look at [`ZXingReader.cpp`](example/ZXingReader.cpp). -[Note: At least C++17 is reqired on the client side to use the API.] +[Note: At least C++17 is required on the client side to use the API.] ### To write barcodes: 1. Create a [`MultiFormatWriter`](core/src/MultiFormatWriter.h) instance with the format you want to generate. Set encoding and margins if needed. From 5fb7e6d0985e6416162f8aa2bc1c068794671682 Mon Sep 17 00:00:00 2001 From: axxel Date: Tue, 22 Oct 2024 21:56:04 +0200 Subject: [PATCH 03/11] cmake: update minimum version to 3.16 (fix #857) --- CMakeLists.txt | 2 +- README.md | 4 ++-- core/CMakeLists.txt | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fee4c68cdc..b48b2d09e2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.15) +cmake_minimum_required(VERSION 3.16) project(ZXing) diff --git a/README.md b/README.md index 2fb0031c8f..90eb314f39 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ Thanks a lot for your contribution! [Note:] * DataBar used to be called RSS. - * DataBar, DX Film Edge, MaxiCode, Micro QR Code, and rMQR Code are not supported for writing. + * DataBar, DX Film Edge, MaxiCode, Micro QR Code and rMQR Code are not supported for writing. * Building with only C++17 (see [CMakeLists.txt](https://github.com/zxing-cpp/zxing-cpp/blob/d4b0f502775857f257d13efd25fb840ece1bca3e/CMakeLists.txt#L45)) changes the behavior of the library: it then lacks support for DataBarLimited and multi-symbol and position independent detection for DataMatrix. ## Getting Started @@ -98,7 +98,7 @@ As an example, have a look at [`ZXingWriter.cpp`](example/ZXingWriter.cpp). ## Build Instructions These are the generic instructions to build the library on Windows/macOS/Linux. For details on how to build the individual wrappers, follow the links above. -1. Make sure [CMake](https://cmake.org) version 3.15 or newer is installed. +1. Make sure [CMake](https://cmake.org) version 3.16 or newer is installed. The python module requires 3.18 or higher. 2. Make sure a sufficiently C++20 compliant compiler is installed (minimum VS 2019 16.10? / gcc 11 / clang 12?). 3. See the cmake `ZXING_...` options to enable the testing code, python wrapper, etc. diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index d7ea297a96..487e9357e3 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.15) +cmake_minimum_required(VERSION 3.16) project (ZXing VERSION "2.2.1") set (ZXING_SONAME 3) # see https://github.com/zxing-cpp/zxing-cpp/issues/333 From 939abf85bb2b77da8bb4ade36c6e49c6ef00e1e6 Mon Sep 17 00:00:00 2001 From: axxel Date: Tue, 29 Oct 2024 14:30:09 +0100 Subject: [PATCH 04/11] test: remove 3 DataBar samples that don't actually contain valid symbols Working on the edge-2-edge style decoding for DataBar, it became apparent that one symbol (captured 3 times) was actually invalid. No online decoder was able to scan it and the number content inside the image was obviously wrong, shown by comparison with a generated code with those numbers. --- test/blackbox/BlackboxTestRunner.cpp | 2 +- test/samples/rss14-2/16.png | Bin 31681 -> 0 bytes test/samples/rss14-2/16.txt | 1 - test/samples/rss14-2/17.png | Bin 29917 -> 0 bytes test/samples/rss14-2/17.txt | 1 - test/samples/rss14-2/18.png | Bin 30249 -> 0 bytes test/samples/rss14-2/18.txt | 1 - 7 files changed, 1 insertion(+), 4 deletions(-) delete mode 100644 test/samples/rss14-2/16.png delete mode 100644 test/samples/rss14-2/16.txt delete mode 100644 test/samples/rss14-2/17.png delete mode 100644 test/samples/rss14-2/17.txt delete mode 100644 test/samples/rss14-2/18.png delete mode 100644 test/samples/rss14-2/18.txt diff --git a/test/blackbox/BlackboxTestRunner.cpp b/test/blackbox/BlackboxTestRunner.cpp index 5e35d9448b..91161deeed 100644 --- a/test/blackbox/BlackboxTestRunner.cpp +++ b/test/blackbox/BlackboxTestRunner.cpp @@ -533,7 +533,7 @@ int runBlackBoxTests(const fs::path& testPathPrefix, const std::set { 6, 6, 180 }, }); - runTests("rss14-2", "DataBar", 16, { + runTests("rss14-2", "DataBar", 13, { { 8, 10, 0 }, { 9, 10, 180 }, }); diff --git a/test/samples/rss14-2/16.png b/test/samples/rss14-2/16.png deleted file mode 100644 index e919782c68601622830aff50973d19067462021a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 31681 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 diff --git a/test/samples/rss14-2/16.txt b/test/samples/rss14-2/16.txt deleted file mode 100644 index adb4ff3445..0000000000 --- a/test/samples/rss14-2/16.txt +++ /dev/null @@ -1 +0,0 @@ -02001234567893 \ No newline at end of file diff --git a/test/samples/rss14-2/17.png b/test/samples/rss14-2/17.png deleted file mode 100644 index 253139db3ea5e828d5a9b677f0ed7d5db16287f1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29917 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 Yzx=C8Og}NYx&QzG07*qoM6N<$g7p{|NB{r; diff --git a/test/samples/rss14-2/17.txt b/test/samples/rss14-2/17.txt deleted file mode 100644 index adb4ff3445..0000000000 --- a/test/samples/rss14-2/17.txt +++ /dev/null @@ -1 +0,0 @@ -02001234567893 \ No newline at end of file diff --git a/test/samples/rss14-2/18.png b/test/samples/rss14-2/18.png deleted file mode 100644 index c7d76c941652fbff6c73f096396263bdc897d1b2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30249 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 diff --git a/test/samples/rss14-2/18.txt b/test/samples/rss14-2/18.txt deleted file mode 100644 index adb4ff3445..0000000000 --- a/test/samples/rss14-2/18.txt +++ /dev/null @@ -1 +0,0 @@ -02001234567893 \ No newline at end of file From 308f82077dd82979c9df1f82a8ff264dcf0d6371 Mon Sep 17 00:00:00 2001 From: axxel Date: Tue, 29 Oct 2024 15:27:25 +0100 Subject: [PATCH 05/11] DataBar: improve detection rate by incorporating edge-2-edge pattern idea This brings the algorithm closer to the reference algorithm and to what the new DataBarLimited reader is doing. One less MAX_INDIVIDUAL_VARIANCE magic number, yay. --- core/src/Pattern.h | 9 +-- core/src/oned/ODCode128Reader.cpp | 4 +- core/src/oned/ODDataBarCommon.cpp | 9 +++ core/src/oned/ODDataBarCommon.h | 65 +++++++++++++++++++--- core/src/oned/ODDataBarExpandedReader.cpp | 19 +++---- core/src/oned/ODDataBarLimitedReader.cpp | 39 +------------ core/src/oned/ODDataBarReader.cpp | 28 ++++------ test/blackbox/BlackboxTestRunner.cpp | 6 +- test/samples/rss14-2/0120358468019312.jpg | Bin 0 -> 768 bytes test/samples/rss14-2/0120358468019312.txt | 1 + 10 files changed, 100 insertions(+), 80 deletions(-) create mode 100644 test/samples/rss14-2/0120358468019312.jpg create mode 100644 test/samples/rss14-2/0120358468019312.txt diff --git a/core/src/Pattern.h b/core/src/Pattern.h index 06bc4e7b9e..891060b45e 100644 --- a/core/src/Pattern.h +++ b/core/src/Pattern.h @@ -278,14 +278,15 @@ PatternView FindLeftGuard(const PatternView& view, int minSize, const FixedPatte }); } -template -std::array NormalizedE2EPattern(const PatternView& view) +template +std::array NormalizedE2EPattern(const PatternView& view, int mods, bool reverse = false) { - double moduleSize = static_cast(view.sum(LEN)) / SUM; + double moduleSize = static_cast(view.sum(LEN)) / mods; std::array e2e; for (int i = 0; i < LEN - 2; i++) { - double v = (view[i] + view[i + 1]) / moduleSize; + int i_v = reverse ? LEN - 2 - i : i; + double v = (view[i_v] + view[i_v + 1]) / moduleSize; e2e[i] = int(v + .5); } diff --git a/core/src/oned/ODCode128Reader.cpp b/core/src/oned/ODCode128Reader.cpp index 55f52e0b38..bacb033694 100644 --- a/core/src/oned/ODCode128Reader.cpp +++ b/core/src/oned/ODCode128Reader.cpp @@ -158,7 +158,7 @@ class Raw2TxtDecoder constexpr auto START_PATTERN_PREFIX = FixedPattern<3, 4>{2, 1, 1}; constexpr int CHAR_LEN = 6; constexpr float QUIET_ZONE = 5; // quiet zone spec is 10 modules, real world examples ignore that, see #138 -constexpr int CHAR_SUM = 11; +constexpr int CHAR_MODS = 11; //TODO: make this a constexpr variable initialization static auto E2E_PATTERNS = [] { @@ -180,7 +180,7 @@ Barcode Code128Reader::decodePattern(int rowNumber, PatternView& next, std::uniq int minCharCount = 4; // start + payload + checksum + stop auto decodePattern = [](const PatternView& view, bool start = false) { // This is basically the reference algorithm from the specification - int code = IndexOf(E2E_PATTERNS, ToInt(NormalizedE2EPattern(view))); + int code = IndexOf(E2E_PATTERNS, ToInt(NormalizedE2EPattern(view, CHAR_MODS))); if (code == -1 && !start) // if the reference algo fails, give the original upstream version a try (required to decode a few samples) code = DecodeDigit(view, Code128::CODE_PATTERNS, MAX_AVG_VARIANCE, MAX_INDIVIDUAL_VARIANCE); return code; diff --git a/core/src/oned/ODDataBarCommon.cpp b/core/src/oned/ODDataBarCommon.cpp index 4ca091a139..5c63800c47 100644 --- a/core/src/oned/ODDataBarCommon.cpp +++ b/core/src/oned/ODDataBarCommon.cpp @@ -74,6 +74,14 @@ using Array4F = std::array; bool ReadDataCharacterRaw(const PatternView& view, int numModules, bool reversed, Array4I& oddPattern, Array4I& evnPattern) { +#if 1 + auto pattern = NormalizedPatternFromE2E<8>(view, numModules, reversed); + OddEven res = {oddPattern, evnPattern}; + + for (int i = 0; i < Size(pattern); ++i) + res[i % 2][i / 2] = pattern[i]; + +#else OddEven res = {oddPattern, evnPattern}; OddEven rem; @@ -86,6 +94,7 @@ bool ReadDataCharacterRaw(const PatternView& view, int numModules, bool reversed res[i % 2][i / 2] = int(v + .5f); rem[i % 2][i / 2] = v - res[i % 2][i / 2]; } +#endif // DataBarExpanded data character is 17 modules wide // DataBar outer data character is 16 modules wide diff --git a/core/src/oned/ODDataBarCommon.h b/core/src/oned/ODDataBarCommon.h index 5e6bd893dd..cb937ebb17 100644 --- a/core/src/oned/ODDataBarCommon.h +++ b/core/src/oned/ODDataBarCommon.h @@ -114,14 +114,22 @@ struct PairHash constexpr int FULL_PAIR_SIZE = 8 + 5 + 8; constexpr int HALF_PAIR_SIZE = 8 + 5 + 2; // half has to be followed by a guard pattern -template -int ParseFinderPattern(const PatternView& view, bool reversed, T l2rPattern, T r2lPattern) +template +int ParseFinderPattern(const PatternView& view, bool reversed, const std::array, N>& e2ePatterns) { - constexpr float MAX_AVG_VARIANCE = 0.2f; - constexpr float MAX_INDIVIDUAL_VARIANCE = 0.45f; - - int i = 1 + RowReader::DecodeDigit(view, reversed ? r2lPattern : l2rPattern, MAX_AVG_VARIANCE, - MAX_INDIVIDUAL_VARIANCE, true); + const auto e2e = NormalizedE2EPattern<5>(view, 15, reversed); + + int best_i, best_e = 3; + for (int i = 0; i < Size(e2ePatterns); ++i) { + int e = 0; + for (int j = 0; j < 3; ++j) + e += std::abs(e2ePatterns[i][j] - e2e[j]); + if (e < best_e) { + best_e = e; + best_i = i; + } + } + int i = best_e <= 1 ? 1 + best_i : 0; return reversed ? -i : i; } @@ -134,6 +142,49 @@ struct OddEven using Array4I = std::array; +// elements() determines the element widths of an (n,k) character with +// at least one even-numbered element that's just one module wide. +// (Note: even-numbered elements - 2nd, 4th, 6th, etc., have odd indexes) +// for DataBarLimited: LEN=14, mods=26/18 +template +std::array NormalizedPatternFromE2E(const PatternView& view, int mods, bool reversed = false) +{ + bool isExp = mods == 17; // elementsExp() with at least one odd-numbered element that's just one module wide + const auto e2e = NormalizedE2EPattern(view, mods, reversed); + std::array widths; + + // derive element widths from normalized edge-to-similar-edge measurements + int barSum = widths[0] = isExp ? 8 : 1; // first assume 1st bar is 1 / 8 + for (int i = 0; i < Size(e2e); i++) { + widths[i + 1] = e2e[i] - widths[i]; + barSum += widths[i + 1]; + } + widths.back() = mods - barSum; // last even element makes mods modules + + // int minEven = widths[1]; + // for (int i = 3; i < Size(widths); i += 2) + // minEven = std::min(minEven, widths[i]); + OddEven min = {widths[0], widths[1]}; + for (int i = 2; i < Size(widths); i++) + min[i] = std::min(min[i], widths[i]); + + if (isExp && min[0] > 1) { + // minimum odd width is too big, readjust so minimum odd is 1 + for (int i = 0; i < Size(widths); i += 2) { + widths[i] -= min[0] - 1; + widths[i + 1] += min[0] - 1; + } + } else if (!isExp && min[1] > 1) { + // minimum even width is too big, readjust so minimum even is 1 + for (int i = 0; i < Size(widths); i += 2) { + widths[i] += min[1] - 1; + widths[i + 1] -= min[1] - 1; + } + } + + return widths; +} + bool ReadDataCharacterRaw(const PatternView& view, int numModules, bool reversed, Array4I& oddPattern, Array4I& evnPattern); diff --git a/core/src/oned/ODDataBarExpandedReader.cpp b/core/src/oned/ODDataBarExpandedReader.cpp index 15c2a54954..19c63ba59d 100644 --- a/core/src/oned/ODDataBarExpandedReader.cpp +++ b/core/src/oned/ODDataBarExpandedReader.cpp @@ -137,19 +137,16 @@ static const std::array VALID_HALF_PAIRS = {{-FINDER_A, FINDER_B, -FINDE static int ParseFinderPattern(const PatternView& view, Direction dir) { - static constexpr std::array, 6> FINDER_PATTERNS = {{ - {1, 8, 4, 1, 1}, // A - {3, 6, 4, 1, 1}, // B - {3, 4, 6, 1, 1}, // C - {3, 2, 8, 1, 1}, // D - {2, 6, 5, 1, 1}, // E - {2, 2, 9, 1, 1}, // F + static constexpr std::array, 6> e2ePatterns = {{ + {9, 12, 5 }, // {1, 8, 4, 1, 1}, // A + {9, 10, 5 }, // {3, 6, 4, 1, 1}, // B + {7, 10, 7 }, // {3, 4, 6, 1, 1}, // C + {5, 10, 9 }, // {3, 2, 8, 1, 1}, // D + {8, 11, 6 }, // {2, 6, 5, 1, 1}, // E + {4, 11, 10}, // {2, 2, 9, 1, 1}, // F }}; - // TODO: c++20 constexpr inversion from FIND_PATTERN? - static constexpr std::array, 6> REVERSED_FINDER_PATTERNS = { - {{1, 1, 4, 8, 1}, {1, 1, 4, 6, 3}, {1, 1, 6, 4, 3}, {1, 1, 8, 2, 3}, {1, 1, 5, 6, 2}, {1, 1, 9, 2, 2}}}; - return ParseFinderPattern(view, dir == Direction::Left, FINDER_PATTERNS, REVERSED_FINDER_PATTERNS); + return ParseFinderPattern<6>(view, dir == Direction::Left, e2ePatterns); } static bool ChecksumIsValid(const Pairs& pairs) diff --git a/core/src/oned/ODDataBarLimitedReader.cpp b/core/src/oned/ODDataBarLimitedReader.cpp index 65e8f22231..db57feb024 100644 --- a/core/src/oned/ODDataBarLimitedReader.cpp +++ b/core/src/oned/ODDataBarLimitedReader.cpp @@ -27,39 +27,6 @@ using namespace DataBar; constexpr int CHAR_LEN = 14; constexpr int SYMBOL_LEN = 1 + 3 * CHAR_LEN + 2; -// elements() determines the element widths of an (n,k) character with -// at least one even-numbered element that's just one module wide. -// (Note: even-numbered elements - 2nd, 4th, 6th, etc., have odd indexes) -// for DataBarLimited: SUM=26/18, LEN=14 -template -std::array NormalizedPatternFromE2E(const PatternView& view) -{ - auto e2e = NormalizedE2EPattern(view); - std::array widths; - - // derive element widths from normalized edge-to-similar-edge measurements - int barSum = widths[0] = 1; // first assume 1st bar is 1 - for (int i = 0; i < Size(e2e); i++) { - widths[i + 1] = e2e[i] - widths[i]; - barSum += widths[i + 1]; - } - widths.back() = SUM - barSum; // last even element makes SUM modules - - int minEven = widths[1]; - for (int i = 3; i < Size(widths); i += 2) - minEven = std::min(minEven, widths[i]); - - if (minEven > 1) { - // minimum even width is too big, readjust so minimum even is 1 - for (int i = 0; i < Size(widths); i += 2) { - widths[i] += minEven - 1; - widths[i + 1] -= minEven - 1; - } - } - - return widths; -} - static Character ReadDataCharacter(const PatternView& view) { constexpr int G_SUM[] = {0, 183064, 820064, 1000776, 1491021, 1979845, 1996939}; @@ -67,7 +34,7 @@ static Character ReadDataCharacter(const PatternView& view) constexpr int ODD_SUM[] = {17, 13, 9, 15, 11, 19, 7}; constexpr int ODD_WIDEST[] = {6, 5, 3, 5, 4, 8, 1}; - auto pattern = NormalizedPatternFromE2E<14, 26>(view); + auto pattern = NormalizedPatternFromE2E<14>(view, 26); int checkSum = 0; for (auto it = pattern.rbegin(); it != pattern.rend(); ++it) @@ -170,13 +137,13 @@ Barcode DataBarLimitedReader::decodePattern(int rowNumber, PatternView& next, st if ((!next.isAtFirstBar() && next[-1] < modSize) || (!next.isAtLastBar() && next[SYMBOL_LEN] < 5 * modSize)) continue; - auto checkCharPattern = ToInt(NormalizedPatternFromE2E(checkView)); + auto checkCharPattern = ToInt(NormalizedPatternFromE2E(checkView, 18)); int checkSum = IndexOf(CheckChars, checkCharPattern); if (checkSum == -1) continue; printf("%f - ", modSize); - printv("%d ", NormalizedPatternFromE2E(checkView)); + printv("%d ", NormalizedPatternFromE2E(checkView, 18)); auto left = ReadDataCharacter(leftView); auto right = ReadDataCharacter(rightView); diff --git a/core/src/oned/ODDataBarReader.cpp b/core/src/oned/ODDataBarReader.cpp index 27c64090db..f42b92a682 100644 --- a/core/src/oned/ODDataBarReader.cpp +++ b/core/src/oned/ODDataBarReader.cpp @@ -86,25 +86,19 @@ static Character ReadDataCharacter(const PatternView& view, bool outsideChar, bo int ParseFinderPattern(const PatternView& view, bool reversed) { - static constexpr std::array, 10> FINDER_PATTERNS = {{ - {3, 8, 2, 1, 1}, - {3, 5, 5, 1, 1}, - {3, 3, 7, 1, 1}, - {3, 1, 9, 1, 1}, - {2, 7, 4, 1, 1}, - {2, 5, 6, 1, 1}, - {2, 3, 8, 1, 1}, - {1, 5, 7, 1, 1}, - {1, 3, 9, 1, 1}, + static constexpr std::array, 9> e2ePatterns = {{ + {11, 10, 3 }, // {3, 8, 2, 1, 1} + {8 , 10, 6 }, // {3, 5, 5, 1, 1} + {6 , 10, 8 }, // {3, 3, 7, 1, 1} + {4 , 10, 10}, // {3, 1, 9, 1, 1} + {9 , 11, 5 }, // {2, 7, 4, 1, 1} + {7 , 11, 7 }, // {2, 5, 6, 1, 1} + {5 , 11, 9 }, // {2, 3, 8, 1, 1} + {6 , 11, 8 }, // {1, 5, 7, 1, 1} + {4 , 12, 10}, // {1, 3, 9, 1, 1} }}; - // TODO: c++20 constexpr inversion from FIND_PATTERN? - static constexpr std::array, 10> REVERSED_FINDER_PATTERNS = {{ - {1, 1, 2, 8, 3}, {1, 1, 5, 5, 3}, {1, 1, 7, 3, 3}, {1, 1, 9, 1, 3}, {1, 1, 4, 7, 2}, - {1, 1, 6, 5, 2}, {1, 1, 8, 3, 2}, {1, 1, 7, 5, 1}, {1, 1, 9, 3, 1}, - }}; - - return ParseFinderPattern(view, reversed, FINDER_PATTERNS, REVERSED_FINDER_PATTERNS); + return ParseFinderPattern<9>(view, reversed, e2ePatterns); } static Pair ReadPair(const PatternView& view, bool rightPair) diff --git a/test/blackbox/BlackboxTestRunner.cpp b/test/blackbox/BlackboxTestRunner.cpp index 91161deeed..c778e2c051 100644 --- a/test/blackbox/BlackboxTestRunner.cpp +++ b/test/blackbox/BlackboxTestRunner.cpp @@ -533,9 +533,9 @@ int runBlackBoxTests(const fs::path& testPathPrefix, const std::set { 6, 6, 180 }, }); - runTests("rss14-2", "DataBar", 13, { - { 8, 10, 0 }, - { 9, 10, 180 }, + runTests("rss14-2", "DataBar", 14, { + { 10, 11, 0 }, + { 10, 11, 180 }, }); runTests("rssexpanded-1", "DataBarExpanded", 34, { diff --git a/test/samples/rss14-2/0120358468019312.jpg b/test/samples/rss14-2/0120358468019312.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2bf3c5606d23d276fc9240e360ca73fb0e3069c6 GIT binary patch literal 768 zcmex=Vj7khl zf{e_9jQ@`?$S^Q4F)=YSAOIUXD+f@3k>&p_plYD=85l|)HAZYrbBn$3@bQYrubnoF zmQ@866fk4wYxS;Y?|4wsZx7(-3FQ~#s~xmLxC(t1}3nHOaeeo z(KgXD21|YMDr5#J+?sOXaZ0DBKTxF!kk7&dbRH+%Tt+4qHg;xKLB-@^Ate*Dz@m-D zrin>~BBCm)hUSh<2cceIv}a(?>%4j3;QQZwQHJ7kH>#%2P!+#4`)nFyK3WKUPg+;WJa^%- zq$9dD0(%+*^R8CRN$ooR_Orbc>kl^7S8v;Hv&ycBEcE;$`fiD*_q>UM*$0nLbG-P{ z``SLH_&1^t6T7NcuJmp?zoNP4DvQnr5!slR2P>~$anQclIjdq)i$+? Date: Tue, 5 Nov 2024 10:48:19 +0100 Subject: [PATCH 06/11] ITF: fix detection regression introduced in e3672fdf329718f87ffd5431eb232937911d507f Add test image that checks for support of slanted (non-perpendicular) scanned symbols. --- core/src/oned/ODITFReader.cpp | 16 ++++++++++------ test/blackbox/BlackboxTestRunner.cpp | 6 +++--- test/samples/itf-1/1-slanted.png | Bin 0 -> 368 bytes test/samples/itf-1/1-slanted.txt | 1 + test/samples/itf-1/with-tail.png | Bin 0 -> 194 bytes test/samples/itf-1/with-tail.txt | 1 + 6 files changed, 15 insertions(+), 9 deletions(-) create mode 100644 test/samples/itf-1/1-slanted.png create mode 100644 test/samples/itf-1/1-slanted.txt create mode 100644 test/samples/itf-1/with-tail.png create mode 100644 test/samples/itf-1/with-tail.txt diff --git a/core/src/oned/ODITFReader.cpp b/core/src/oned/ODITFReader.cpp index 8f677ea9a4..8e16477dad 100644 --- a/core/src/oned/ODITFReader.cpp +++ b/core/src/oned/ODITFReader.cpp @@ -41,31 +41,35 @@ Barcode ITFReader::decodePattern(int rowNumber, PatternView& next, std::unique_p txt.reserve(20); while (next.isValid()) { - threshold = NarrowWideThreshold(next); - if (!threshold.isValid()) + // look for end-of-symbol + if (next[3] > threshold.space * 3) break; BarAndSpace digits, numWide; + bool bad = false; for (int i = 0; i < 10; ++i) { - if (next[i] > threshold[i] * 2) - break; + bad |= next[i] > threshold[i] * 3 || next[i] < threshold[i] / 3; numWide[i] += next[i] > threshold[i]; digits[i] += weights[i/2] * (next[i] > threshold[i]); } - if (numWide.bar != 2 || numWide.space != 2) + if (bad || numWide.bar != 2 || numWide.space != 2) break; for (int i = 0; i < 2; ++i) txt.push_back(ToDigit(digits[i] == 11 ? 0 : digits[i])); + // update threshold to support scanning slanted symbols (scanned non-perpendicular) + threshold = NarrowWideThreshold(next); + next.skipSymbol(); } next = next.subView(0, 3); // Check quiet zone size - if (!next.isValid() || !(next.isAtLastBar() || next[3] > minQuietZone * (threshold.bar + threshold.space) / 3)) + if (!next.isValid() || !threshold.isValid() + || !(next.isAtLastBar() || next[3] > minQuietZone * (threshold.bar + threshold.space) / 3)) return {}; // Check stop pattern diff --git a/test/blackbox/BlackboxTestRunner.cpp b/test/blackbox/BlackboxTestRunner.cpp index c778e2c051..94bd072750 100644 --- a/test/blackbox/BlackboxTestRunner.cpp +++ b/test/blackbox/BlackboxTestRunner.cpp @@ -464,9 +464,9 @@ int runBlackBoxTests(const fs::path& testPathPrefix, const std::set { 3, 5, 180 }, }, ReaderOptions().setEanAddOnSymbol(EanAddOnSymbol::Require)); - runTests("itf-1", "ITF", 12, { - { 11, 12, 0 }, - { 11, 12, 180 }, + runTests("itf-1", "ITF", 14, { + { 13, 14, 0 }, + { 13, 14, 180 }, }); runTests("itf-2", "ITF", 6, { diff --git a/test/samples/itf-1/1-slanted.png b/test/samples/itf-1/1-slanted.png new file mode 100644 index 0000000000000000000000000000000000000000..f8018870d4d58329f38c5529d894c6b8a71a9f31 GIT binary patch literal 368 zcmV-$0gwKPP)000dL00000>S%bm0003uNklI!UXadA2jI7CQ9g9J`44ri5;f)XSX z%cPU~`_mvaHZ{KA<=LL$1NqJPsTm<3kIde#iin!eW|LMP$T;W71GQvn)5|=Fh{$D7 z>U`Pfbsk53Hd7H1OYaIeNmk6NYG#89_7k&y8MQ}cQB~3VL)1q0evVRNX}mc{A<u!s(`s;tunymN$lDypgJ*gB^EG zY-`HvIkH$*ookHCx`ETpI)whIKp7|lWuOcN%0L+?17#>s2FgGg`m-PPF2r_13XI19 O0000ukxG zLx!6gAD6WA32bUHwr~?W!4}7Q+vM-!=S~a1#MZoW{!#G3_gG`^!jPWOge@XsuBG2s zpKY8PWj%{w_U`aEX7d-WjBZ?-5O{0(BA0Xq?}IC2U$AfYojvK3)C#G^zl-NWzJ*6WDQ{T>a-65DpUXO@geCyz>r$Km literal 0 HcmV?d00001 diff --git a/test/samples/itf-1/with-tail.txt b/test/samples/itf-1/with-tail.txt new file mode 100644 index 0000000000..5bcda57faf --- /dev/null +++ b/test/samples/itf-1/with-tail.txt @@ -0,0 +1 @@ +00123456 \ No newline at end of file From dda630976e62e6d51b2f31978b387155c1f3aed5 Mon Sep 17 00:00:00 2001 From: axxel Date: Tue, 5 Nov 2024 11:12:39 +0100 Subject: [PATCH 07/11] dotnet: replace List with Barcode[] as return type of Read This allows eliminating any managed heap allocation in the no-barcode-found case. This is basically the low hanging fruit part of #838. --- wrappers/dotnet/ZXingCpp.DemoReader/Program.cs | 10 +++++----- wrappers/dotnet/ZXingCpp/ZXingCpp.cs | 15 ++++++++++----- wrappers/dotnet/ZXingCpp/ZXingCpp.csproj | 4 ++-- 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/wrappers/dotnet/ZXingCpp.DemoReader/Program.cs b/wrappers/dotnet/ZXingCpp.DemoReader/Program.cs index 6b111444d1..7e9b672c5a 100644 --- a/wrappers/dotnet/ZXingCpp.DemoReader/Program.cs +++ b/wrappers/dotnet/ZXingCpp.DemoReader/Program.cs @@ -10,7 +10,7 @@ public static class MagickImageBarcodeReader { - public static List Read(MagickImage img, ReaderOptions? opts = null) + public static Barcode[] Read(MagickImage img, ReaderOptions? opts = null) { if (img.DetermineBitDepth() < 8) img.SetBitDepth(8); @@ -19,12 +19,12 @@ public static List Read(MagickImage img, ReaderOptions? opts = null) return BarcodeReader.Read(iv, opts); } - public static List From(this BarcodeReader reader, MagickImage img) => Read(img, reader); + public static Barcode[] From(this BarcodeReader reader, MagickImage img) => Read(img, reader); } public static class SkBitmapBarcodeReader { - public static List Read(SKBitmap img, ReaderOptions? opts = null) + public static Barcode[] Read(SKBitmap img, ReaderOptions? opts = null) { var format = img.Info.ColorType switch { @@ -44,7 +44,7 @@ public static List Read(SKBitmap img, ReaderOptions? opts = null) return BarcodeReader.Read(iv, opts); } - public static List From(this BarcodeReader reader, SKBitmap img) => Read(img, reader); + public static Barcode[] From(this BarcodeReader reader, SKBitmap img) => Read(img, reader); } public class Program @@ -65,7 +65,7 @@ public static void Main(string[] args) if (args.Length >= 2) readBarcodes.Formats = Barcode.FormatsFromString(args[1]); - + foreach (var b in readBarcodes.From(img)) Console.WriteLine($"{b.Format} ({b.ContentType}): {b.Text} / [{string.Join(", ", b.Bytes)}] {b.ErrorMsg}"); } diff --git a/wrappers/dotnet/ZXingCpp/ZXingCpp.cs b/wrappers/dotnet/ZXingCpp/ZXingCpp.cs index c422a8268b..90eae5fed2 100644 --- a/wrappers/dotnet/ZXingCpp/ZXingCpp.cs +++ b/wrappers/dotnet/ZXingCpp/ZXingCpp.cs @@ -479,20 +479,25 @@ public static BarcodeFormats FormatsFromString(string str) public class BarcodeReader : ReaderOptions { - public static List Read(ImageView iv, ReaderOptions? opts = null) + public static Barcode[] Read(ImageView iv, ReaderOptions? opts = null) { var ptr = CheckError(ZXing_ReadBarcodes(iv._d, opts?._d ?? IntPtr.Zero)); + // return static empty array if no Barcodes are found, avoiding any managed heap allocation + var res = Array.Empty(); var size = ZXing_Barcodes_size(ptr); - var res = new List(size); - for (int i = 0; i < size; ++i) - res.Add(new Barcode(ZXing_Barcodes_move(ptr, i))); + if (size > 0) { + res = new Barcode[size]; + for (int i = 0; i < size; ++i) + res[i] = new Barcode(ZXing_Barcodes_move(ptr, i)); + } + ZXing_Barcodes_delete(ptr); return res; } - public List From(ImageView iv) => Read(iv, this); + public Barcode[] From(ImageView iv) => Read(iv, this); } public class BarcodeCreator : CreatorOptions diff --git a/wrappers/dotnet/ZXingCpp/ZXingCpp.csproj b/wrappers/dotnet/ZXingCpp/ZXingCpp.csproj index a60313cd19..3db7fdd2a9 100644 --- a/wrappers/dotnet/ZXingCpp/ZXingCpp.csproj +++ b/wrappers/dotnet/ZXingCpp/ZXingCpp.csproj @@ -6,7 +6,7 @@ enable ZXingCpp - 0.2.2-alpha + 0.3.0-alpha Axel Waggershauser zxing-cpp @@ -29,4 +29,4 @@ - + From 8ad13cbc8413fb17aa382972f09b28d99cd0364c Mon Sep 17 00:00:00 2001 From: axxel Date: Tue, 5 Nov 2024 14:36:23 +0100 Subject: [PATCH 08/11] rust: publish a new alpha version on crates.io (0.4.1) This should fix the issue discussed in #832. --- wrappers/rust/Cargo.toml | 2 +- wrappers/rust/README.md | 2 +- wrappers/rust/build.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/wrappers/rust/Cargo.toml b/wrappers/rust/Cargo.toml index fa473bb8b1..b38be6ca58 100644 --- a/wrappers/rust/Cargo.toml +++ b/wrappers/rust/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "zxing-cpp" -version = "0.4.0" +version = "0.4.1" edition = "2021" # authors = ["Axel Waggershauser "] license = "Apache-2.0" diff --git a/wrappers/rust/README.md b/wrappers/rust/README.md index 02d870b40f..8c849b3704 100644 --- a/wrappers/rust/README.md +++ b/wrappers/rust/README.md @@ -15,7 +15,7 @@ In your Cargo.toml: # `bundled` causes cargo to compile and statically link an up to # date version of the c++ core library. This is the most convenient # and safe way to build the library. -zxing-cpp = { version = "0.4.0", features = ["bundled", "image"] } +zxing-cpp = { version = "0.4.1", features = ["bundled", "image"] } ``` Simple example reading some barcodes from a jpg file: diff --git a/wrappers/rust/build.rs b/wrappers/rust/build.rs index 8a078fd798..cf17c6c43a 100644 --- a/wrappers/rust/build.rs +++ b/wrappers/rust/build.rs @@ -31,7 +31,7 @@ fn main() -> miette::Result<()> { } // manual bindings.rs generation: - // bindgen core/src/ZXingC.h -o src/bindings.rs --no-prepend-enum-name --merge-extern-blocks --use-core --no-doc-comments --no-layout-tests --with-derive-partialeq --allowlist-item "ZXing.*" + // bindgen core/src/ZXingC.h -o src/bindings.rs --no-prepend-enum-name --merge-extern-blocks --use-core --no-doc-comments --no-layout-tests --with-derive-partialeq --allowlist-item "ZXing.*" -- -DZXING_EXPERIMENTAL_API Ok(()) } From cd9bba33ef9cc175120f6e9ba49cc08b1f27a338 Mon Sep 17 00:00:00 2001 From: axxel Date: Tue, 5 Nov 2024 17:49:18 +0100 Subject: [PATCH 09/11] BitHacks: fix MSVC build when /Zc:__cplusplus is not set on client side This fixes #863. --- core/src/BitHacks.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/core/src/BitHacks.h b/core/src/BitHacks.h index 679f91d2b1..db100e41ae 100644 --- a/core/src/BitHacks.h +++ b/core/src/BitHacks.h @@ -11,11 +11,16 @@ #include #include -#if __has_include() && __cplusplus > 201703L // MSVC has the header but then warns about including it +// MSVC has the header but then warns about including it. +// We check for _MSVC_LANG here as well, so client code is depending on /Zc:__cplusplus +#if __has_include() && (__cplusplus > 201703L || _MSVC_LANG > 201703L) #include #if __cplusplus > 201703L && defined(__ANDROID__) // NDK 25.1.8937393 has the implementation but fails to advertise it #define __cpp_lib_bitops 201907L #endif +#elif defined(_MSC_VER) +// accoring to #863 MSVC defines __cpp_lib_bitops even when it not included and bitops are not available +#undef __cpp_lib_bitops #endif #if defined(__clang__) || defined(__GNUC__) From 30a51c0a2d2d405d787a5154e9f01fd6a1f6e58b Mon Sep 17 00:00:00 2001 From: Stephan Bergmann Date: Wed, 6 Nov 2024 11:04:12 +0100 Subject: [PATCH 10/11] Missing include (for std::nullptr_t) --- core/src/pdf417/ZXNullable.h | 1 + 1 file changed, 1 insertion(+) diff --git a/core/src/pdf417/ZXNullable.h b/core/src/pdf417/ZXNullable.h index 8d3a69ffa7..694087eb3d 100644 --- a/core/src/pdf417/ZXNullable.h +++ b/core/src/pdf417/ZXNullable.h @@ -5,6 +5,7 @@ #pragma once +#include #include #include From 579650afbd9f156d36351980c85722c498426ddc Mon Sep 17 00:00:00 2001 From: axxel Date: Wed, 6 Nov 2024 22:44:18 +0100 Subject: [PATCH 11/11] PDF417: prevent wrong position info with right side collapsing to (0,0) Truncated PDF417 symbols don't have a stop-guard. The top-right and bottom-right info for those was always (0,0). This could also happen for normal PDF417 symbols when detecting the stop-guard failed. This patch introduces a very crude approximation of the right side of the symbol for this case that does at least make some sense. I consider this a fix for #866. This is related to #145 and #340. --- core/src/pdf417/PDFDecoderResultExtra.h | 2 ++ core/src/pdf417/PDFReader.cpp | 11 +++++++++-- core/src/pdf417/PDFScanningDecoder.cpp | 13 +++++++++---- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/core/src/pdf417/PDFDecoderResultExtra.h b/core/src/pdf417/PDFDecoderResultExtra.h index 8aaf60a253..13108a37af 100644 --- a/core/src/pdf417/PDFDecoderResultExtra.h +++ b/core/src/pdf417/PDFDecoderResultExtra.h @@ -33,6 +33,8 @@ class DecoderResultExtra : public CustomData public: + int approxSymbolWidth = -1; + int segmentIndex() const { return _segmentIndex; } diff --git a/core/src/pdf417/PDFReader.cpp b/core/src/pdf417/PDFReader.cpp index 7c804ecf30..b3d0ef4cb6 100644 --- a/core/src/pdf417/PDFReader.cpp +++ b/core/src/pdf417/PDFReader.cpp @@ -9,6 +9,7 @@ #include "PDFDetector.h" #include "PDFScanningDecoder.h" #include "PDFCodewordDecoder.h" +#include "PDFDecoderResultExtra.h" #include "ReaderOptions.h" #include "DecoderResult.h" #include "DetectorResult.h" @@ -85,7 +86,13 @@ static Barcodes DoDecode(const BinaryBitmap& image, bool multiple, bool tryRotat ScanningDecoder::Decode(*detectorResult.bits, points[4], points[5], points[6], points[7], GetMinCodewordWidth(points), GetMaxCodewordWidth(points)); if (decoderResult.isValid(returnErrors)) { - auto point = [&](int i) { return rotate(PointI(points[i].value())); }; + auto point = [&](int i) { + auto meta = dynamic_cast(decoderResult.extra().get()); + if (points[i].hasValue() || i < 2 || !meta) + return rotate(PointI(points[i].value())); + else + return rotate(PointI(points[i-2].value()) + PointI(meta->approxSymbolWidth, 0)); + }; res.emplace_back(std::move(decoderResult), DetectorResult{{}, {point(0), point(2), point(3), point(1)}}, BarcodeFormat::PDF417); if (!multiple) @@ -306,7 +313,7 @@ Reader::decode(const BinaryBitmap& image) const // This falls through and tries the non-pure code path if we have a checksum error. This approach is // currently the best option to deal with 'aliased' input like e.g. 03-aliased.png } - + return FirstOrDefault(DoDecode(image, false, _opts.tryRotate(), _opts.returnErrors())); } diff --git a/core/src/pdf417/PDFScanningDecoder.cpp b/core/src/pdf417/PDFScanningDecoder.cpp index bd5eac8d9c..2fd4f1fcfe 100644 --- a/core/src/pdf417/PDFScanningDecoder.cpp +++ b/core/src/pdf417/PDFScanningDecoder.cpp @@ -13,6 +13,7 @@ #include "PDFCodewordDecoder.h" #include "PDFDetectionResult.h" #include "PDFDecoder.h" +#include "PDFDecoderResultExtra.h" #include "PDFModulusGF.h" #include "ZXAlgorithms.h" #include "ZXTestSupport.h" @@ -127,7 +128,7 @@ static Nullable DetectCodeword(const BitMatrix& image, int minColumn, } // TODO implement check for width and correction of black and white bars // use start (and maybe stop pattern) to determine if blackbars are wider than white bars. If so, adjust. - // should probably done only for codewords with a lot more than 17 bits. + // should probably done only for codewords with a lot more than 17 bits. // The following fixes 10-1.png, which has wide black bars and small white bars // for (int i = 0; i < moduleBitCount.length; i++) { // if (i % 2 == 0) { @@ -674,7 +675,7 @@ static DecoderResult CreateDecoderResult(DetectionResult& detectionResult) // TODO don't pass in minCodewordWidth and maxCodewordWidth, pass in barcode columns for start and stop pattern // columns. That way width can be deducted from the pattern column. -// This approach also allows detecting more details about the barcode, e.g. if a bar type (white or black) is wider +// This approach also allows detecting more details about the barcode, e.g. if a bar type (white or black) is wider // than it should be. This can happen if the scanner used a bad blackpoint. DecoderResult ScanningDecoder::Decode(const BitMatrix& image, const Nullable& imageTopLeft, const Nullable& imageBottomLeft, @@ -685,7 +686,7 @@ ScanningDecoder::Decode(const BitMatrix& image, const Nullable& ima if (!BoundingBox::Create(image.width(), image.height(), imageTopLeft, imageBottomLeft, imageTopRight, imageBottomRight, boundingBox)) { return {}; } - + Nullable leftRowIndicatorColumn, rightRowIndicatorColumn; DetectionResult detectionResult; for (int i = 0; i < 2; i++) { @@ -739,7 +740,11 @@ ScanningDecoder::Decode(const BitMatrix& image, const Nullable& ima } } } - return CreateDecoderResult(detectionResult); + auto res = CreateDecoderResult(detectionResult); + auto meta = dynamic_cast(res.extra().get()); + if (meta) + meta->approxSymbolWidth = (detectionResult.barcodeColumnCount() + 2) * (minCodewordWidth + maxCodewordWidth) / 2; + return res; } } // Pdf417