Merge pull request #106 from Eism/UPCEAN_Extensions

UPCEANExtensions

Thank you very much @Eism for your contribution!
This commit is contained in:
Nikolaos Ftylitakis 2019-06-19 11:16:44 +03:00 committed by GitHub
commit 465e1f0065
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 1119 additions and 15 deletions

View File

@ -5,6 +5,7 @@
#include <zxing/BinaryBitmap.h>
#include <zxing/MultiFormatReader.h>
#include <zxing/DecodeHints.h>
#include <zxing/ResultMetadata.h>
#include "CameraImageWrapper.h"
#include "ImageHandler.h"
#include <QTime>
@ -109,6 +110,25 @@ bool QZXing::getTryHarder()
{
return tryHarder_;
}
void QZXing::setAllowedExtensions(const QVariantList& extensions)
{
std::set<int> 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<DecodeHintType>(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<int>());
try {
res = decoder->decode(bb, hints);
processingTime = t.elapsed();
lastDecodeOperationSucceded_ = true;
} catch(zxing::Exception &/*e*/) {}
}
if (tryHarder_ && bb->isRotateSupported()) {
Ref<BinaryBitmap> 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);

View File

@ -22,6 +22,9 @@
#include <QObject>
#include <QImage>
#include <QVariantList>
#include <set>
#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<int> allowedExtensions_;
/**
* If true, the decoding operation will take place at a different thread.

View File

@ -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 \

View File

@ -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<int> toset) {
allowedEanExtensions = toset;
}
std::set<int> DecodeHints::getAllowedEanExtensions() const {
return allowedEanExtensions;
}
void DecodeHints::setResultPointCallback(Ref<ResultPointCallback> 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<int> 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;
}

View File

@ -23,16 +23,20 @@
#include <zxing/BarcodeFormat.h>
#include <zxing/ResultPointCallback.h>
#include <set>
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<ResultPointCallback> callback;
std::set<int> allowedEanExtensions;
public:
static const DecodeHintType AZTEC_HINT;
@ -75,12 +79,16 @@ class DecodeHints {
void setTryHarder(bool toset);
bool getTryHarder() const;
void setAllowedEanExtensions(std::set<int> toset);
std::set<int> getAllowedEanExtensions() const;
void setResultPointCallback(Ref<ResultPointCallback> const&);
Ref<ResultPointCallback> getResultPointCallback() const;
DecodeHints& operator =(DecodeHints const &other);
friend DecodeHints operator| (DecodeHints const&, DecodeHints const&);
friend DecodeHints operator& (DecodeHints const&, DecodeHints const&);
};
}

View File

@ -35,8 +35,9 @@ namespace zxing {
Result::Result(Ref<String> text,
ArrayRef<zxing::byte> rawBytes,
ArrayRef< Ref<ResultPoint> > 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_;
}
}

View File

@ -26,6 +26,7 @@
#include <zxing/common/Str.h>
#include <zxing/common/Types.h>
#include <zxing/ResultPoint.h>
#include <zxing/ResultMetadata.h>
#include <zxing/BarcodeFormat.h>
namespace zxing {
@ -37,12 +38,14 @@ private:
ArrayRef< Ref<ResultPoint> > resultPoints_;
BarcodeFormat format_;
std::string charSet_;
ResultMetadata metadata_;
public:
Result(Ref<String> text,
ArrayRef<zxing::byte> rawBytes,
ArrayRef< Ref<ResultPoint> > resultPoints,
BarcodeFormat format, std::string charSet = "");
BarcodeFormat format, std::string charSet = "",
ResultMetadata metadata = ResultMetadata());
~Result();
Ref<String> getText();
ArrayRef<zxing::byte> getRawBytes();
@ -50,6 +53,7 @@ public:
ArrayRef< Ref<ResultPoint> >& getResultPoints();
BarcodeFormat getBarcodeFormat() const;
std::string getCharSet() const;
ResultMetadata& getMetadata();
friend std::ostream& operator<<(std::ostream &out, Result& result);
};

View File

@ -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 <zxing/ResultMetadata.h>
#include <zxing/common/ByteArray.h>
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<IntegerValue>(value);
}
void ResultMetadata::put(Key key, const std::string &value) {
_contents[key] = std::make_shared<StringValue>(value);
}
void ResultMetadata::putAll(const ResultMetadata& other) {
_contents.insert(other._contents.begin(), other._contents.end());
}
std::list<ResultMetadata::Key> ResultMetadata::keys() const
{
std::list<Key> 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

View File

@ -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 <string>
#include <map>
#include <memory>
#include <list>
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,
/**
* <p>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.</p>
*/
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<Key> keys() const;
std::string keyToString(Key key) const;
bool empty() const;
private:
struct Value;
struct IntegerValue;
struct StringValue;
std::map<Key, std::shared_ptr<Value>> _contents;
};
}
#endif

