mirror of
https://github.com/zxing/zxing.git
synced 2025-03-05 20:48:51 -08:00
minor C++ optimizations
This is mostly just inlining a couple of getter/setter pairs that are in the tightest loops. The only semantic change is making the retain() and release() methods of the reference counted objects non-virtual, which allows them to be inlined. See also http://groups.google.com/group/zxing/browse_thread/thread/6ea93730a7093199 git-svn-id: https://zxing.googlecode.com/svn/trunk@1974 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
parent
70190f7805
commit
31cb655de2
|
@ -59,14 +59,6 @@ size_t BitArray::getSize() {
|
|||
return size_;
|
||||
}
|
||||
|
||||
bool BitArray::get(size_t i) {
|
||||
return (bits_[i >> logBits_] & (1 << (i & bitsMask_))) != 0;
|
||||
}
|
||||
|
||||
void BitArray::set(size_t i) {
|
||||
bits_[i >> logBits_] |= 1 << (i & bitsMask_);
|
||||
}
|
||||
|
||||
void BitArray::setBulk(size_t i, unsigned int newBits) {
|
||||
bits_[i >> logBits_] = newBits;
|
||||
}
|
||||
|
|
|
@ -42,8 +42,15 @@ public:
|
|||
BitArray(size_t size);
|
||||
~BitArray();
|
||||
size_t getSize();
|
||||
bool get(size_t i);
|
||||
void set(size_t i);
|
||||
|
||||
bool get(size_t i) {
|
||||
return (bits_[i >> logBits_] & (1 << (i & bitsMask_))) != 0;
|
||||
}
|
||||
|
||||
void set(size_t i) {
|
||||
bits_[i >> logBits_] |= 1 << (i & bitsMask_);
|
||||
}
|
||||
|
||||
void setBulk(size_t i, unsigned int newBits);
|
||||
void setRange(int start, int end);
|
||||
void clear();
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
using std::numeric_limits;
|
||||
using std::ostream;
|
||||
using std::ostringstream;
|
||||
|
||||
|
@ -34,21 +33,9 @@ using zxing::BitArray;
|
|||
using zxing::Ref;
|
||||
|
||||
namespace {
|
||||
unsigned int logDigits(unsigned digits) {
|
||||
unsigned log = 0;
|
||||
unsigned val = 1;
|
||||
while (val < digits) {
|
||||
log++;
|
||||
val <<= 1;
|
||||
}
|
||||
return log;
|
||||
}
|
||||
|
||||
const unsigned int bitsPerWord = numeric_limits<unsigned int>::digits;
|
||||
const unsigned int logBits = logDigits(bitsPerWord);
|
||||
const unsigned int bitsMask = (1 << logBits) - 1;
|
||||
|
||||
size_t wordsForSize(size_t width, size_t height) {
|
||||
size_t wordsForSize(size_t width,
|
||||
size_t height,
|
||||
unsigned int logBits) {
|
||||
size_t bits = width * height;
|
||||
int arraySize = bits >> logBits;
|
||||
if (bits - (arraySize << logBits) != 0) {
|
||||
|
@ -60,16 +47,14 @@ namespace {
|
|||
|
||||
BitMatrix::BitMatrix(size_t dimension) :
|
||||
width_(dimension), height_(dimension), words_(0), bits_(NULL) {
|
||||
|
||||
words_ = wordsForSize(width_, height_);
|
||||
words_ = wordsForSize(width_, height_, logBits);
|
||||
bits_ = new unsigned int[words_];
|
||||
clear();
|
||||
}
|
||||
|
||||
BitMatrix::BitMatrix(size_t width, size_t height) :
|
||||
width_(width), height_(height), words_(0), bits_(NULL) {
|
||||
|
||||
words_ = wordsForSize(width_, height_);
|
||||
words_ = wordsForSize(width_, height_, logBits);
|
||||
bits_ = new unsigned int[words_];
|
||||
clear();
|
||||
}
|
||||
|
@ -79,16 +64,6 @@ BitMatrix::~BitMatrix() {
|
|||
}
|
||||
|
||||
|
||||
bool BitMatrix::get(size_t x, size_t y) const {
|
||||
size_t offset = x + width_ * y;
|
||||
return ((bits_[offset >> logBits] >> (offset & bitsMask)) & 0x01) != 0;
|
||||
}
|
||||
|
||||
void BitMatrix::set(size_t x, size_t y) {
|
||||
size_t offset = x + width_ * y;
|
||||
bits_[offset >> logBits] |= 1 << (offset & bitsMask);
|
||||
}
|
||||
|
||||
void BitMatrix::flip(size_t x, size_t y) {
|
||||
size_t offset = x + width_ * y;
|
||||
bits_[offset >> logBits] ^= 1 << (offset & bitsMask);
|
||||
|
@ -135,7 +110,7 @@ Ref<BitArray> BitMatrix::getRow(int y, Ref<BitArray> row) {
|
|||
size_t lastBit = i < lastWord ? bitsPerWord - 1 : end & bitsMask;
|
||||
unsigned int mask;
|
||||
if (firstBit == 0 && lastBit == logBits) {
|
||||
mask = numeric_limits<unsigned int>::max();
|
||||
mask = std::numeric_limits<unsigned int>::max();
|
||||
} else {
|
||||
mask = 0;
|
||||
for (size_t j = firstBit; j <= lastBit; j++) {
|
||||
|
|
|
@ -34,14 +34,35 @@ private:
|
|||
size_t words_;
|
||||
unsigned int* bits_;
|
||||
|
||||
#define ZX_LOG_DIGITS(digits) \
|
||||
((digits == 8) ? 3 : \
|
||||
((digits == 16) ? 4 : \
|
||||
((digits == 32) ? 5 : \
|
||||
((digits == 64) ? 6 : \
|
||||
((digits == 128) ? 7 : \
|
||||
(-1))))))
|
||||
|
||||
static const unsigned int bitsPerWord =
|
||||
std::numeric_limits<unsigned int>::digits;
|
||||
static const unsigned int logBits = ZX_LOG_DIGITS(bitsPerWord);
|
||||
static const unsigned int bitsMask = (1 << logBits) - 1;
|
||||
|
||||
public:
|
||||
BitMatrix(size_t dimension);
|
||||
BitMatrix(size_t width, size_t height);
|
||||
|
||||
~BitMatrix();
|
||||
// Inlining this does not really improve performance.
|
||||
bool get(size_t x, size_t y) const;
|
||||
void set(size_t x, size_t y);
|
||||
|
||||
bool get(size_t x, size_t y) const {
|
||||
size_t offset = x + width_ * y;
|
||||
return ((bits_[offset >> logBits] >> (offset & bitsMask)) & 0x01) != 0;
|
||||
}
|
||||
|
||||
void set(size_t x, size_t y) {
|
||||
size_t offset = x + width_ * y;
|
||||
bits_[offset >> logBits] |= 1 << (offset & bitsMask);
|
||||
}
|
||||
|
||||
void flip(size_t x, size_t y);
|
||||
void clear();
|
||||
void setRegion(size_t left, size_t top, size_t width, size_t height);
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
*/
|
||||
|
||||
//#define DEBUG_COUNTING
|
||||
//using namespace std;
|
||||
|
||||
#include <iostream>
|
||||
|
||||
|
@ -45,7 +44,7 @@ public:
|
|||
}
|
||||
virtual ~Counted() {
|
||||
}
|
||||
virtual Counted *retain() {
|
||||
Counted *retain() {
|
||||
#ifdef DEBUG_COUNTING
|
||||
cout << "retaining " << typeid(*this).name() << " " << this <<
|
||||
" @ " << count_;
|
||||
|
@ -56,7 +55,7 @@ public:
|
|||
#endif
|
||||
return this;
|
||||
}
|
||||
virtual void release() {
|
||||
void release() {
|
||||
#ifdef DEBUG_COUNTING
|
||||
cout << "releasing " << typeid(*this).name() << " " << this <<
|
||||
" @ " << count_;
|
||||
|
|
|
@ -44,19 +44,22 @@ HybridBinarizer::~HybridBinarizer() {
|
|||
}
|
||||
|
||||
|
||||
Ref<Binarizer> HybridBinarizer::createBinarizer(Ref<LuminanceSource> source) {
|
||||
Ref<Binarizer>
|
||||
HybridBinarizer::createBinarizer(Ref<LuminanceSource> source) {
|
||||
return Ref<Binarizer> (new HybridBinarizer(source));
|
||||
}
|
||||
|
||||
Ref<BitMatrix> HybridBinarizer::getBlackMatrix() {
|
||||
// Calculates the final BitMatrix once for all requests. This could be called once from the
|
||||
// constructor instead, but there are some advantages to doing it lazily, such as making
|
||||
// profiling easier, and not doing heavy lifting when callers don't expect it.
|
||||
// Calculates the final BitMatrix once for all requests. This could
|
||||
// be called once from the constructor instead, but there are some
|
||||
// advantages to doing it lazily, such as making profiling easier,
|
||||
// and not doing heavy lifting when callers don't expect it.
|
||||
if (matrix_) {
|
||||
return matrix_;
|
||||
}
|
||||
LuminanceSource& source = *getLuminanceSource();
|
||||
if (source.getWidth() >= MINIMUM_DIMENSION && source.getHeight() >= MINIMUM_DIMENSION) {
|
||||
if (source.getWidth() >= MINIMUM_DIMENSION &&
|
||||
source.getHeight() >= MINIMUM_DIMENSION) {
|
||||
unsigned char* luminances = source.getMatrix();
|
||||
int width = source.getWidth();
|
||||
int height = source.getHeight();
|
||||
|
@ -68,14 +71,22 @@ Ref<BitMatrix> HybridBinarizer::getBlackMatrix() {
|
|||
if ((height & BLOCK_SIZE_MASK) != 0) {
|
||||
subHeight++;
|
||||
}
|
||||
int* blackPoints = calculateBlackPoints(luminances, subWidth, subHeight, width, height);
|
||||
int* blackPoints =
|
||||
calculateBlackPoints(luminances, subWidth, subHeight, width, height);
|
||||
|
||||
Ref<BitMatrix> newMatrix (new BitMatrix(width, height));
|
||||
calculateThresholdForBlock(luminances, subWidth, subHeight, width, height, blackPoints, newMatrix);
|
||||
calculateThresholdForBlock(luminances,
|
||||
subWidth,
|
||||
subHeight,
|
||||
width,
|
||||
height,
|
||||
blackPoints,
|
||||
newMatrix);
|
||||
matrix_ = newMatrix;
|
||||
|
||||
// N.B.: these deletes are inadequate if anything between the new and this point can throw.
|
||||
// As of this writing, it doesn't look like they do.
|
||||
// N.B.: these deletes are inadequate if anything between the new
|
||||
// and this point can throw. As of this writing, it doesn't look
|
||||
// like they do.
|
||||
|
||||
delete [] blackPoints;
|
||||
delete [] luminances;
|
||||
|
@ -86,8 +97,14 @@ Ref<BitMatrix> HybridBinarizer::getBlackMatrix() {
|
|||
return matrix_;
|
||||
}
|
||||
|
||||
void HybridBinarizer::calculateThresholdForBlock(unsigned char* luminances, int subWidth, int subHeight,
|
||||
int width, int height, int blackPoints[], Ref<BitMatrix> matrix) {
|
||||
void
|
||||
HybridBinarizer::calculateThresholdForBlock(unsigned char* luminances,
|
||||
int subWidth,
|
||||
int subHeight,
|
||||
int width,
|
||||
int height,
|
||||
int blackPoints[],
|
||||
Ref<BitMatrix> const& matrix) {
|
||||
for (int y = 0; y < subHeight; y++) {
|
||||
int yoffset = y << BLOCK_SIZE_POWER;
|
||||
if (yoffset + BLOCK_SIZE >= height) {
|
||||
|
@ -117,8 +134,12 @@ void HybridBinarizer::calculateThresholdForBlock(unsigned char* luminances, int
|
|||
}
|
||||
}
|
||||
|
||||
void HybridBinarizer::threshold8x8Block(unsigned char* luminances, int xoffset, int yoffset, int threshold,
|
||||
int stride, Ref<BitMatrix> matrix) {
|
||||
void HybridBinarizer::threshold8x8Block(unsigned char* luminances,
|
||||
int xoffset,
|
||||
int yoffset,
|
||||
int threshold,
|
||||
int stride,
|
||||
Ref<BitMatrix> const& matrix) {
|
||||
for (int y = 0, offset = yoffset * stride + xoffset;
|
||||
y < BLOCK_SIZE;
|
||||
y++, offset += stride) {
|
||||
|
|
|
@ -41,15 +41,28 @@ namespace zxing {
|
|||
virtual Ref<BitMatrix> getBlackMatrix();
|
||||
Ref<Binarizer> createBinarizer(Ref<LuminanceSource> source);
|
||||
private:
|
||||
// We'll be using one-D arrays because C++ can't dynamically allocate 2D arrays
|
||||
int* calculateBlackPoints(unsigned char* luminances, int subWidth, int subHeight,
|
||||
int width, int height);
|
||||
void calculateThresholdForBlock(unsigned char* luminances, int subWidth, int subHeight,
|
||||
int width, int height, int blackPoints[], Ref<BitMatrix> matrix);
|
||||
void threshold8x8Block(unsigned char* luminances, int xoffset, int yoffset, int threshold,
|
||||
int stride, Ref<BitMatrix> matrix);
|
||||
// We'll be using one-D arrays because C++ can't dynamically allocate 2D
|
||||
// arrays
|
||||
int* calculateBlackPoints(unsigned char* luminances,
|
||||
int subWidth,
|
||||
int subHeight,
|
||||
int width,
|
||||
int height);
|
||||
void calculateThresholdForBlock(unsigned char* luminances,
|
||||
int subWidth,
|
||||
int subHeight,
|
||||
int width,
|
||||
int height,
|
||||
int blackPoints[],
|
||||
Ref<BitMatrix> const& matrix);
|
||||
void threshold8x8Block(unsigned char* luminances,
|
||||
int xoffset,
|
||||
int yoffset,
|
||||
int threshold,
|
||||
int stride,
|
||||
Ref<BitMatrix> const& matrix);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* GLOBALHISTOGRAMBINARIZER_H_ */
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue