diff --git a/src/QZXing.cpp b/src/QZXing.cpp index 4f81ea9..9f118a2 100644 --- a/src/QZXing.cpp +++ b/src/QZXing.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include "CameraImageWrapper.h" #include "ImageHandler.h" #include @@ -109,6 +110,25 @@ bool QZXing::getTryHarder() { return tryHarder_; } +void QZXing::setAllowedExtensions(const QVariantList& extensions) +{ + std::set allowedExtensions; + for (const QVariant& extension: extensions) { + allowedExtensions.insert(extension.toInt()); + } + + allowedExtensions_ = allowedExtensions; +} + +QVariantList QZXing::getAllowedExtensions() +{ + QVariantList allowedExtensions; + for (const int& extension: allowedExtensions_) { + allowedExtensions << extension; + } + + return allowedExtensions; +} QString QZXing::decoderFormatToString(int fmt) { @@ -185,6 +205,37 @@ bool QZXing::getLastDecodeOperationSucceded() return lastDecodeOperationSucceded_; } +QVariantMap QZXing::metadataToMap(const ResultMetadata &metadata) +{ + QVariantMap obj; + for (const ResultMetadata::Key &key: metadata.keys()) { + QString keyName = QString::fromStdString(metadata.keyToString(key)); + + switch (key) { + case ResultMetadata::ORIENTATION: + case ResultMetadata::ISSUE_NUMBER: + case ResultMetadata::STRUCTURED_APPEND_SEQUENCE: + case ResultMetadata::STRUCTURED_APPEND_CODE_COUNT: + case ResultMetadata::STRUCTURED_APPEND_PARITY: + obj[keyName] = QVariant(metadata.getInt(key)); + break; + case ResultMetadata::ERROR_CORRECTION_LEVEL: + case ResultMetadata::SUGGESTED_PRICE: + case ResultMetadata::POSSIBLE_COUNTRY: + case ResultMetadata::UPC_EAN_EXTENSION: + obj[keyName] = QVariant(metadata.getString(key).c_str()); + break; + + case ResultMetadata::OTHER: + case ResultMetadata::PDF417_EXTRA_METADATA: + case ResultMetadata::BYTE_SEGMENTS: + break; + } + } + + return obj; +} + void QZXing::setDecoder(const uint &hint) { unsigned int newHints = 0; @@ -352,6 +403,10 @@ QString QZXing::decodeImage(const QImage &image, int maxWidth, int maxHeight, bo DecodeHints hints(static_cast(enabledDecoders)); + if (hints.containsFormat(BarcodeFormat::UPC_EAN_EXTENSION)) { + hints.setAllowedEanExtensions(allowedExtensions_); + } + lastDecodeOperationSucceded_ = false; try { res = decoder->decode(bb, hints); @@ -369,6 +424,19 @@ QString QZXing::decodeImage(const QImage &image, int maxWidth, int maxHeight, bo lastDecodeOperationSucceded_ = true; } catch(zxing::Exception &/*e*/) {} + if (!lastDecodeOperationSucceded_ && + hints.containsFormat(BarcodeFormat::UPC_EAN_EXTENSION) && + !allowedExtensions_.empty() && + !(hints & DecodeHints::PRODUCT_HINT).isEmpty() ) { + hints.setAllowedEanExtensions(std::set()); + + try { + res = decoder->decode(bb, hints); + processingTime = t.elapsed(); + lastDecodeOperationSucceded_ = true; + } catch(zxing::Exception &/*e*/) {} + } + if (tryHarder_ && bb->isRotateSupported()) { Ref bbTmp = bb; @@ -400,6 +468,9 @@ QString QZXing::decodeImage(const QImage &image, int maxWidth, int maxHeight, bo emit tagFound(string); emit tagFoundAdvanced(string, foundedFmt, charSet_); + QVariantMap metadataMap = metadataToMap(res->getMetadata()); + emit tagFoundAdvanced(string, foundedFmt, charSet_, metadataMap); + try { const QRectF rect = getTagRect(res->getResultPoints(), binz->getBlackMatrix()); emit tagFoundAdvanced(string, foundedFmt, charSet_, rect); diff --git a/src/QZXing.h b/src/QZXing.h index fd36b63..b35bc8d 100644 --- a/src/QZXing.h +++ b/src/QZXing.h @@ -22,6 +22,9 @@ #include #include +#include + +#include #if QT_VERSION >= 0x050000 class QQmlEngine; @@ -30,6 +33,7 @@ // forward declaration namespace zxing { class MultiFormatReader; +class ResultMetadata; } class ImageHandler; @@ -53,6 +57,7 @@ class Q_PROPERTY(int processingTime READ getProcessTimeOfLastDecoding) Q_PROPERTY(uint enabledDecoders READ getEnabledFormats WRITE setDecoder NOTIFY enabledFormatsChanged) Q_PROPERTY(bool tryHarder READ getTryHarder WRITE setTryHarder) + Q_PROPERTY(QVariantList allowedExtensions READ getAllowedExtensions WRITE setAllowedExtensions) public: /* @@ -112,12 +117,17 @@ public: void setTryHarder(bool tryHarder); bool getTryHarder(); + void setAllowedExtensions(const QVariantList& extensions); + QVariantList getAllowedExtensions(); static QString decoderFormatToString(int fmt); Q_INVOKABLE QString foundedFormat() const; Q_INVOKABLE QString charSet() const; bool getLastDecodeOperationSucceded(); +private: + QVariantMap metadataToMap(const zxing::ResultMetadata& metadata); + public slots: /** * The decoding function. Will try to decode the given image based on the enabled decoders. @@ -200,6 +210,7 @@ signals: void tagFound(QString tag); void tagFoundAdvanced(const QString &tag, const QString &format, const QString &charSet) const; void tagFoundAdvanced(const QString &tag, const QString &format, const QString &charSet, const QRectF &rect) const; + void tagFoundAdvanced(const QString &tag, const QString &format, const QString &charSet, const QVariantMap &metadata) const; void error(QString msg); private: @@ -211,6 +222,7 @@ private: QString charSet_; bool tryHarder_; bool lastDecodeOperationSucceded_; + std::set allowedExtensions_; /** * If true, the decoding operation will take place at a different thread. diff --git a/src/QZXing.pri b/src/QZXing.pri index f0976c9..97339bf 100644 --- a/src/QZXing.pri +++ b/src/QZXing.pri @@ -34,6 +34,7 @@ HEADERS += $$PWD/QZXing_global.h \ $$PWD/zxing/zxing/ResultPointCallback.h \ $$PWD/zxing/zxing/ResultPoint.h \ $$PWD/zxing/zxing/Result.h \ + $$PWD/zxing/zxing/ResultMetadata.h \ $$PWD/zxing/zxing/ReaderException.h \ $$PWD/zxing/zxing/Reader.h \ $$PWD/zxing/zxing/NotFoundException.h \ @@ -75,6 +76,7 @@ HEADERS += $$PWD/QZXing_global.h \ $$PWD/zxing/zxing/common/reedsolomon/ReedSolomonDecoder.h \ $$PWD/zxing/zxing/common/reedsolomon/GenericGFPoly.h \ $$PWD/zxing/zxing/common/reedsolomon/GenericGF.h \ + $$PWD/zxing/zxing/common/ByteArray.h \ $$PWD/zxing/zxing/datamatrix/Version.h \ $$PWD/zxing/zxing/datamatrix/DataMatrixReader.h \ $$PWD/zxing/zxing/datamatrix/decoder/Decoder.h \ @@ -86,6 +88,9 @@ HEADERS += $$PWD/QZXing_global.h \ $$PWD/zxing/zxing/datamatrix/detector/CornerPoint.h \ $$PWD/zxing/zxing/oned/UPCEReader.h \ $$PWD/zxing/zxing/oned/UPCEANReader.h \ + $$PWD/zxing/zxing/oned/UPCEANExtensionSupport.h \ + $$PWD/zxing/zxing/oned/UPCEANExtension2Support.h \ + $$PWD/zxing/zxing/oned/UPCEANExtension5Support.h \ $$PWD/zxing/zxing/oned/UPCAReader.h \ $$PWD/zxing/zxing/oned/OneDResultPoint.h \ $$PWD/zxing/zxing/oned/OneDReader.h \ @@ -94,6 +99,7 @@ HEADERS += $$PWD/QZXing_global.h \ $$PWD/zxing/zxing/oned/ITFReader.h \ $$PWD/zxing/zxing/oned/EAN13Reader.h \ $$PWD/zxing/zxing/oned/EAN8Reader.h \ + $$PWD/zxing/zxing/oned/EANManufacturerOrgSupport.h \ $$PWD/zxing/zxing/oned/Code128Reader.h \ $$PWD/zxing/zxing/oned/Code39Reader.h \ $$PWD/zxing/zxing/oned/CodaBarReader.h \ @@ -157,6 +163,7 @@ SOURCES += $$PWD/CameraImageWrapper.cpp \ $$PWD/zxing/zxing/ResultPointCallback.cpp \ $$PWD/zxing/zxing/ResultPoint.cpp \ $$PWD/zxing/zxing/Result.cpp \ + $$PWD/zxing/zxing/ResultMetadata.cpp \ $$PWD/zxing/zxing/Reader.cpp \ $$PWD/zxing/zxing/MultiFormatReader.cpp \ $$PWD/zxing/zxing/LuminanceSource.cpp \ @@ -198,6 +205,9 @@ SOURCES += $$PWD/CameraImageWrapper.cpp \ $$PWD/zxing/zxing/datamatrix/DataMatrixReader.cpp \ $$PWD/zxing/zxing/oned/UPCEReader.cpp \ $$PWD/zxing/zxing/oned/UPCEANReader.cpp \ + $$PWD/zxing/zxing/oned/UPCEANExtensionSupport.cpp \ + $$PWD/zxing/zxing/oned/UPCEANExtension2Support.cpp \ + $$PWD/zxing/zxing/oned/UPCEANExtension5Support.cpp \ $$PWD/zxing/zxing/oned/UPCAReader.cpp \ $$PWD/zxing/zxing/oned/OneDResultPoint.cpp \ $$PWD/zxing/zxing/oned/OneDReader.cpp \ @@ -206,6 +216,7 @@ SOURCES += $$PWD/CameraImageWrapper.cpp \ $$PWD/zxing/zxing/oned/ITFReader.cpp \ $$PWD/zxing/zxing/oned/EAN13Reader.cpp \ $$PWD/zxing/zxing/oned/EAN8Reader.cpp \ + $$PWD/zxing/zxing/oned/EANManufacturerOrgSupport.cpp \ $$PWD/zxing/zxing/oned/Code128Reader.cpp \ $$PWD/zxing/zxing/oned/Code39Reader.cpp \ $$PWD/zxing/zxing/oned/CodaBarReader.cpp \ diff --git a/src/zxing/zxing/DecodeHints.cpp b/src/zxing/zxing/DecodeHints.cpp index 3961683..3c358ce 100644 --- a/src/zxing/zxing/DecodeHints.cpp +++ b/src/zxing/zxing/DecodeHints.cpp @@ -77,6 +77,7 @@ const zxing::DecodeHints DecodeHints::DEFAULT_HINT( DecodeHints::DecodeHints() { hints = 0; + allowedEanExtensions = {}; } DecodeHints::DecodeHints(const zxing::DecodeHintType &init) { @@ -86,6 +87,7 @@ DecodeHints::DecodeHints(const zxing::DecodeHintType &init) { DecodeHints::DecodeHints(const DecodeHints &other) { hints = other.hints; callback = other.callback; + allowedEanExtensions = other.allowedEanExtensions; } void DecodeHints::addFormat(BarcodeFormat toadd) { @@ -150,6 +152,14 @@ bool DecodeHints::getTryHarder() const { return (hints & TRYHARDER_HINT) != 0; } +void DecodeHints::setAllowedEanExtensions(std::set toset) { + allowedEanExtensions = toset; +} + +std::set DecodeHints::getAllowedEanExtensions() const { + return allowedEanExtensions; +} + void DecodeHints::setResultPointCallback(Ref const& _callback) { callback = _callback; } @@ -162,6 +172,7 @@ zxing::DecodeHints &zxing::DecodeHints::operator =(const zxing::DecodeHints &oth { hints = other.hints; callback = other.callback; + allowedEanExtensions = other.allowedEanExtensions; return *this; } @@ -171,5 +182,27 @@ zxing::DecodeHints zxing::operator | (DecodeHints const& l, DecodeHints const& r if (!result.callback) { result.callback = r.callback; } + + result.allowedEanExtensions = l.allowedEanExtensions; + result.allowedEanExtensions.insert(r.allowedEanExtensions.begin(), + r.allowedEanExtensions.end()); + + return result; +} + +zxing::DecodeHints zxing::operator & (DecodeHints const& l, DecodeHints const& r) { + DecodeHints result (l); + result.hints &= r.hints; + if (!result.callback) { + result.callback = r.callback; + } + + std::set intersect; + std::set_intersection(l.allowedEanExtensions.begin(), l.allowedEanExtensions.end(), + r.allowedEanExtensions.begin(), r.allowedEanExtensions.end(), + std::inserter(intersect, intersect.begin())); + + result.allowedEanExtensions = intersect; + return result; } diff --git a/src/zxing/zxing/DecodeHints.h b/src/zxing/zxing/DecodeHints.h index b39c5b5..b24e349 100644 --- a/src/zxing/zxing/DecodeHints.h +++ b/src/zxing/zxing/DecodeHints.h @@ -23,16 +23,20 @@ #include #include +#include + namespace zxing { typedef unsigned int DecodeHintType; class DecodeHints; DecodeHints operator | (DecodeHints const&, DecodeHints const&); +DecodeHints operator & (DecodeHints const&, DecodeHints const&); class DecodeHints { private: DecodeHintType hints; Ref callback; + std::set allowedEanExtensions; public: static const DecodeHintType AZTEC_HINT; @@ -75,12 +79,16 @@ class DecodeHints { void setTryHarder(bool toset); bool getTryHarder() const; + void setAllowedEanExtensions(std::set toset); + std::set getAllowedEanExtensions() const; + void setResultPointCallback(Ref const&); Ref getResultPointCallback() const; DecodeHints& operator =(DecodeHints const &other); friend DecodeHints operator| (DecodeHints const&, DecodeHints const&); + friend DecodeHints operator& (DecodeHints const&, DecodeHints const&); }; } diff --git a/src/zxing/zxing/Result.cpp b/src/zxing/zxing/Result.cpp index 8f66edb..fdfec54 100644 --- a/src/zxing/zxing/Result.cpp +++ b/src/zxing/zxing/Result.cpp @@ -35,8 +35,9 @@ namespace zxing { Result::Result(Ref text, ArrayRef rawBytes, ArrayRef< Ref > resultPoints, - BarcodeFormat format, std::string charSet) : - text_(text), rawBytes_(rawBytes), resultPoints_(resultPoints), format_(format), charSet_(charSet) { + BarcodeFormat format, std::string charSet, + ResultMetadata metadata) : + text_(text), rawBytes_(rawBytes), resultPoints_(resultPoints), format_(format), charSet_(charSet), metadata_(metadata) { } Result::~Result() { @@ -67,4 +68,9 @@ std::string Result::getCharSet() const return charSet_; } +ResultMetadata &Result::getMetadata() +{ + return metadata_; +} + } diff --git a/src/zxing/zxing/Result.h b/src/zxing/zxing/Result.h index 3e6f731..9a4e6b8 100644 --- a/src/zxing/zxing/Result.h +++ b/src/zxing/zxing/Result.h @@ -26,6 +26,7 @@ #include #include #include +#include #include namespace zxing { @@ -37,12 +38,14 @@ private: ArrayRef< Ref > resultPoints_; BarcodeFormat format_; std::string charSet_; + ResultMetadata metadata_; public: Result(Ref text, ArrayRef rawBytes, ArrayRef< Ref > resultPoints, - BarcodeFormat format, std::string charSet = ""); + BarcodeFormat format, std::string charSet = "", + ResultMetadata metadata = ResultMetadata()); ~Result(); Ref getText(); ArrayRef getRawBytes(); @@ -50,6 +53,7 @@ public: ArrayRef< Ref >& getResultPoints(); BarcodeFormat getBarcodeFormat() const; std::string getCharSet() const; + ResultMetadata& getMetadata(); friend std::ostream& operator<<(std::ostream &out, Result& result); }; diff --git a/src/zxing/zxing/ResultMetadata.cpp b/src/zxing/zxing/ResultMetadata.cpp new file mode 100644 index 0000000..3a194c1 --- /dev/null +++ b/src/zxing/zxing/ResultMetadata.cpp @@ -0,0 +1,110 @@ +/* +* Copyright 2008 ZXing authors +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +* 2019-05-08 translation from Java into C++ +*/ + +#include +#include + +namespace zxing { + +struct ResultMetadata::Value +{ + virtual ~Value() {} + virtual int toInteger(int fallback) const { + return fallback; + } + virtual std::string toString() const { + return std::string(); + } +}; + +struct ResultMetadata::IntegerValue : public Value +{ + int value; + explicit IntegerValue(int v) : value(v) {} + int toInteger(int) const override { + return value; + } +}; + +struct ResultMetadata::StringValue : public Value +{ + std::string value; + explicit StringValue(std::string v) : value(std::move(v)) {} + std::string toString() const override { + return value; + } +}; + +int ResultMetadata::getInt(Key key, int fallbackValue) const +{ + auto it = _contents.find(key); + return it != _contents.end() ? it->second->toInteger(fallbackValue) : fallbackValue; +} + +std::string ResultMetadata::getString(Key key) const { + auto it = _contents.find(key); + return it != _contents.end() ? it->second->toString() : std::string(); +} + +void ResultMetadata::put(Key key, int value) { + _contents[key] = std::make_shared(value); +} + +void ResultMetadata::put(Key key, const std::string &value) { + _contents[key] = std::make_shared(value); +} + +void ResultMetadata::putAll(const ResultMetadata& other) { + _contents.insert(other._contents.begin(), other._contents.end()); +} + +std::list ResultMetadata::keys() const +{ + std::list keys; + for(auto it = _contents.begin(); it != _contents.end(); ++it) { + keys.push_back(it->first); + } + + return keys; +} + +bool ResultMetadata::empty() const +{ + return _contents.empty(); +} + +std::string ResultMetadata::keyToString(Key key) const +{ + switch (key) + { + case OTHER: return "OTHER"; + case ORIENTATION: return "ORIENTATION"; + case BYTE_SEGMENTS: return "BYTE_SEGMENTS"; + case ERROR_CORRECTION_LEVEL: return "ERROR_CORRECTION_LEVEL"; + case ISSUE_NUMBER: return "ISSUE_NUMBER"; + case SUGGESTED_PRICE: return "SUGGESTED_PRICE"; + case POSSIBLE_COUNTRY: return "POSSIBLE_COUNTRY"; + case UPC_EAN_EXTENSION: return "UPC_EAN_EXTENSION"; + case PDF417_EXTRA_METADATA: return "PDF417_EXTRA_METADATA"; + case STRUCTURED_APPEND_SEQUENCE: return "STRUCTURED_APPEND_SEQUENCE"; + case STRUCTURED_APPEND_CODE_COUNT: return "STRUCTURED_APPEND_CODE_COUNT"; + case STRUCTURED_APPEND_PARITY: return "STRUCTURED_APPEND_PARITY"; + } +} + +} // zxing diff --git a/src/zxing/zxing/ResultMetadata.h b/src/zxing/zxing/ResultMetadata.h new file mode 100644 index 0000000..b982e92 --- /dev/null +++ b/src/zxing/zxing/ResultMetadata.h @@ -0,0 +1,137 @@ +#ifndef ZXING_RESULT_METADATA_H +#define ZXING_RESULT_METADATA_H +/* +* Copyright 2008 ZXing authors +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +* 2019-05-08 translation from Java into C++ +*/ + +#include +#include +#include +#include + +namespace zxing { + +class ByteArray; + +/** + * Represents some type of metadata about the result of the decoding that the decoder + * wishes to communicate back to the caller. + */ +class ResultMetadata +{ +public: + + enum Key { + + /** + * Unspecified, application-specific metadata. Maps to an unspecified {@link Object}. + */ + OTHER, + + /** + * Denotes the likely approximate orientation of the barcode in the image. This value + * is given as degrees rotated clockwise from the normal, upright orientation. + * For example a 1D barcode which was found by reading top-to-bottom would be + * said to have orientation "90". This key maps to an {@link Integer} whose + * value is in the range [0,360). + */ + ORIENTATION, + + /** + *