View File

@ -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 <vector>
#include <cstdint>
namespace zxing {
/**
* ByteArray is an extension of std::vector<unsigned char>.
*/
class ByteArray : public std::vector<uint8_t>
{
public:
ByteArray() {}
ByteArray(std::initializer_list<uint8_t> list) : std::vector<uint8_t>(list) {}
explicit ByteArray(int len) : std::vector<uint8_t>(len, 0) {}
int length() const { return static_cast<int>(size()); }
const char* charPtr() const { return reinterpret_cast<const char*>(data()); }
char* charPtr() { return reinterpret_cast<char*>(data()); }
};
}
#endif

View File

@ -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
* <a href="http://en.wikipedia.org/wiki/List_of_GS1_country_codes">
* http://en.wikipedia.org/wiki/List_of_GS1_country_codes</a>.
*
* @author Sean Owen
*/
#include <zxing/oned/EANManufacturerOrgSupport.h>
#include <zxing/common/Str.h>
#include <cstdlib>
namespace zxing {
namespace oned {
struct Country {
std::vector<int> 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<String> EANManufacturerOrgSupport::lookupCountryIdentifier(Ref<String>& 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<int> range = Countries[i].range;
int start = range[0];
if (prefix < start) {
return Ref<String>();
}
int end = range.size() == 1 ? start : range[1];
if (prefix <= end) {
return Ref<String>(new String(Countries[i].id));
}
}
return Ref<String>();
}
}
}

View File

@ -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 <zxing/common/Counted.h>
#include <iostream>
#include <vector>
namespace zxing {
class String;
namespace oned {
class EANManufacturerOrgSupport
{
public:
static Ref<String> lookupCountryIdentifier(Ref<String> &productCode);
};
}
}
#endif

View File

