MultiFormatReader.cpp 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. /*
  2. * Copyright 2016 Nu-book Inc.
  3. * Copyright 2016 ZXing authors
  4. */
  5. // SPDX-License-Identifier: Apache-2.0
  6. #include "MultiFormatReader.h"
  7. #include "BarcodeFormat.h"
  8. #include "BinaryBitmap.h"
  9. #include "ReaderOptions.h"
  10. #include "aztec/AZReader.h"
  11. #include "datamatrix/DMReader.h"
  12. #include "maxicode/MCReader.h"
  13. #include "oned/ODReader.h"
  14. #include "pdf417/PDFReader.h"
  15. #include "qrcode/QRReader.h"
  16. #include <memory>
  17. namespace ZXing {
  18. MultiFormatReader::MultiFormatReader(const ReaderOptions& opts) : _opts(opts)
  19. {
  20. auto formats = opts.formats().empty() ? BarcodeFormat::Any : opts.formats();
  21. // Put linear readers upfront in "normal" mode
  22. if (formats.testFlags(BarcodeFormat::LinearCodes) && !opts.tryHarder())
  23. _readers.emplace_back(new OneD::Reader(opts));
  24. if (formats.testFlags(BarcodeFormat::QRCode | BarcodeFormat::MicroQRCode | BarcodeFormat::RMQRCode))
  25. _readers.emplace_back(new QRCode::Reader(opts, true));
  26. if (formats.testFlag(BarcodeFormat::DataMatrix))
  27. _readers.emplace_back(new DataMatrix::Reader(opts, true));
  28. if (formats.testFlag(BarcodeFormat::Aztec))
  29. _readers.emplace_back(new Aztec::Reader(opts, true));
  30. if (formats.testFlag(BarcodeFormat::PDF417))
  31. _readers.emplace_back(new Pdf417::Reader(opts));
  32. if (formats.testFlag(BarcodeFormat::MaxiCode))
  33. _readers.emplace_back(new MaxiCode::Reader(opts));
  34. // At end in "try harder" mode
  35. if (formats.testFlags(BarcodeFormat::LinearCodes) && opts.tryHarder())
  36. _readers.emplace_back(new OneD::Reader(opts));
  37. }
  38. MultiFormatReader::~MultiFormatReader() = default;
  39. Barcode MultiFormatReader::read(const BinaryBitmap& image) const
  40. {
  41. Barcode r;
  42. for (const auto& reader : _readers) {
  43. r = reader->decode(image);
  44. if (r.isValid())
  45. return r;
  46. }
  47. return _opts.returnErrors() ? r : Barcode();
  48. }
  49. Barcodes MultiFormatReader::readMultiple(const BinaryBitmap& image, int maxSymbols) const
  50. {
  51. Barcodes res;
  52. for (const auto& reader : _readers) {
  53. if (image.inverted() && !reader->supportsInversion)
  54. continue;
  55. auto r = reader->decode(image, maxSymbols);
  56. if (!_opts.returnErrors()) {
  57. #ifdef __cpp_lib_erase_if
  58. std::erase_if(r, [](auto&& s) { return !s.isValid(); });
  59. #else
  60. auto it = std::remove_if(r.begin(), r.end(), [](auto&& s) { return !s.isValid(); });
  61. r.erase(it, r.end());
  62. #endif
  63. }
  64. maxSymbols -= Size(r);
  65. res.insert(res.end(), std::move_iterator(r.begin()), std::move_iterator(r.end()));
  66. if (maxSymbols <= 0)
  67. break;
  68. }
  69. // sort barcodes based on their position on the image
  70. std::sort(res.begin(), res.end(), [](const Barcode& l, const Barcode& r) {
  71. auto lp = l.position().topLeft();
  72. auto rp = r.position().topLeft();
  73. return lp.y < rp.y || (lp.y == rp.y && lp.x < rp.x);
  74. });
  75. return res;
  76. }
  77. } // ZXing