C++ Port:

- Fixed to be able to build for the Symbian emulator (variable-sized arrays cannot be created on the stack).
- Fixed bug only present on Symbian phones that prevented the alignment patterns from being found (the Symbian implementation of valarray does not initialize its values to 0, unless it is explicitly specified as the default value).
- Fixed an include.

git-svn-id: https://zxing.googlecode.com/svn/trunk@1100 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
ralf.kistner@gmail.com 2009-11-05 22:11:15 +00:00
parent d2fea027ec
commit 4c51e618e3
4 changed files with 274 additions and 259 deletions

View file

@ -1,42 +1,42 @@
Decider('MD5') Decider('MD5')
env = Environment() env = Environment()
debug = True debug = True
compile_options = {} compile_options = {}
flags = [] flags = []
if debug: if debug:
#compile_options['CPPDEFINES'] = "-DDEBUG" #compile_options['CPPDEFINES'] = "-DDEBUG"
flags.append("-O0 -g3 -Wall") flags.append("-O0 -g3 -Wall")
compile_options['CXXFLAGS'] = ' '.join(flags) compile_options['CXXFLAGS'] = ' '.join(flags)
def all_files(dir, ext='.cpp', level=5): def all_files(dir, ext='.cpp', level=5):
files = [] files = []
for i in range(level): for i in range(1, level):
files += Glob(dir + ('/*' * i) + ext) files += Glob(dir + ('/*' * i) + ext)
return files return files
magick_include = ['/usr/include/ImageMagick/'] magick_include = ['/usr/include/ImageMagick/']
magick_libs = ['Magick++', 'MagickWand', 'MagickCore'] magick_libs = ['Magick++', 'MagickWand', 'MagickCore']
cppunit_libs = ['cppunit'] cppunit_libs = ['cppunit']
zxing_files = all_files('core/src') zxing_files = all_files('core/src')
zxing_include = ['core/src'] zxing_include = ['core/src']
zxing_libs = env.Library('zxing', source=zxing_files, CPPPATH=zxing_include, **compile_options) zxing_libs = env.Library('zxing', source=zxing_files, CPPPATH=zxing_include, **compile_options)
app_files = all_files('magick/src') app_files = all_files('magick/src')
app_executable = env.Program('zxing', app_files, CPPPATH=magick_include + zxing_include, LIBS=magick_libs + zxing_libs, **compile_options) app_executable = env.Program('zxing', app_files, CPPPATH=magick_include + zxing_include, LIBS=magick_libs + zxing_libs, **compile_options)
test_files = all_files('core/tests/src') test_files = all_files('core/tests/src')
test_executable = env.Program('testrunner', test_files, CPPPATH=zxing_include, LIBS=zxing_libs + cppunit_libs, **compile_options) test_executable = env.Program('testrunner', test_files, CPPPATH=zxing_include, LIBS=zxing_libs + cppunit_libs, **compile_options)
Alias('lib', zxing_libs) Alias('lib', zxing_libs)
Alias('tests', test_executable) Alias('tests', test_executable)
Alias('zxing', app_executable) Alias('zxing', app_executable)

View file