@ -61,14 +61,14 @@ MultiFormatUPCEANReader::MultiFormatUPCEANReader(DecodeHints hints) : readers()
#include <typeinfo>
Ref<Result> MultiFormatUPCEANReader::decodeRow(int rowNumber, Ref<BitArray> row, zxing::DecodeHints /*hints*/) {
Ref<Result> MultiFormatUPCEANReader::decodeRow(int rowNumber, Ref<BitArray> 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<UPCEANReader> reader = readers[i];
Ref<Result> result;
try {
result = reader->decodeRow(rowNumber, row, startGuardPattern);
result = reader->decodeRow(rowNumber, row, startGuardPattern, hints);
} catch (ReaderException const& ignored) {
(void)ignored;
continue;

View File

@ -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 <zxing/oned/UPCEANExtension2Support.h>
#include <zxing/oned/UPCEANReader.h>
#include <zxing/oned/OneDResultPoint.h>
#include <zxing/common/BitArray.h>
#include <zxing/Result.h>
#include <zxing/NotFoundException.h>
#include <sstream>
#include <iomanip>
#include <cstdlib>
namespace zxing {
namespace oned {
static int decodeMiddle(Ref<BitArray> row, int rowOffset_, std::string& resultString)
{
std::vector<int> 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<char>('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<Result> UPCEANExtension2Support::decodeRow(int rowNumber, Ref<BitArray> 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<ResultPoint> > resultPoints(2);
resultPoints[0] = Ref<OneDResultPoint>(new OneDResultPoint((extStartRangeBegin + extStartRangeEnd) / 2.0f,
static_cast<float> (rowNumber)));
resultPoints[1] = Ref<OneDResultPoint>(new OneDResultPoint(static_cast<float> (range),
static_cast<float> (rowNumber)));
return Ref<Result>(new Result(Ref<String>(new String(resultString)),
ArrayRef<zxing::byte>(),
resultPoints,
BarcodeFormat::UPC_EAN_EXTENSION,
"",
metadata));
}
}
}

View File

@ -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 <zxing/common/Counted.h>
namespace zxing {
class Result;
class BitArray;
namespace oned {
class UPCEANExtension2Support
{
public:
static Ref<Result> decodeRow(int rowNumber, Ref<BitArray> row, int extStartRangeBegin, int extStartRangeEnd);
};
}
}
#endif

View File

@ -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 <zxing/oned/UPCEANExtension5Support.h>
#include <zxing/oned/UPCEANReader.h>
#include <zxing/oned/OneDResultPoint.h>
#include <zxing/common/BitArray.h>
#include <zxing/Result.h>
#include <zxing/NotFoundException.h>
#include <sstream>
#include <iomanip>
#include <cstdlib>
namespace zxing {
namespace oned {
static int extensionChecksum(const std::string& s)
{
int length = static_cast<int>(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<BitArray> row, int rowOffset_, std::string& resultString)
{
std::vector<int> 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<char>('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<Result> UPCEANExtension5Support::decodeRow(int rowNumber, Ref<BitArray> 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<ResultPoint> > resultPoints(2);
resultPoints[0] = Ref<OneDResultPoint>(new OneDResultPoint((extStartRangeBegin + extStartRangeEnd) / 2.0f,
static_cast<float> (rowNumber)));
resultPoints[1] = Ref<OneDResultPoint>(new OneDResultPoint(static_cast<float> (range),
static_cast<float> (rowNumber)));
return Ref<Result>(new Result(Ref<String>(new String(resultString)),
ArrayRef<zxing::byte>(),
resultPoints,
BarcodeFormat::UPC_EAN_EXTENSION,
"",
metadata));
}
}
}

View File

@ -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 <zxing/common/Counted.h>
namespace zxing {
class Result;
class BitArray;
namespace oned {
class UPCEANExtension5Support
{
public:
static Ref<Result> decodeRow(int rowNumber, Ref<BitArray> row, int extStartRangeBegin, int extStartRangeEnd);
};
}
}
#endif

View File

@ -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 <zxing/oned/UPCEANExtensionSupport.h>
#include <zxing/oned/UPCEANExtension5Support.h>
#include <zxing/oned/UPCEANExtension2Support.h>
#include <zxing/oned/UPCEANReader.h>
#include <zxing/Result.h>
#include <zxing/common/BitArray.h>
#include <zxing/NotFoundException.h>
namespace zxing {
namespace oned {
static const std::vector<int> EXTENSION_START_PATTERN = { 1, 1, 2 };
Ref<Result> UPCEANExtensionSupport::decodeRow(int rowNumber, Ref<BitArray> 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

View File

@ -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 <zxing/common/Counted.h>
namespace zxing {
class Result;
class BitArray;
namespace oned {
class UPCEANExtensionSupport
{
public:
static Ref<Result> decodeRow(int rowNumber, Ref<BitArray> row, int rowOffset);
};
}
}
#endif

View File

@ -118,13 +118,14 @@ UPCEANReader::L_AND_G_PATTERNS (VECTOR_INIT(L_AND_G_PATTERNS_));
UPCEANReader::UPCEANReader() {}
Ref<Result> UPCEANReader::decodeRow(int rowNumber, Ref<BitArray> row, zxing::DecodeHints /*hints*/) {
return decodeRow(rowNumber, row, findStartGuardPattern(row));
Ref<Result> UPCEANReader::decodeRow(int rowNumber, Ref<BitArray> row, DecodeHints hints) {
return decodeRow(rowNumber, row, findStartGuardPattern(row), hints);
}
Ref<Result> UPCEANReader::decodeRow(int rowNumber,
Ref<BitArray> 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<Result> 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<ResultPoint> > resultPoints(2);
resultPoints[0] = Ref<ResultPoint>(new OneDResultPoint(left, (float) rowNumber));
resultPoints[1] = Ref<ResultPoint>(new OneDResultPoint(right, (float) rowNumber));
resultPoints[0] = Ref<ResultPoint>(new OneDResultPoint(left, static_cast<float> (rowNumber)));
resultPoints[1] = Ref<ResultPoint>(new OneDResultPoint(right, static_cast<float> (rowNumber)));
Ref<Result> decodeResult (new Result(resultString, ArrayRef<zxing::byte>(), resultPoints, format));
// Java extension and man stuff
int extensionLength = 0;
try {
Ref<Result> 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>& resultPoint: extensionResult->getResultPoints()->values()) {
decodeResult->getResultPoints()->push_back(resultPoint);
}
}
} catch (NotFoundException const& /*nfe*/) {
// continue
}
std::set<int> 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<String> countryID = eanManSupport.lookupCountryIdentifier(resultString);
if (countryID) {
decodeResult->getMetadata().put(ResultMetadata::POSSIBLE_COUNTRY, countryID->getText());
}
}
return decodeResult;
}

View File

@ -19,6 +19,8 @@
*/
#include <zxing/oned/OneDReader.h>
#include <zxing/oned/UPCEANExtensionSupport.h>
#include <zxing/oned/EANManufacturerOrgSupport.h>
#include <zxing/common/BitArray.h>
#include <zxing/Result.h>
@ -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<int>& counters);
protected:
public:
static const std::vector<int> START_END_PATTERN;
static const std::vector<int> MIDDLE_PATTERN;
@ -67,7 +69,7 @@ public:
std::string& resultString) = 0;
virtual Ref<Result> decodeRow(int rowNumber, Ref<BitArray> row, DecodeHints hints);
virtual Ref<Result> decodeRow(int rowNumber, Ref<BitArray> row, Range const& range);
virtual Ref<Result> decodeRow(int rowNumber, Ref<BitArray> row, Range const& range, DecodeHints hints = DecodeHints());
static int decodeDigit(Ref<BitArray> row,
std::vector<int>& counters,