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

View file

@ -1,209 +1,209 @@
#ifndef __ARRAY_H__
#define __ARRAY_H__
/*
* Array.h
* zxing
*
* Created by Christian Brunschen on 07/05/2008.
* Copyright 2008 Google UK. 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 <valarray>
#include <cstdarg>
#ifdef DEBUG_COUNTING
#include <iostream>
#include <typeinfo>
#endif
#include "Counted.h"
namespace zxing {
template<typename T> class Array : public Counted {
protected:
public:
std::valarray<T> values_;
Array(size_t n) :
Counted(), values_(T(), n) {
}
Array(T *ts, size_t n) :
Counted(), values_(ts, n) {
}
Array(T v, size_t n) :
Counted(), values_(v, n) {
}
Array(std::valarray<T> &v) :
Counted(), values_(v) {
}
Array(Array<T> &other) :
Counted(), values_(other.values_) {
}
Array(Array<T> *other) :
Counted(), values_(other->values_) {
}
virtual ~Array() {
}
Array<T>& operator=(const Array<T> &other) {
#ifdef DEBUG_COUNTING
cout << "assigning values from Array " << &other << " to this Array " << this << ", ";
#endif
values_ = other.values_;
#ifdef DEBUG_COUNTING
cout << "new size = " << values_.size() << "\n";
#endif
return *this;
}
Array<T>& operator=(const std::valarray<T> &array) {
#ifdef DEBUG_COUNTING
cout << "assigning values from Array " << &array << " to this Array " << this << ", ";
#endif
values_ = array;
#ifdef DEBUG_COUNTING
cout << "new size = " << values_.size() << "\n";
#endif
return *this;
}
T operator[](size_t i) const {
return values_[i];
}
T& operator[](size_t i) {
return values_[i];
}
size_t size() const {
return values_.size();
}
std::valarray<T> values() const {
return values_;
}
std::valarray<T>& values() {
return values_;
}
};
template<typename T> class ArrayRef {
private:
public:
Array<T> *array_;
ArrayRef() :
array_(0) {
#ifdef DEBUG_COUNTING
cout << "instantiating empty ArrayRef " << this << "\n";
#endif
}
ArrayRef(size_t n) :
array_(0) {
#ifdef DEBUG_COUNTING
cout << "instantiating ArrayRef " << this << "with size " << n << "\n";
#endif
reset(new Array<T> (n));
}
ArrayRef(T *ts, size_t n) :
array_(0) {
#ifdef DEBUG_COUNTING
cout << "instantiating ArrayRef " << this << "with " << n << " elements at " << (void *)ts << "\n";
#endif
reset(new Array<T> (ts, n));
}
ArrayRef(Array<T> *a) :
array_(0) {
#ifdef DEBUG_COUNTING
cout << "instantiating ArrayRef " << this << " from pointer:\n";
#endif
reset(a);
}
ArrayRef(const Array<T> &a) :
array_(0) {
#ifdef DEBUG_COUNTING
cout << "instantiating ArrayRef " << this << " from reference to Array " << (void *)&a << ":\n";
#endif
reset(const_cast<Array<T> *>(&a));
}
ArrayRef(const ArrayRef &other) :
array_(0) {
#ifdef DEBUG_COUNTING
cout << "instantiating ArrayRef " << this << " from ArrayRef " << &other << ":\n";
#endif
reset(other.array_);
}
template<class Y>
ArrayRef(const ArrayRef<Y> &other) :
array_(0) {
#ifdef DEBUG_COUNTING
cout << "instantiating ArrayRef " << this << " from ArrayRef " << &other << ":\n";
#endif
reset(static_cast<const Array<T> *>(other.array_));
}
~ArrayRef() {
#ifdef DEBUG_COUNTING
cout << "destroying ArrayRef " << this << " with " << (array_ ? typeid(*array_).name() : "NULL") << " "
<< array_ << "\n";
#endif
if (array_) {
array_->release();
}
array_ = 0;
}
T operator[](size_t i) const {
return (*array_)[i];
}
T& operator[](size_t i) {
return (*array_)[i];
}
size_t size() const {
return array_->size();
}
void reset(Array<T> *a) {
#ifdef DEBUG_COUNTING
cout << "resetting ArrayRef " << this << " from " << (array_ ? typeid(*array_).name() : "NULL") << " "
<< array_ << " to " << (a ? typeid(*a).name() : "NULL") << " " << a << "\n";
#endif
if (a) {
a->retain();
}
if (array_) {
array_->release();
}
array_ = a;
}
void reset(const ArrayRef<T> &other) {
reset(other.array_);
}
ArrayRef<T>& operator=(const ArrayRef<T> &other) {
reset(other);
return *this;
}
ArrayRef<T>& operator=(Array<T> *a) {
reset(a);
return *this;
}
Array<T>& operator*() {
return *array_;
}
Array<T>* operator->() {
return array_;
}
};
} // namespace zxing
#endif // __ARRAY_H__
#ifndef __ARRAY_H__
#define __ARRAY_H__
/*
* Array.h
* zxing
*
* Created by Christian Brunschen on 07/05/2008.
* Copyright 2008 Google UK. 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 <valarray>
#include <cstdarg>
#ifdef DEBUG_COUNTING
#include <iostream>
#include <typeinfo>
#endif
#include <zxing/common/Counted.h>
namespace zxing {
template<typename T> class Array : public Counted {
protected:
public:
std::valarray<T> values_;
Array(size_t n) :
Counted(), values_(T(), n) {
}
Array(T *ts, size_t n) :
Counted(), values_(ts, n) {
}
Array(T v, size_t n) :
Counted(), values_(v, n) {
}
Array(std::valarray<T> &v) :
Counted(), values_(v) {
}
Array(Array<T> &other) :
Counted(), values_(other.values_) {
}
Array(Array<T> *other) :
Counted(), values_(other->values_) {
}
virtual ~Array() {
}
Array<T>& operator=(const Array<T> &other) {
#ifdef DEBUG_COUNTING
cout << "assigning values from Array " << &other << " to this Array " << this << ", ";
#endif
values_ = other.values_;
#ifdef DEBUG_COUNTING
cout << "new size = " << values_.size() << "\n";
#endif
return *this;
}
Array<T>& operator=(const std::valarray<T> &array) {
#ifdef DEBUG_COUNTING
cout << "assigning values from Array " << &array << " to this Array " << this << ", ";
#endif
values_ = array;
#ifdef DEBUG_COUNTING
cout << "new size = " << values_.size() << "\n";
#endif
return *this;
}
T operator[](size_t i) const {
return values_[i];
}
T& operator[](size_t i) {
return values_[i];
}
size_t size() const {
return values_.size();
}
std::valarray<T> values() const {
return values_;
}
std::valarray<T>& values() {
return values_;
}
};
template<typename T> class ArrayRef {
private:
public:
Array<T> *array_;
ArrayRef() :
array_(0) {
#ifdef DEBUG_COUNTING
cout << "instantiating empty ArrayRef " << this << "\n";
#endif
}
ArrayRef(size_t n) :
array_(0) {
#ifdef DEBUG_COUNTING
cout << "instantiating ArrayRef " << this << "with size " << n << "\n";
#endif
reset(new Array<T> (n));
}
ArrayRef(T *ts, size_t n) :
array_(0) {
#ifdef DEBUG_COUNTING
cout << "instantiating ArrayRef " << this << "with " << n << " elements at " << (void *)ts << "\n";
#endif
reset(new Array<T> (ts, n));
}
ArrayRef(Array<T> *a) :
array_(0) {
#ifdef DEBUG_COUNTING
cout << "instantiating ArrayRef " << this << " from pointer:\n";
#endif
reset(a);
}
ArrayRef(const Array<T> &a) :
array_(0) {
#ifdef DEBUG_COUNTING
cout << "instantiating ArrayRef " << this << " from reference to Array " << (void *)&a << ":\n";
#endif
reset(const_cast<Array<T> *>(&a));
}
ArrayRef(const ArrayRef &other) :
array_(0) {
#ifdef DEBUG_COUNTING
cout << "instantiating ArrayRef " << this << " from ArrayRef " << &other << ":\n";
#endif
reset(other.array_);
}
template<class Y>
ArrayRef(const ArrayRef<Y> &other) :
array_(0) {
#ifdef DEBUG_COUNTING
cout << "instantiating ArrayRef " << this << " from ArrayRef " << &other << ":\n";
#endif
reset(static_cast<const Array<T> *>(other.array_));
}
~ArrayRef() {
#ifdef DEBUG_COUNTING
cout << "destroying ArrayRef " << this << " with " << (array_ ? typeid(*array_).name() : "NULL") << " "
<< array_ << "\n";
#endif
if (array_) {
array_->release();
}
array_ = 0;
}
T operator[](size_t i) const {
return (*array_)[i];
}
T& operator[](size_t i) {
return (*array_)[i];
}
size_t size() const {
return array_->size();
}
void reset(Array<T> *a) {
#ifdef DEBUG_COUNTING
cout << "resetting ArrayRef " << this << " from " << (array_ ? typeid(*array_).name() : "NULL") << " "
<< array_ << " to " << (a ? typeid(*a).name() : "NULL") << " " << a << "\n";
#endif
if (a) {
a->retain();
}
if (array_) {
array_->release();
}
array_ = a;
}
void reset(const ArrayRef<T> &other) {
reset(other.array_);
}
ArrayRef<T>& operator=(const ArrayRef<T> &other) {
reset(other);
return *this;
}
ArrayRef<T>& operator=(Array<T> *a) {
reset(a);
return *this;
}
Array<T>& operator*() {
return *array_;
}
Array<T>* operator->() {
return array_;
}
};
} // namespace zxing
#endif // __ARRAY_H__

View file

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