2D barcode formats typically encode text, but allow for a sort of 'byte mode' + * which is sometimes used to encode binary data. While {@link Result} makes available + * the complete raw bytes in the barcode for these formats, it does not offer the bytes + * from the byte segments alone.

+ */ + BYTE_SEGMENTS, + + /** + * Error correction level used, if applicable. The value type depends on the + * format, but is typically a String. + */ + ERROR_CORRECTION_LEVEL, + + /** + * For some periodicals, indicates the issue number as an {@link Integer}. + */ + ISSUE_NUMBER, + + /** + * For some products, indicates the suggested retail price in the barcode as a + * formatted {@link String}. + */ + SUGGESTED_PRICE, + + /** + * For some products, the possible country of manufacture as a {@link String} denoting the + * ISO country code. Some map to multiple possible countries, like "US/CA". + */ + POSSIBLE_COUNTRY, + + /** + * For some products, the extension text + */ + UPC_EAN_EXTENSION, + + /** + * PDF417-specific metadata + */ + PDF417_EXTRA_METADATA, + + /** + * If the code format supports structured append and the current scanned code is part of one then the + * sequence number is given with it. + */ + STRUCTURED_APPEND_SEQUENCE, + + /** + * If the code format supports structured append and the current scanned code is part of one then the + * total code count is given with it. + */ + STRUCTURED_APPEND_CODE_COUNT, + + /** + * If the code format supports structured append and the current scanned code is part of one then the + * parity is given with it. + */ + STRUCTURED_APPEND_PARITY + }; + + int getInt(Key key, int fallbackValue = 0) const; + std::string getString(Key key) const; + + void put(Key key, int value); + void put(Key key, const std::string& value); + + void putAll(const ResultMetadata& other); + + std::list keys() const; + std::string keyToString(Key key) const; + + bool empty() const; + +private: + struct Value; + struct IntegerValue; + struct StringValue; + + std::map> _contents; +}; + +} + +#endif diff --git a/src/zxing/zxing/common/ByteArray.h b/src/zxing/zxing/common/ByteArray.h new file mode 100644 index 0000000..7a2afb9 --- /dev/null +++ b/src/zxing/zxing/common/ByteArray.h @@ -0,0 +1,42 @@ +#ifndef ZXING_BYTE_ARRAY_H +#define ZXING_BYTE_ARRAY_H +/* +* Copyright 2008 ZXing authors +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +* 2019-05-08 translation from Java into C++ +*/ + +#include +#include + +namespace zxing { + +/** + * ByteArray is an extension of std::vector. + */ +class ByteArray : public std::vector +{ +public: + ByteArray() {} + ByteArray(std::initializer_list list) : std::vector(list) {} + explicit ByteArray(int len) : std::vector(len, 0) {} + int length() const { return static_cast(size()); } + const char* charPtr() const { return reinterpret_cast(data()); } + char* charPtr() { return reinterpret_cast(data()); } +}; + +} + +#endif diff --git a/src/zxing/zxing/oned/EANManufacturerOrgSupport.cpp b/src/zxing/zxing/oned/EANManufacturerOrgSupport.cpp new file mode 100644 index 0000000..334b9ff --- /dev/null +++ b/src/zxing/zxing/oned/EANManufacturerOrgSupport.cpp @@ -0,0 +1,168 @@ +/* +* Copyright 2008 ZXing authors +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +/* + * Records EAN prefix to GS1 Member Organization, where the member organization + * correlates strongly with a country. This is an imperfect means of identifying + * a country of origin by EAN-13 barcode value. See + * + * http://en.wikipedia.org/wiki/List_of_GS1_country_codes. + * + * @author Sean Owen + */ + +#include +#include + +#include + +namespace zxing { +namespace oned { + +struct Country { + std::vector range; + std::string id; +}; + +static Country Countries[] { + { {0,19}, "US/CA" }, + { {30,39}, "US" }, + { {60,139}, "US/CA" }, + { {300,379}, "FR" }, + { {380}, "BG" }, + { {383}, "SI" }, + { {385}, "HR" }, + { {387}, "BA" }, + { {400,440}, "DE" }, + { {450,459}, "JP" }, + { {460,469}, "RU" }, + { {471}, "TW" }, + { {474}, "EE" }, + { {475}, "LV" }, + { {476}, "AZ" }, + { {477}, "LT" }, + { {478}, "UZ" }, + { {479}, "LK" }, + { {480}, "PH" }, + { {481}, "BY" }, + { {482}, "UA" }, + { {484}, "MD" }, + { {485}, "AM" }, + { {486}, "GE" }, + { {487}, "KZ" }, + { {489}, "HK" }, + { {490,499}, "JP" }, + { {500,509}, "GB" }, + { {520}, "GR" }, + { {528}, "LB" }, + { {529}, "CY" }, + { {531}, "MK" }, + { {535}, "MT" }, + { {539}, "IE" }, + { {540,549}, "BE/LU" }, + { {560}, "PT" }, + { {569}, "IS" }, + { {570,579}, "DK" }, + { {590}, "PL" }, + { {594}, "RO" }, + { {599}, "HU" }, + { {600,601}, "ZA" }, + { {603}, "GH" }, + { {608}, "BH" }, + { {609}, "MU" }, + { {611}, "MA" }, + { {613}, "DZ" }, + { {616}, "KE" }, + { {618}, "CI" }, + { {619}, "TN" }, + { {621}, "SY" }, + { {622}, "EG" }, + { {624}, "LY" }, + { {625}, "JO" }, + { {626}, "IR" }, + { {627}, "KW" }, + { {628}, "SA" }, + { {629}, "AE" }, + { {640,649}, "FI" }, + { {690,695}, "CN" }, + { {700,709}, "NO" }, + { {729}, "IL" }, + { {730,739}, "SE" }, + { {740}, "GT" }, + { {741}, "SV" }, + { {742}, "HN" }, + { {743}, "NI" }, + { {744}, "CR" }, + { {745}, "PA" }, + { {746}, "DO" }, + { {750}, "MX" }, + { {754,755}, "CA" }, + { {759}, "VE" }, + { {760,769}, "CH" }, + { {770}, "CO" }, + { {773}, "UY" }, + { {775}, "PE" }, + { {777}, "BO" }, + { {779}, "AR" }, + { {780}, "CL" }, + { {784}, "PY" }, + { {785}, "PE" }, + { {786}, "EC" }, + { {789,790}, "BR" }, + { {800,839}, "IT" }, + { {840,849}, "ES" }, + { {850}, "CU" }, + { {858}, "SK" }, + { {859}, "CZ" }, + { {860}, "YU" }, + { {865}, "MN" }, + { {867}, "KP" }, + { {868,869}, "TR" }, + { {870,879}, "NL" }, + { {880}, "KR" }, + { {885}, "TH" }, + { {888}, "SG" }, + { {890}, "IN" }, + { {893}, "VN" }, + { {896}, "PK" }, + { {899}, "ID" }, + { {900,919}, "AT" }, + { {930,939}, "AU" }, + { {940,949}, "AZ" }, + { {955}, "MY" }, + { {958}, "MO" } +}; + +Ref EANManufacturerOrgSupport::lookupCountryIdentifier(Ref& productCode) +{ + int prefix = std::atoi(productCode->getText().substr(0, 3).c_str()); + int size = (sizeof(Countries) / sizeof(Countries[0])); + for (int i = 0; i < size; i++) { + std::vector range = Countries[i].range; + int start = range[0]; + if (prefix < start) { + return Ref(); + } + int end = range.size() == 1 ? start : range[1]; + if (prefix <= end) { + return Ref(new String(Countries[i].id)); + } + } + return Ref(); +} + +} +} diff --git a/src/zxing/zxing/oned/EANManufacturerOrgSupport.h b/src/zxing/zxing/oned/EANManufacturerOrgSupport.h new file mode 100644 index 0000000..e317ff7 --- /dev/null +++ b/src/zxing/zxing/oned/EANManufacturerOrgSupport.h @@ -0,0 +1,41 @@ +#ifndef ZXING_EAN_MANUFACTURER_ORG_SUPPORT_H +#define ZXING_EAN_MANUFACTURER_ORG_SUPPORT_H +/* +* Copyright 2008 ZXing authors +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +* 2019-05-08 translation from Java into C++ +*/ + +#include + +#include +#include + +namespace zxing { + +class String; + +namespace oned { + +class EANManufacturerOrgSupport +{ +public: + static Ref lookupCountryIdentifier(Ref &productCode); +}; + +} +} + +#endif diff --git a/src/zxing/zxing/oned/MultiFormatUPCEANReader.cpp b/src/zxing/zxing/oned/MultiFormatUPCEANReader.cpp index 0ee3398..fbff86b 100644 --- a/src/zxing/zxing/oned/MultiFormatUPCEANReader.cpp +++ b/src/zxing/zxing/oned/MultiFormatUPCEANReader.cpp @@ -61,14 +61,14 @@ MultiFormatUPCEANReader::MultiFormatUPCEANReader(DecodeHints hints) : readers() #include -Ref MultiFormatUPCEANReader::decodeRow(int rowNumber, Ref row, zxing::DecodeHints /*hints*/) { +Ref MultiFormatUPCEANReader::decodeRow(int rowNumber, Ref row, DecodeHints hints) { // Compute this location once and reuse it on multiple implementations UPCEANReader::Range startGuardPattern = UPCEANReader::findStartGuardPattern(row); for (int i = 0, e = int(readers.size()); i < e; i++) { Ref reader = readers[i]; Ref result; try { - result = reader->decodeRow(rowNumber, row, startGuardPattern); + result = reader->decodeRow(rowNumber, row, startGuardPattern, hints); } catch (ReaderException const& ignored) { (void)ignored; continue; diff --git a/src/zxing/zxing/oned/UPCEANExtension2Support.cpp b/src/zxing/zxing/oned/UPCEANExtension2Support.cpp new file mode 100644 index 0000000..657d4d7 --- /dev/null +++ b/src/zxing/zxing/oned/UPCEANExtension2Support.cpp @@ -0,0 +1,96 @@ +/* +* Copyright 2008 ZXing authors +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +* 2019-05-08 translation from Java into C++ +*/ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace zxing { +namespace oned { + +static int decodeMiddle(Ref row, int rowOffset_, std::string& resultString) +{ + std::vector counters(4); + counters[0] = 0; + counters[1] = 0; + counters[2] = 0; + counters[3] = 0; + + int end = row->getSize(); + int rowOffset = rowOffset_; + + int lgPatternFound = 0; + + for (int x = 0; x < 2 && rowOffset < end; x++) { + int bestMatch = UPCEANReader::decodeDigit(row, counters, rowOffset, + UPCEANReader::L_AND_G_PATTERNS); + resultString += static_cast('0' + bestMatch % 10); + for (int counter : counters) { + rowOffset += counter; + } + if (bestMatch >= 10) { + lgPatternFound |= 1 << (1 - x); + } + if (x != 1) { + // Read off separator if not last + rowOffset = row->getNextSet(rowOffset); + rowOffset = row->getNextUnset(rowOffset); + } + } + + if (resultString.length() != 2) { + throw NotFoundException(); + } + + if (std::atoi(resultString.c_str()) % 4 !=lgPatternFound) { + throw NotFoundException(); + } + + return rowOffset; +} + +Ref UPCEANExtension2Support::decodeRow(int rowNumber, Ref row, int extStartRangeBegin, int extStartRangeEnd) +{ + std::string resultString; + int range = decodeMiddle(row, extStartRangeEnd, resultString); + + ResultMetadata metadata; + metadata.put(ResultMetadata::ISSUE_NUMBER, std::atoi(resultString.c_str())); + + ArrayRef< Ref > resultPoints(2); + resultPoints[0] = Ref(new OneDResultPoint((extStartRangeBegin + extStartRangeEnd) / 2.0f, + static_cast (rowNumber))); + resultPoints[1] = Ref(new OneDResultPoint(static_cast (range), + static_cast (rowNumber))); + return Ref(new Result(Ref(new String(resultString)), + ArrayRef(), + resultPoints, + BarcodeFormat::UPC_EAN_EXTENSION, + "", + metadata)); +} + +} +} diff --git a/src/zxing/zxing/oned/UPCEANExtension2Support.h b/src/zxing/zxing/oned/UPCEANExtension2Support.h new file mode 100644 index 0000000..f36b145 --- /dev/null +++ b/src/zxing/zxing/oned/UPCEANExtension2Support.h @@ -0,0 +1,38 @@ +#ifndef ZXING_UPCEAN_EXTENSION_2_SUPPORT_H +#define ZXING_UPCEAN_EXTENSION_2_SUPPORT_H +/* +* Copyright 2008 ZXing authors +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +* 2019-05-08 translation from Java into C++ +*/ +#include + +namespace zxing { + +class Result; +class BitArray; + +namespace oned { + +class UPCEANExtension2Support +{ +public: + static Ref decodeRow(int rowNumber, Ref row, int extStartRangeBegin, int extStartRangeEnd); +}; + +} +} + +#endif diff --git a/src/zxing/zxing/oned/UPCEANExtension5Support.cpp b/src/zxing/zxing/oned/UPCEANExtension5Support.cpp new file mode 100644 index 0000000..c474ff6 --- /dev/null +++ b/src/zxing/zxing/oned/UPCEANExtension5Support.cpp @@ -0,0 +1,165 @@ +/* +* Copyright 2008 ZXing authors +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +* 2019-05-08 translation from Java into C++ +*/ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace zxing { +namespace oned { + +static int extensionChecksum(const std::string& s) +{ + int length = static_cast(s.length()); + int sum = 0; + for (int i = length - 2; i >= 0; i -= 2) { + sum += (int)s[i] - (int) '0'; + } + sum *= 3; + for (int i = length - 1; i >= 0; i -= 2) { + sum += (int)s[i] - (int) '0'; + } + sum *= 3; + return sum % 10; +} + +static int determineCheckDigit(int lgPatternFound) +{ + static const int CHECK_DIGIT_ENCODINGS[] = { + 0x18, 0x14, 0x12, 0x11, 0x0C, 0x06, 0x03, 0x0A, 0x09, 0x05 + }; + for (int d = 0; d < 10; d++) { + if (lgPatternFound == CHECK_DIGIT_ENCODINGS[d]) { + return d; + } + } + return -1; +} + +static int decodeMiddle(Ref row, int rowOffset_, std::string& resultString) +{ + std::vector counters(4); + counters[0] = 0; + counters[1] = 0; + counters[2] = 0; + counters[3] = 0; + + int end = row->getSize(); + int rowOffset = rowOffset_; + + int lgPatternFound = 0; + + for (int x = 0; x < 5 && rowOffset < end; x++) { + int bestMatch = UPCEANReader::decodeDigit(row, counters, rowOffset, + UPCEANReader::L_AND_G_PATTERNS); + resultString += static_cast('0' + bestMatch % 10); + for (int counter : counters) { + rowOffset += counter; + } + if (bestMatch >= 10) { + lgPatternFound |= 1 << (4 - x); + } + if (x != 4) { + // Read off separator if not last + rowOffset = row->getNextSet(rowOffset); + rowOffset = row->getNextUnset(rowOffset); + } + } + + if (resultString.length() != 5) { + throw NotFoundException(); + } + + int checkDigit = determineCheckDigit(lgPatternFound); + if (extensionChecksum(resultString) != checkDigit) { + throw NotFoundException(); + } + + return rowOffset; +} + +static std::string parseExtension5String(const std::string& raw) +{ + std::string currency; + switch (raw.front()) { + case '0': + currency = "\xa3"; + break; + case '5': + currency = "$"; + break; + case '9': + // Reference: http://www.jollytech.com + if (raw == "90000") { + // No suggested retail price + return std::string(); + } + if (raw == "99991") { + // Complementary + return "0.00"; + } + if (raw == "99990") { + return "Used"; + } + // Otherwise... unknown currency? + currency = ""; + break; + default: + currency = ""; + break; + } + int rawAmount = std::atoi(raw.substr(1).c_str()); + std::stringstream buf; + buf << currency << std::fixed << std::setprecision(2) << (float(rawAmount) / 100); + return buf.str(); +} + +Ref UPCEANExtension5Support::decodeRow(int rowNumber, Ref row, int extStartRangeBegin, int extStartRangeEnd) +{ + std::string resultString; + int range = decodeMiddle(row, extStartRangeEnd, resultString); + + ResultMetadata metadata; + std::string value = parseExtension5String(resultString); + if (!value.empty()) { + metadata.put(ResultMetadata::SUGGESTED_PRICE, value); + } + + ArrayRef< Ref > resultPoints(2); + resultPoints[0] = Ref(new OneDResultPoint((extStartRangeBegin + extStartRangeEnd) / 2.0f, + static_cast (rowNumber))); + resultPoints[1] = Ref(new OneDResultPoint(static_cast (range), + static_cast (rowNumber))); + + return Ref(new Result(Ref(new String(resultString)), + ArrayRef(), + resultPoints, + BarcodeFormat::UPC_EAN_EXTENSION, + "", + metadata)); +} + +} +} diff --git a/src/zxing/zxing/oned/UPCEANExtension5Support.h b/src/zxing/zxing/oned/UPCEANExtension5Support.h new file mode 100644 index 0000000..090b151 --- /dev/null +++ b/src/zxing/zxing/oned/UPCEANExtension5Support.h @@ -0,0 +1,38 @@ +#ifndef ZXING_UPCEAN_EXTENSION_5_SUPPORT_H +#define ZXING_UPCEAN_EXTENSION_5_SUPPORT_H +/* +* Copyright 2008 ZXing authors +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +* 2019-05-08 translation from Java into C++ +*/ +#include + +namespace zxing { + +class Result; +class BitArray; + +namespace oned { + +class UPCEANExtension5Support +{ +public: + static Ref decodeRow(int rowNumber, Ref row, int extStartRangeBegin, int extStartRangeEnd); +}; + +} +} + +#endif diff --git a/src/zxing/zxing/oned/UPCEANExtensionSupport.cpp b/src/zxing/zxing/oned/UPCEANExtensionSupport.cpp new file mode 100644 index 0000000..8866f21 --- /dev/null +++ b/src/zxing/zxing/oned/UPCEANExtensionSupport.cpp @@ -0,0 +1,44 @@ +/* +* Copyright 2008 ZXing authors +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +* 2019-05-08 translation from Java into C++ +*/ + +#include +#include +#include +#include +#include +#include +#include + +namespace zxing { +namespace oned { + +static const std::vector EXTENSION_START_PATTERN = { 1, 1, 2 }; + +Ref UPCEANExtensionSupport::decodeRow(int rowNumber, Ref row, int rowOffset) +{ + auto extStartRange = UPCEANReader::findGuardPattern(row, rowOffset, false, EXTENSION_START_PATTERN); + + try { + return UPCEANExtension5Support::decodeRow(rowNumber, row, extStartRange[0], extStartRange[1]); + } catch (NotFoundException const& /*nfe*/) { + return UPCEANExtension2Support::decodeRow(rowNumber, row, extStartRange[0], extStartRange[1]); + } +} + +} // oned +} // zxing diff --git a/src/zxing/zxing/oned/UPCEANExtensionSupport.h b/src/zxing/zxing/oned/UPCEANExtensionSupport.h new file mode 100644 index 0000000..ecdc171 --- /dev/null +++ b/src/zxing/zxing/oned/UPCEANExtensionSupport.h @@ -0,0 +1,38 @@ +#ifndef ZXING_UPCEAN_EXTENSION_SUPPORT_H +#define ZXING_UPCEAN_EXTENSION_SUPPORT_H +/* +* Copyright 2008 ZXing authors +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +* 2019-05-08 translation from Java into C++ +*/ +#include + +namespace zxing { + +class Result; +class BitArray; + +namespace oned { + +class UPCEANExtensionSupport +{ +public: + static Ref decodeRow(int rowNumber, Ref row, int rowOffset); +}; + +} +} + +#endif diff --git a/src/zxing/zxing/oned/UPCEANReader.cpp b/src/zxing/zxing/oned/UPCEANReader.cpp index 8daab87..0853871 100644 --- a/src/zxing/zxing/oned/UPCEANReader.cpp +++ b/src/zxing/zxing/oned/UPCEANReader.cpp @@ -118,13 +118,14 @@ UPCEANReader::L_AND_G_PATTERNS (VECTOR_INIT(L_AND_G_PATTERNS_)); UPCEANReader::UPCEANReader() {} -Ref UPCEANReader::decodeRow(int rowNumber, Ref row, zxing::DecodeHints /*hints*/) { - return decodeRow(rowNumber, row, findStartGuardPattern(row)); +Ref UPCEANReader::decodeRow(int rowNumber, Ref row, DecodeHints hints) { + return decodeRow(rowNumber, row, findStartGuardPattern(row), hints); } Ref UPCEANReader::decodeRow(int rowNumber, Ref row, - Range const& startGuardRange) { + Range const& startGuardRange, + DecodeHints hints) { string& result = decodeRowStringBuffer; result.clear(); int endStart = decodeMiddle(row, startGuardRange, result); @@ -153,11 +154,50 @@ Ref UPCEANReader::decodeRow(int rowNumber, float left = (float) (startGuardRange[1] + startGuardRange[0]) / 2.0f; float right = (float) (endRange[1] + endRange[0]) / 2.0f; BarcodeFormat format = getBarcodeFormat(); + ArrayRef< Ref > resultPoints(2); - resultPoints[0] = Ref(new OneDResultPoint(left, (float) rowNumber)); - resultPoints[1] = Ref(new OneDResultPoint(right, (float) rowNumber)); + resultPoints[0] = Ref(new OneDResultPoint(left, static_cast (rowNumber))); + resultPoints[1] = Ref(new OneDResultPoint(right, static_cast (rowNumber))); + Ref decodeResult (new Result(resultString, ArrayRef(), resultPoints, format)); - // Java extension and man stuff + int extensionLength = 0; + + try { + Ref extensionResult = extensionReader.decodeRow(rowNumber, row, endRange[1]); + if (extensionResult) { + decodeResult->getMetadata().put(ResultMetadata::UPC_EAN_EXTENSION, extensionResult->getText()->getText()); + decodeResult->getMetadata().putAll(extensionResult->getMetadata()); + extensionLength = extensionResult->getText()->length(); + + for (const Ref& resultPoint: extensionResult->getResultPoints()->values()) { + decodeResult->getResultPoints()->push_back(resultPoint); + } + } + } catch (NotFoundException const& /*nfe*/) { + // continue + } + + std::set allowedExtensions = hints.getAllowedEanExtensions(); + if (allowedExtensions.size() > 0) { + bool valid = false; + for (int length: allowedExtensions) { + if (extensionLength == length) { + valid = true; + break; + } + } + if (!valid) { + throw NotFoundException(); + } + } + + if (format == BarcodeFormat::EAN_13 || format == BarcodeFormat::UPC_A) { + Ref countryID = eanManSupport.lookupCountryIdentifier(resultString); + if (countryID) { + decodeResult->getMetadata().put(ResultMetadata::POSSIBLE_COUNTRY, countryID->getText()); + } + } + return decodeResult; } diff --git a/src/zxing/zxing/oned/UPCEANReader.h b/src/zxing/zxing/oned/UPCEANReader.h index 452db88..98bb020 100644 --- a/src/zxing/zxing/oned/UPCEANReader.h +++ b/src/zxing/zxing/oned/UPCEANReader.h @@ -19,6 +19,8 @@ */ #include +#include +#include #include #include @@ -28,8 +30,8 @@ namespace oned { class UPCEANReader : public OneDReader { private: std::string decodeRowStringBuffer; - // UPCEANExtensionSupport extensionReader; - // EANManufacturerOrgSupport eanManSupport; + UPCEANExtensionSupport extensionReader; + EANManufacturerOrgSupport eanManSupport; static const int MAX_AVG_VARIANCE; static const int MAX_INDIVIDUAL_VARIANCE; @@ -47,7 +49,7 @@ class UPCEANReader : public OneDReader { std::vector& counters); -protected: +public: static const std::vector START_END_PATTERN; static const std::vector MIDDLE_PATTERN; @@ -67,7 +69,7 @@ public: std::string& resultString) = 0; virtual Ref decodeRow(int rowNumber, Ref row, DecodeHints hints); - virtual Ref decodeRow(int rowNumber, Ref row, Range const& range); + virtual Ref decodeRow(int rowNumber, Ref row, Range const& range, DecodeHints hints = DecodeHints()); static int decodeDigit(Ref row, std::vector& counters,