From 7bba1c4680e5a7847f65ba306d8e063391a8b828 Mon Sep 17 00:00:00 2001 From: flyashi Date: Thu, 29 Jul 2010 19:39:44 +0000 Subject: [PATCH] C++ port: add decode hints system git-svn-id: https://zxing.googlecode.com/svn/trunk@1498 59b500cc-1b3d-0410-9834-0bbf25fbcc57 --- cpp/core/src/zxing/DecodeHints.cpp | 80 +++++++++++++++++++ cpp/core/src/zxing/DecodeHints.h | 79 ++++++++++++++++++ cpp/core/src/zxing/MultiFormatReader.cpp | 6 +- cpp/core/src/zxing/MultiFormatReader.h | 3 +- cpp/core/src/zxing/Reader.cpp | 5 ++ cpp/core/src/zxing/Reader.h | 4 +- .../src/zxing/datamatrix/DataMatrixReader.cpp | 2 +- .../src/zxing/datamatrix/DataMatrixReader.h | 3 +- cpp/core/src/zxing/oned/OneDReader.cpp | 55 ++++++------- cpp/core/src/zxing/oned/OneDReader.h | 5 +- cpp/core/src/zxing/oned/UPCAReader.cpp | 4 +- cpp/core/src/zxing/oned/UPCAReader.h | 3 +- cpp/core/src/zxing/qrcode/QRCodeReader.cpp | 4 +- cpp/core/src/zxing/qrcode/QRCodeReader.h | 3 +- 14 files changed, 214 insertions(+), 42 deletions(-) create mode 100644 cpp/core/src/zxing/DecodeHints.cpp create mode 100644 cpp/core/src/zxing/DecodeHints.h diff --git a/cpp/core/src/zxing/DecodeHints.cpp b/cpp/core/src/zxing/DecodeHints.cpp new file mode 100644 index 000000000..5a9da76f0 --- /dev/null +++ b/cpp/core/src/zxing/DecodeHints.cpp @@ -0,0 +1,80 @@ +/* + * DecodeHintType.cpp + * zxing + * + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ + +#include +#include +namespace zxing { + +DecodeHints::DecodeHints() { + hints = 0; +} + +DecodeHints::DecodeHints(DecodeHintType init) { + hints = init; +} + +DecodeHints::~DecodeHints() { + // if DecodeHintType requires a destructor in the future, call it here +} + +void DecodeHints::addFormat(BarcodeFormat toadd) { + switch (toadd) { + case BarcodeFormat_QR_CODE: hints |= BARCODEFORMAT_QR_CODE_HINT; break; + case BarcodeFormat_DATA_MATRIX: hints |= BARCODEFORMAT_DATA_MATRIX_HINT; break; + case BarcodeFormat_UPC_E: hints |= BARCODEFORMAT_UPC_E_HINT; break; + case BarcodeFormat_UPC_A: hints |= BARCODEFORMAT_UPC_A_HINT; break; + case BarcodeFormat_EAN_8: hints |= BARCODEFORMAT_EAN_8_HINT; break; + case BarcodeFormat_EAN_13: hints |= BARCODEFORMAT_EAN_13_HINT; break; + case BarcodeFormat_CODE_128: hints |= BARCODEFORMAT_CODE_128_HINT; break; + case BarcodeFormat_CODE_39: hints |= BARCODEFORMAT_CODE_39_HINT; break; + case BarcodeFormat_ITF: hints |= BARCODEFORMAT_ITF_HINT; break; + default: throw IllegalArgumentException("Unrecognizd barcode format"); + } +} + +bool DecodeHints::containsFormat(BarcodeFormat tocheck) const { + DecodeHintType checkAgainst; + switch (tocheck) { + case BarcodeFormat_QR_CODE: checkAgainst = BARCODEFORMAT_QR_CODE_HINT; break; + case BarcodeFormat_DATA_MATRIX: checkAgainst = BARCODEFORMAT_DATA_MATRIX_HINT; break; + case BarcodeFormat_UPC_E: checkAgainst = BARCODEFORMAT_UPC_E_HINT; break; + case BarcodeFormat_UPC_A: checkAgainst = BARCODEFORMAT_UPC_A_HINT; break; + case BarcodeFormat_EAN_8: checkAgainst = BARCODEFORMAT_EAN_8_HINT; break; + case BarcodeFormat_EAN_13: checkAgainst = BARCODEFORMAT_EAN_13_HINT; break; + case BarcodeFormat_CODE_128: checkAgainst = BARCODEFORMAT_CODE_128_HINT; break; + case BarcodeFormat_CODE_39: checkAgainst = BARCODEFORMAT_CODE_39_HINT; break; + case BarcodeFormat_ITF: checkAgainst = BARCODEFORMAT_ITF_HINT; break; + default: throw IllegalArgumentException("Unrecognizd barcode format"); + } + return (hints & checkAgainst); +} + +void DecodeHints::setTryHarder(bool toset) { + if (toset) { + hints |= TRYHARDER_HINT; + } else { + hints &= ~TRYHARDER_HINT; + } +} + +bool DecodeHints::getTryHarder() const { + return (hints & TRYHARDER_HINT); +} + +} /* namespace */ diff --git a/cpp/core/src/zxing/DecodeHints.h b/cpp/core/src/zxing/DecodeHints.h new file mode 100644 index 000000000..cd1fe2585 --- /dev/null +++ b/cpp/core/src/zxing/DecodeHints.h @@ -0,0 +1,79 @@ +/* + * DecodeHintType.h + * zxing + * + * Copyright 2010 ZXing authors All rights reserved. + * + * 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. + */ +#ifndef DECODEHINTS_H_ +#define DECODEHINTS_H_ + +#include + +namespace zxing { + +typedef unsigned int DecodeHintType; + +class DecodeHints { + + private: + + static const DecodeHintType BARCODEFORMAT_QR_CODE_HINT = 1 << BarcodeFormat_QR_CODE; + static const DecodeHintType BARCODEFORMAT_DATA_MATRIX_HINT = 1 << BarcodeFormat_DATA_MATRIX; + static const DecodeHintType BARCODEFORMAT_UPC_E_HINT = 1 << BarcodeFormat_UPC_E; + static const DecodeHintType BARCODEFORMAT_UPC_A_HINT = 1 << BarcodeFormat_UPC_A; + static const DecodeHintType BARCODEFORMAT_EAN_8_HINT = 1 << BarcodeFormat_EAN_8; + static const DecodeHintType BARCODEFORMAT_EAN_13_HINT = 1 << BarcodeFormat_EAN_13; + static const DecodeHintType BARCODEFORMAT_CODE_128_HINT = 1 << BarcodeFormat_CODE_128; + static const DecodeHintType BARCODEFORMAT_CODE_39_HINT = 1 << BarcodeFormat_CODE_39; + static const DecodeHintType BARCODEFORMAT_ITF_HINT = 1 << BarcodeFormat_ITF; + static const DecodeHintType TRYHARDER_HINT = 1 << 31; + + DecodeHintType hints; + + public: + + static const DecodeHintType BARCODEFORMAT_PRODUCT_HINT = + BARCODEFORMAT_UPC_E_HINT | + BARCODEFORMAT_UPC_A_HINT | + BARCODEFORMAT_EAN_8_HINT | + BARCODEFORMAT_EAN_13_HINT; + + static const DecodeHintType BARCODEFORMAT_ONED_HINT = + BARCODEFORMAT_PRODUCT_HINT | + BARCODEFORMAT_CODE_128_HINT | + BARCODEFORMAT_CODE_39_HINT | + BARCODEFORMAT_ITF_HINT; + + static const DecodeHintType BARCODEFORMAT_ANY_HINT = + BARCODEFORMAT_ONED_HINT | +// TODO: uncomment once this passes QA +// BARCODEFORMAT_DATA_MATRIX_HINT | + BARCODEFORMAT_QR_CODE_HINT; + + static const DecodeHintType DEFAULT_HINTS = BARCODEFORMAT_ANY_HINT; + + DecodeHints(); + DecodeHints(DecodeHintType init); + ~DecodeHints(); + void addFormat(BarcodeFormat toadd); + bool containsFormat(BarcodeFormat tocheck) const; + void setTryHarder(bool toset); + bool getTryHarder() const; + +}; + +} + +#endif diff --git a/cpp/core/src/zxing/MultiFormatReader.cpp b/cpp/core/src/zxing/MultiFormatReader.cpp index 40ad5af0b..a4631888d 100644 --- a/cpp/core/src/zxing/MultiFormatReader.cpp +++ b/cpp/core/src/zxing/MultiFormatReader.cpp @@ -34,10 +34,10 @@ namespace zxing { readers.push_back(new zxing::oned::MultiFormatOneDReader()); } - Ref MultiFormatReader::decode(Ref image){ + Ref MultiFormatReader::decode(Ref image, DecodeHints hints){ for (unsigned int i = 0; i < readers.size(); i++) { try { - return readers[i]->decode(image); + return readers[i]->decode(image, hints); } catch (ReaderException re) { // continue } @@ -50,4 +50,4 @@ namespace zxing { delete readers[i]; } } -} \ No newline at end of file +} diff --git a/cpp/core/src/zxing/MultiFormatReader.h b/cpp/core/src/zxing/MultiFormatReader.h index f88ebc979..44d4ce248 100644 --- a/cpp/core/src/zxing/MultiFormatReader.h +++ b/cpp/core/src/zxing/MultiFormatReader.h @@ -23,6 +23,7 @@ #include #include #include +#include namespace zxing { class MultiFormatReader : public Reader { @@ -32,7 +33,7 @@ namespace zxing { public: MultiFormatReader(); - Ref decode(Ref image); + Ref decode(Ref image, DecodeHints hints); ~MultiFormatReader(); }; diff --git a/cpp/core/src/zxing/Reader.cpp b/cpp/core/src/zxing/Reader.cpp index 1e1fdc39b..8326051b3 100755 --- a/cpp/core/src/zxing/Reader.cpp +++ b/cpp/core/src/zxing/Reader.cpp @@ -24,4 +24,9 @@ namespace zxing { Reader::~Reader() { } +Ref Reader::decode(Ref image) { + DecodeHints hints(hints.DEFAULT_HINTS); + return decode(image, hints); +} + } diff --git a/cpp/core/src/zxing/Reader.h b/cpp/core/src/zxing/Reader.h index d7844a9ae..8f16c98c5 100755 --- a/cpp/core/src/zxing/Reader.h +++ b/cpp/core/src/zxing/Reader.h @@ -23,6 +23,7 @@ #include #include +#include namespace zxing { @@ -30,7 +31,8 @@ namespace zxing { protected: Reader() {} public: - virtual Ref decode(Ref image) = 0; + Ref decode(Ref image); + virtual Ref decode(Ref image, DecodeHints hints) = 0; virtual ~Reader(); }; diff --git a/cpp/core/src/zxing/datamatrix/DataMatrixReader.cpp b/cpp/core/src/zxing/datamatrix/DataMatrixReader.cpp index 8b00161ef..74a1b2c63 100644 --- a/cpp/core/src/zxing/datamatrix/DataMatrixReader.cpp +++ b/cpp/core/src/zxing/datamatrix/DataMatrixReader.cpp @@ -31,7 +31,7 @@ DataMatrixReader::DataMatrixReader() : decoder_() { } -Ref DataMatrixReader::decode(Ref image) { +Ref DataMatrixReader::decode(Ref image, DecodeHints hints) { #ifdef DEBUG cout << "decoding image " << image.object_ << ":\n" << flush; #endif diff --git a/cpp/core/src/zxing/datamatrix/DataMatrixReader.h b/cpp/core/src/zxing/datamatrix/DataMatrixReader.h index 4d621c8d9..e266739c1 100644 --- a/cpp/core/src/zxing/datamatrix/DataMatrixReader.h +++ b/cpp/core/src/zxing/datamatrix/DataMatrixReader.h @@ -22,6 +22,7 @@ */ #include +#include #include namespace zxing { @@ -33,7 +34,7 @@ private: public: DataMatrixReader(); - virtual Ref decode(Ref image); + virtual Ref decode(Ref image, DecodeHints hints); virtual ~DataMatrixReader(); }; diff --git a/cpp/core/src/zxing/oned/OneDReader.cpp b/cpp/core/src/zxing/oned/OneDReader.cpp index d3e491691..05f9a9bba 100644 --- a/cpp/core/src/zxing/oned/OneDReader.cpp +++ b/cpp/core/src/zxing/oned/OneDReader.cpp @@ -31,14 +31,16 @@ namespace zxing { OneDReader::OneDReader() { } - Ref OneDReader::decode(Ref image) { - try { - return doDecode(image); + Ref OneDReader::decode(Ref image, DecodeHints hints) { + + try { + return doDecode(image, hints); }catch (ReaderException re) { - if (false /*tryHarder && image.isRotateSupported()*/) { + if (hints.getTryHarder() && image->isRotateSupported()) { + + Ref rotatedImage(image->rotateCounterClockwise()); + Ref result(doDecode(rotatedImage, hints)); /* - BinaryBitmap rotatedImage = image.rotateCounterClockwise(); - Result result = doDecode(rotatedImage, hints); // Record that we found it rotated 90 degrees CCW / 270 degrees CW Hashtable metadata = result.getResultMetadata(); int orientation = 270; @@ -48,34 +50,32 @@ namespace zxing { ((Integer) metadata.get(ResultMetadataType.ORIENTATION)).intValue()) % 360; } result.putMetadata(ResultMetadataType.ORIENTATION, new Integer(orientation)); - // Update result points - ResultPoint[] points = result.getResultPoints(); - int height = rotatedImage.getHeight(); - for (int i = 0; i < points.length; i++) { - points[i] = new ResultPoint(height - points[i].getY() - 1, points[i].getX()); + */ + // Update result points + std::vector > points (result->getResultPoints()); + int height = rotatedImage->getHeight(); + for (size_t i = 0; i < points.size(); i++) { + points[i].reset(new OneDResultPoint(height - points[i]->getY() - 1, points[i]->getX())); } return result; - */ } else { throw re; } } } - Ref OneDReader::doDecode(Ref image){ + Ref OneDReader::doDecode(Ref image, DecodeHints hints){ int width = image->getWidth(); int height = image->getHeight(); Ref row(new BitArray(width)); -// BitArray row = new BitArray(width); - int middle = height >> 1; - bool tryHarder = true;//hints != null && hints.containsKey(DecodeHintType.TRY_HARDER); - int rowStep = (int)fmax(1, height >> (tryHarder ? 7 : 4)); + bool tryHarder = hints.getTryHarder(); + int rowStep = (int)fmax(1, height >> (tryHarder ? 8 : 5)); int maxLines; if (tryHarder) { maxLines = height; // Look at the whole image, not just the center } else { - maxLines = 9; // Nine rows spaced 1/16 apart is roughly the middle half of the image + maxLines = 15; // 15 rows spaced 1/32 apart is roughly the middle half of the image } for (int x = 0; x < maxLines; x++) { @@ -95,7 +95,7 @@ namespace zxing { }catch (ReaderException re) { continue; }catch (IllegalArgumentException re) { - continue; + continue; } // While we have the image data in a BitArray, it's fairly cheap to reverse it in place to @@ -112,17 +112,18 @@ namespace zxing { // // But it was upside down, so note that // result.putMetadata(ResultMetadataType.ORIENTATION, new Integer(180)); // // And remember to flip the result points horizontally. - std::vector > points(result->getResultPoints()); - if (points.size() == 2) { - Ref pointZero(new OneDResultPoint(width - points[0]->getX() - 1, points[0]->getY())); - points[0] = pointZero; + std::vector > points(result->getResultPoints()); + // if there's exactly two points (which there should be), flip the x coordinate + // if there's not exactly 2, I don't know what do do with it + if (points.size() == 2) { + Ref pointZero(new OneDResultPoint(width - points[0]->getX() - 1, points[0]->getY())); + points[0] = pointZero; - Ref pointOne(new OneDResultPoint(width - points[1]->getX() - 1, points[1]->getY())); - points[1] = pointOne; + Ref pointOne(new OneDResultPoint(width - points[1]->getX() - 1, points[1]->getY())); + points[1] = pointOne; result.reset(new Result(result->getText(),result->getRawBytes(),points,result->getBarcodeFormat())); - } - + } } return result; } catch (ReaderException re) { diff --git a/cpp/core/src/zxing/oned/OneDReader.h b/cpp/core/src/zxing/oned/OneDReader.h index bb3b64979..e246ef3c7 100644 --- a/cpp/core/src/zxing/oned/OneDReader.h +++ b/cpp/core/src/zxing/oned/OneDReader.h @@ -23,6 +23,7 @@ #include #include #include +#include namespace zxing { namespace oned { @@ -30,12 +31,12 @@ namespace zxing { private: static const int INTEGER_MATH_SHIFT = 8; - Ref doDecode(Ref image); + Ref doDecode(Ref image, DecodeHints hints); public: static const int PATTERN_MATCH_RESULT_SCALE_FACTOR = 1 << INTEGER_MATH_SHIFT; OneDReader(); - virtual Ref decode(Ref image); + virtual Ref decode(Ref image, DecodeHints hints); virtual Ref decodeRow(int rowNumber, Ref row) = 0; static unsigned int patternMatchVariance(int counters[], int countersSize, const int pattern[], int maxIndividualVariance); diff --git a/cpp/core/src/zxing/oned/UPCAReader.cpp b/cpp/core/src/zxing/oned/UPCAReader.cpp index cb2fcb5e3..3638318fd 100644 --- a/cpp/core/src/zxing/oned/UPCAReader.cpp +++ b/cpp/core/src/zxing/oned/UPCAReader.cpp @@ -32,8 +32,8 @@ namespace zxing { Ref UPCAReader::decodeRow(int rowNumber, Ref row, int startGuardRange[]){ return maybeReturnResult(ean13Reader.decodeRow(rowNumber, row, startGuardRange)); } - Ref UPCAReader::decode(Ref image){ - return maybeReturnResult(ean13Reader.decode(image)); + Ref UPCAReader::decode(Ref image, DecodeHints hints){ + return maybeReturnResult(ean13Reader.decode(image, hints)); } int UPCAReader::decodeMiddle(Ref row, int startRange[], int startRangeLen, std::string& resultString){ diff --git a/cpp/core/src/zxing/oned/UPCAReader.h b/cpp/core/src/zxing/oned/UPCAReader.h index 85422072c..d225d17df 100644 --- a/cpp/core/src/zxing/oned/UPCAReader.h +++ b/cpp/core/src/zxing/oned/UPCAReader.h @@ -19,6 +19,7 @@ */ #include +#include namespace zxing { namespace oned { @@ -35,7 +36,7 @@ namespace zxing { Ref decodeRow(int rowNumber, Ref row); //throws ReaderException Ref decodeRow(int rowNumber, Ref row, int startGuardRange[]); //throws ReaderException - Ref decode(Ref image); + Ref decode(Ref image, DecodeHints hints); BarcodeFormat getBarcodeFormat(); }; diff --git a/cpp/core/src/zxing/qrcode/QRCodeReader.cpp b/cpp/core/src/zxing/qrcode/QRCodeReader.cpp index 656b6f9bf..da116441a 100644 --- a/cpp/core/src/zxing/qrcode/QRCodeReader.cpp +++ b/cpp/core/src/zxing/qrcode/QRCodeReader.cpp @@ -30,8 +30,8 @@ namespace zxing { QRCodeReader::QRCodeReader() :decoder_() { } - - Ref QRCodeReader::decode(Ref image) { + //TODO: see if any of the other files in the qrcode tree need tryHarder + Ref QRCodeReader::decode(Ref image, DecodeHints hints) { #ifdef DEBUG cout << "decoding image " << image.object_ << ":\n" << flush; #endif diff --git a/cpp/core/src/zxing/qrcode/QRCodeReader.h b/cpp/core/src/zxing/qrcode/QRCodeReader.h index 8257c7a39..0c5ca8fee 100644 --- a/cpp/core/src/zxing/qrcode/QRCodeReader.h +++ b/cpp/core/src/zxing/qrcode/QRCodeReader.h @@ -23,6 +23,7 @@ #include #include +#include namespace zxing { namespace qrcode { @@ -33,7 +34,7 @@ namespace zxing { public: QRCodeReader(); - virtual Ref decode(Ref image); + virtual Ref decode(Ref image, DecodeHints hints); virtual ~QRCodeReader(); };