@ -1,209 +1,209 @@
#ifndef __ARRAY_H__ #ifndef __ARRAY_H__
#define __ARRAY_H__ #define __ARRAY_H__
/* /*
* Array.h * Array.h
* zxing * zxing
* *
* Created by Christian Brunschen on 07/05/2008. * Created by Christian Brunschen on 07/05/2008.
* Copyright 2008 Google UK. All rights reserved. * Copyright 2008 Google UK. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
#include <valarray> #include <valarray>
#include <cstdarg> #include <cstdarg>
#ifdef DEBUG_COUNTING #ifdef DEBUG_COUNTING
#include <iostream> #include <iostream>
#include <typeinfo> #include <typeinfo>
#endif #endif
#include "Counted.h" #include <zxing/common/Counted.h>
namespace zxing { namespace zxing {
template<typename T> class Array : public Counted { template<typename T> class Array : public Counted {
protected: protected:
public: public:
std::valarray<T> values_; std::valarray<T> values_;
Array(size_t n) : Array(size_t n) :
Counted(), values_(T(), n) { Counted(), values_(T(), n) {
} }
Array(T *ts, size_t n) : Array(T *ts, size_t n) :
Counted(), values_(ts, n) { Counted(), values_(ts, n) {
} }
Array(T v, size_t n) : Array(T v, size_t n) :
Counted(), values_(v, n) { Counted(), values_(v, n) {
} }
Array(std::valarray<T> &v) : Array(std::valarray<T> &v) :
Counted(), values_(v) { Counted(), values_(v) {
} }
Array(Array<T> &other) : Array(Array<T> &other) :
Counted(), values_(other.values_) { Counted(), values_(other.values_) {
} }
Array(Array<T> *other) : Array(Array<T> *other) :
Counted(), values_(other->values_) { Counted(), values_(other->values_) {
} }
virtual ~Array() { virtual ~Array() {
} }
Array<T>& operator=(const Array<T> &other) { Array<T>& operator=(const Array<T> &other) {
#ifdef DEBUG_COUNTING #ifdef DEBUG_COUNTING
cout << "assigning values from Array " << &other << " to this Array " << this << ", "; cout << "assigning values from Array " << &other << " to this Array " << this << ", ";
#endif #endif
values_ = other.values_; values_ = other.values_;
#ifdef DEBUG_COUNTING #ifdef DEBUG_COUNTING
cout << "new size = " << values_.size() << "\n"; cout << "new size = " << values_.size() << "\n";
#endif #endif
return *this; return *this;
} }
Array<T>& operator=(const std::valarray<T> &array) { Array<T>& operator=(const std::valarray<T> &array) {
#ifdef DEBUG_COUNTING #ifdef DEBUG_COUNTING
cout << "assigning values from Array " << &array << " to this Array " << this << ", "; cout << "assigning values from Array " << &array << " to this Array " << this << ", ";
#endif #endif
values_ = array; values_ = array;
#ifdef DEBUG_COUNTING #ifdef DEBUG_COUNTING
cout << "new size = " << values_.size() << "\n"; cout << "new size = " << values_.size() << "\n";
#endif #endif
return *this; return *this;
} }
T operator[](size_t i) const { T operator[](size_t i) const {
return values_[i]; return values_[i];
} }
T& operator[](size_t i) { T& operator[](size_t i) {
return values_[i]; return values_[i];
} }
size_t size() const { size_t size() const {
return values_.size(); return values_.size();
} }
std::valarray<T> values() const { std::valarray<T> values() const {
return values_; return values_;
} }
std::valarray<T>& values() { std::valarray<T>& values() {
return values_; return values_;
} }
}; };
template<typename T> class ArrayRef { template<typename T> class ArrayRef {
private: private:
public: public:
Array<T> *array_; Array<T> *array_;
ArrayRef() : ArrayRef() :
array_(0) { array_(0) {
#ifdef DEBUG_COUNTING #ifdef DEBUG_COUNTING
cout << "instantiating empty ArrayRef " << this << "\n"; cout << "instantiating empty ArrayRef " << this << "\n";
#endif #endif
} }
ArrayRef(size_t n) : ArrayRef(size_t n) :
array_(0) { array_(0) {
#ifdef DEBUG_COUNTING #ifdef DEBUG_COUNTING
cout << "instantiating ArrayRef " << this << "with size " << n << "\n"; cout << "instantiating ArrayRef " << this << "with size " << n << "\n";
#endif #endif
reset(new Array<T> (n)); reset(new Array<T> (n));
} }
ArrayRef(T *ts, size_t n) : ArrayRef(T *ts, size_t n) :
array_(0) { array_(0) {
#ifdef DEBUG_COUNTING #ifdef DEBUG_COUNTING
cout << "instantiating ArrayRef " << this << "with " << n << " elements at " << (void *)ts << "\n"; cout << "instantiating ArrayRef " << this << "with " << n << " elements at " << (void *)ts << "\n";
#endif #endif
reset(new Array<T> (ts, n)); reset(new Array<T> (ts, n));
} }
ArrayRef(Array<T> *a) : ArrayRef(Array<T> *a) :
array_(0) { array_(0) {
#ifdef DEBUG_COUNTING #ifdef DEBUG_COUNTING
cout << "instantiating ArrayRef " << this << " from pointer:\n"; cout << "instantiating ArrayRef " << this << " from pointer:\n";
#endif #endif
reset(a); reset(a);
} }
ArrayRef(const Array<T> &a) : ArrayRef(const Array<T> &a) :
array_(0) { array_(0) {
#ifdef DEBUG_COUNTING #ifdef DEBUG_COUNTING
cout << "instantiating ArrayRef " << this << " from reference to Array " << (void *)&a << ":\n"; cout << "instantiating ArrayRef " << this << " from reference to Array " << (void *)&a << ":\n";
#endif #endif
reset(const_cast<Array<T> *>(&a)); reset(const_cast<Array<T> *>(&a));
} }
ArrayRef(const ArrayRef &other) : ArrayRef(const ArrayRef &other) :
array_(0) { array_(0) {
#ifdef DEBUG_COUNTING #ifdef DEBUG_COUNTING
cout << "instantiating ArrayRef " << this << " from ArrayRef " << &other << ":\n"; cout << "instantiating ArrayRef " << this << " from ArrayRef " << &other << ":\n";
#endif #endif
reset(other.array_); reset(other.array_);
} }
template<class Y> template<class Y>
ArrayRef(const ArrayRef<Y> &other) : ArrayRef(const ArrayRef<Y> &other) :
array_(0) { array_(0) {
#ifdef DEBUG_COUNTING #ifdef DEBUG_COUNTING
cout << "instantiating ArrayRef " << this << " from ArrayRef " << &other << ":\n"; cout << "instantiating ArrayRef " << this << " from ArrayRef " << &other << ":\n";
#endif #endif
reset(static_cast<const Array<T> *>(other.array_)); reset(static_cast<const Array<T> *>(other.array_));
} }
~ArrayRef() { ~ArrayRef() {
#ifdef DEBUG_COUNTING #ifdef DEBUG_COUNTING
cout << "destroying ArrayRef " << this << " with " << (array_ ? typeid(*array_).name() : "NULL") << " " cout << "destroying ArrayRef " << this << " with " << (array_ ? typeid(*array_).name() : "NULL") << " "
<< array_ << "\n"; << array_ << "\n";
#endif #endif
if (array_) { if (array_) {
array_->release(); array_->release();
} }
array_ = 0; array_ = 0;
} }
T operator[](size_t i) const { T operator[](size_t i) const {
return (*array_)[i]; return (*array_)[i];
} }
T& operator[](size_t i) { T& operator[](size_t i) {
return (*array_)[i]; return (*array_)[i];
} }
size_t size() const { size_t size() const {
return array_->size(); return array_->size();
} }
void reset(Array<T> *a) { void reset(Array<T> *a) {
#ifdef DEBUG_COUNTING #ifdef DEBUG_COUNTING
cout << "resetting ArrayRef " << this << " from " << (array_ ? typeid(*array_).name() : "NULL") << " " cout << "resetting ArrayRef " << this << " from " << (array_ ? typeid(*array_).name() : "NULL") << " "
<< array_ << " to " << (a ? typeid(*a).name() : "NULL") << " " << a << "\n"; << array_ << " to " << (a ? typeid(*a).name() : "NULL") << " " << a << "\n";
#endif #endif
if (a) { if (a) {
a->retain(); a->retain();
} }
if (array_) { if (array_) {
array_->release(); array_->release();
} }
array_ = a; array_ = a;
} }
void reset(const ArrayRef<T> &other) { void reset(const ArrayRef<T> &other) {
reset(other.array_); reset(other.array_);
} }
ArrayRef<T>& operator=(const ArrayRef<T> &other) { ArrayRef<T>& operator=(const ArrayRef<T> &other) {
reset(other); reset(other);
return *this; return *this;
} }
ArrayRef<T>& operator=(Array<T> *a) { ArrayRef<T>& operator=(Array<T> *a) {
reset(a); reset(a);
return *this; return *this;
} }
Array<T>& operator*() { Array<T>& operator*() {
return *array_; return *array_;
} }
Array<T>* operator->() { Array<T>* operator->() {
return array_; return array_;
} }
}; };
} // namespace zxing } // namespace zxing
#endif // __ARRAY_H__ #endif // __ARRAY_H__

View file

@ -23,6 +23,11 @@
#include <iconv.h> #include <iconv.h>
// Required for compatibility. TODO: test on Symbian // Required for compatibility. TODO: test on Symbian
#ifdef ZXING_ICONV_CONST
#undef ICONV_CONST
#define ICONV_CONST const
#endif
#ifndef ICONV_CONST #ifndef ICONV_CONST
#define ICONV_CONST /**/ #define ICONV_CONST /**/
#endif #endif
@ -51,8 +56,8 @@ void DecodedBitStreamParser::append(ostream &ost, const unsigned char *bufIn, si
} }
iconv_t cd = iconv_open(UTF8, src); iconv_t cd = iconv_open(UTF8, src);
int maxOut = 4 * nIn + 1; const int maxOut = 4 * nIn + 1;
unsigned char bufOut[maxOut]; unsigned char* bufOut = new unsigned char[maxOut];
ICONV_CONST char *fromPtr = (ICONV_CONST char *)bufIn; ICONV_CONST char *fromPtr = (ICONV_CONST char *)bufIn;
size_t nFrom = nIn; size_t nFrom = nIn;
@ -63,6 +68,7 @@ void DecodedBitStreamParser::append(ostream &ost, const unsigned char *bufIn, si
size_t oneway = iconv(cd, &fromPtr, &nFrom, &toPtr, &nTo); size_t oneway = iconv(cd, &fromPtr, &nFrom, &toPtr, &nTo);
if (oneway == (size_t)(-1)) { if (oneway == (size_t)(-1)) {
iconv_close(cd); iconv_close(cd);
delete[] bufOut;
throw ReaderException("error converting characters"); throw ReaderException("error converting characters");
} }
} }
@ -72,13 +78,14 @@ void DecodedBitStreamParser::append(ostream &ost, const unsigned char *bufIn, si
bufOut[nResult] = '\0'; bufOut[nResult] = '\0';
ost << bufOut; ost << bufOut;
delete[] bufOut;
} }
void DecodedBitStreamParser::decodeKanjiSegment(Ref<BitSource> bits, ostringstream &result, int count) { void DecodedBitStreamParser::decodeKanjiSegment(Ref<BitSource> bits, ostringstream &result, int count) {
// Each character will require 2 bytes. Read the characters as 2-byte pairs // Each character will require 2 bytes. Read the characters as 2-byte pairs
// and decode as Shift_JIS afterwards // and decode as Shift_JIS afterwards
size_t nBytes = 2 * count; size_t nBytes = 2 * count;
unsigned char buffer[nBytes]; unsigned char* buffer = new unsigned char[nBytes];
int offset = 0; int offset = 0;
while (count > 0) { while (count > 0) {
// Each 13 bits encodes a 2-byte character // Each 13 bits encodes a 2-byte character
@ -99,14 +106,16 @@ void DecodedBitStreamParser::decodeKanjiSegment(Ref<BitSource> bits, ostringstre
} }
append(result, buffer, nBytes, SHIFT_JIS); append(result, buffer, nBytes, SHIFT_JIS);
delete[] buffer;
} }
void DecodedBitStreamParser::decodeByteSegment(Ref<BitSource> bits, ostringstream &result, int count) { void DecodedBitStreamParser::decodeByteSegment(Ref<BitSource> bits, ostringstream &result, int count) {
int nBytes = count; int nBytes = count;
unsigned char readBytes[nBytes]; unsigned char* readBytes = new unsigned char[nBytes];
if (count << 3 > bits->available()) { if (count << 3 > bits->available()) {
ostringstream s; ostringstream s;
s << "Count too large: " << count; s << "Count too large: " << count;
delete[] readBytes;
throw ReaderException(s.str().c_str()); throw ReaderException(s.str().c_str());
} }
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
@ -119,11 +128,12 @@ void DecodedBitStreamParser::decodeByteSegment(Ref<BitSource> bits, ostringstrea
// give a hint. // give a hint.
const char *encoding = guessEncoding(readBytes, nBytes); const char *encoding = guessEncoding(readBytes, nBytes);
append(result, readBytes, nBytes, encoding); append(result, readBytes, nBytes, encoding);
delete[] readBytes;
} }
void DecodedBitStreamParser::decodeNumericSegment(Ref<BitSource> bits, ostringstream &result, int count) { void DecodedBitStreamParser::decodeNumericSegment(Ref<BitSource> bits, ostringstream &result, int count) {
int nBytes = count; int nBytes = count;
unsigned char bytes[nBytes]; unsigned char* bytes = new unsigned char[nBytes];
int i = 0; int i = 0;
// Read three digits at a time // Read three digits at a time
while (count >= 3) { while (count >= 3) {
@ -132,6 +142,7 @@ void DecodedBitStreamParser::decodeNumericSegment(Ref<BitSource> bits, ostringst
if (threeDigitsBits >= 1000) { if (threeDigitsBits >= 1000) {
ostringstream s; ostringstream s;
s << "Illegal value for 3-digit unit: " << threeDigitsBits; s << "Illegal value for 3-digit unit: " << threeDigitsBits;
delete[] bytes;
throw ReaderException(s.str().c_str()); throw ReaderException(s.str().c_str());
} }
bytes[i++] = ALPHANUMERIC_CHARS[threeDigitsBits / 100]; bytes[i++] = ALPHANUMERIC_CHARS[threeDigitsBits / 100];
@ -145,6 +156,7 @@ void DecodedBitStreamParser::decodeNumericSegment(Ref<BitSource> bits, ostringst
if (twoDigitsBits >= 100) { if (twoDigitsBits >= 100) {
ostringstream s; ostringstream s;
s << "Illegal value for 2-digit unit: " << twoDigitsBits; s << "Illegal value for 2-digit unit: " << twoDigitsBits;
delete[] bytes;
throw ReaderException(s.str().c_str()); throw ReaderException(s.str().c_str());
} }
bytes[i++] = ALPHANUMERIC_CHARS[twoDigitsBits / 10]; bytes[i++] = ALPHANUMERIC_CHARS[twoDigitsBits / 10];
@ -155,16 +167,18 @@ void DecodedBitStreamParser::decodeNumericSegment(Ref<BitSource> bits, ostringst
if (digitBits >= 10) { if (digitBits >= 10) {
ostringstream s; ostringstream s;
s << "Illegal value for digit unit: " << digitBits; s << "Illegal value for digit unit: " << digitBits;
delete[] bytes;
throw ReaderException(s.str().c_str()); throw ReaderException(s.str().c_str());
} }
bytes[i++] = ALPHANUMERIC_CHARS[digitBits]; bytes[i++] = ALPHANUMERIC_CHARS[digitBits];
} }
append(result, bytes, nBytes, ASCII); append(result, bytes, nBytes, ASCII);
delete[] bytes;
} }
void DecodedBitStreamParser::decodeAlphanumericSegment(Ref<BitSource> bits, ostringstream &result, int count) { void DecodedBitStreamParser::decodeAlphanumericSegment(Ref<BitSource> bits, ostringstream &result, int count) {
int nBytes = count; int nBytes = count;
unsigned char bytes[nBytes]; unsigned char* bytes = new unsigned char[nBytes];
int i = 0; int i = 0;
// Read two characters at a time // Read two characters at a time
while (count > 1) { while (count > 1) {
@ -177,6 +191,7 @@ void DecodedBitStreamParser::decodeAlphanumericSegment(Ref<BitSource> bits, ostr
bytes[i++] = ALPHANUMERIC_CHARS[bits->readBits(6)]; bytes[i++] = ALPHANUMERIC_CHARS[bits->readBits(6)];
} }
append(result, bytes, nBytes, ASCII); append(result, bytes, nBytes, ASCII);
delete[] bytes;
} }
const char * const char *

View file

@ -46,7 +46,7 @@ bool AlignmentPatternFinder::foundPatternCross(valarray<int> &stateCount) {
float AlignmentPatternFinder::crossCheckVertical(size_t startI, size_t centerJ, int maxCount, float AlignmentPatternFinder::crossCheckVertical(size_t startI, size_t centerJ, int maxCount,
int originalStateCountTotal) { int originalStateCountTotal) {
int maxI = image_->getHeight(); int maxI = image_->getHeight();
valarray<int> stateCount(3); valarray<int> stateCount(0, 3);
// Start counting up from center // Start counting up from center
@ -136,7 +136,7 @@ Ref<AlignmentPattern> AlignmentPatternFinder::find() {
// Ref<BitArray> luminanceRow(new BitArray(width_)); // Ref<BitArray> luminanceRow(new BitArray(width_));
// We are looking for black/white/black modules in 1:1:1 ratio; // We are looking for black/white/black modules in 1:1:1 ratio;
// this tracks the number of black/white/black modules seen so far // this tracks the number of black/white/black modules seen so far
valarray<int> stateCount(3); valarray<int> stateCount(0, 3);
for (size_t iGen = 0; iGen < height_; iGen++) { for (size_t iGen = 0; iGen < height_; iGen++) {
// Search from middle outwards // Search from middle outwards
size_t i = middleI + ((iGen & 0x01) == 0 ? ((iGen + 1) >> 1) : -((iGen + 1) >> 1)); size_t i = middleI + ((iGen & 0x01) == 0 ? ((iGen + 1) >> 1) : -((iGen + 1) >> 1));