diff --git a/cpp/blackboxtest.sh b/cpp/blackboxtest.sh new file mode 100755 index 000000000..0aba8cda8 --- /dev/null +++ b/cpp/blackboxtest.sh @@ -0,0 +1,35 @@ +#!/bin/sh + +blackboxpath="../core/test/data/blackbox" + +formats="ean13 ean8 upce upca qrcode" + +passed=0; +failed=0; +oldcat=""; + +for format in $formats; do + for pic in `ls ${blackboxpath}/${format}-*/*.{jpg,JPG} 2>/dev/null`; do + category=${pic%/*}; + category=${category##*/}; + if [ "$oldcat" != "$category" ]; then + echo "***** $oldcat finished - $passed of $((passed+failed)) passed **** ***** ******* ***** *********************" + oldcat=$category; + passed=0; + failed=0; + fi + echo -n "Processing: $pic ... " + tmp="${pic%JPG}"; + txt="${tmp%jpg}txt"; + expected=`cat "$txt"`; + actual=`build/zxing . $pic`; + if [ "$expected" == "$actual" ]; then + echo "passed." + passed=$((passed+1)); + else + echo -e "FAILED\n Expected: $expected\n Detected: $actual" + failed=$((failed+1)); + fi + done +done +echo "***** $oldcat finished - $passed of $((passed+failed)) passed **** ***** ******* ***** *********************" diff --git a/cpp/core/src/zxing/Binarizer.cpp b/cpp/core/src/zxing/Binarizer.cpp index 190138291..b1d8b642d 100644 --- a/cpp/core/src/zxing/Binarizer.cpp +++ b/cpp/core/src/zxing/Binarizer.cpp @@ -23,27 +23,13 @@ namespace zxing { - Binarizer::Binarizer(Ref source) : source_(source), array_(NULL), matrix_(NULL), cached_y_(-1) { + Binarizer::Binarizer(Ref source) : source_(source) { } Binarizer::~Binarizer() { } - Ref Binarizer::getBlackRow(int y, Ref row){ - if (array_ == NULL && cached_y_ != y) { - array_ = estimateBlackRow(y, row); - cached_y_ = y; - } - return array_; - } - - Ref Binarizer::getBlackMatrix() { - if (matrix_ == NULL) - matrix_ = estimateBlackMatrix(); - return matrix_; - } - - Ref Binarizer::getSource() { + Ref Binarizer::getLuminanceSource() const { return source_; } diff --git a/cpp/core/src/zxing/Binarizer.h b/cpp/core/src/zxing/Binarizer.h index 694018d72..d510a0c37 100644 --- a/cpp/core/src/zxing/Binarizer.h +++ b/cpp/core/src/zxing/Binarizer.h @@ -32,20 +32,16 @@ namespace zxing { class Binarizer : public Counted { private: Ref source_; - Ref array_; - Ref matrix_; - int cached_y_; public: Binarizer(Ref source); virtual ~Binarizer(); - virtual Ref estimateBlackRow(int y, Ref row)=0; - Ref getBlackRow(int y, Ref row); + virtual Ref getBlackRow(int y, Ref row) = 0; + virtual Ref getBlackMatrix() = 0; - virtual Ref estimateBlackMatrix() = 0; - Ref getBlackMatrix(); - Ref getSource(); + Ref getLuminanceSource() const ; + virtual Ref createBinarizer(Ref source) = 0; }; } diff --git a/cpp/core/src/zxing/BinaryBitmap.cpp b/cpp/core/src/zxing/BinaryBitmap.cpp index ff79b55d5..ad5a8cd67 100644 --- a/cpp/core/src/zxing/BinaryBitmap.cpp +++ b/cpp/core/src/zxing/BinaryBitmap.cpp @@ -23,7 +23,7 @@ namespace zxing { - BinaryBitmap::BinaryBitmap(Ref binarizer) : bits_(NULL), array_bits_(NULL), binarizer_(binarizer), cached_y_(-1) { + BinaryBitmap::BinaryBitmap(Ref binarizer) : binarizer_(binarizer) { } @@ -31,28 +31,23 @@ namespace zxing { } Ref BinaryBitmap::getBlackRow(int y, Ref row) { - if (array_bits_ == NULL && cached_y_ != y) { - array_bits_ = binarizer_->getBlackRow(y, row); - cached_y_ = y; - } - return array_bits_; + return binarizer_->getBlackRow(y, row); } Ref BinaryBitmap::getBlackMatrix() { - if (bits_ == NULL) { - bits_ = binarizer_->getBlackMatrix(); - } - return bits_; - } - int BinaryBitmap::getWidth() { - return getSource()->getWidth(); - } - int BinaryBitmap::getHeight() { - return getSource()->getHeight(); + return binarizer_->getBlackMatrix(); } - Ref BinaryBitmap::getSource() { - return binarizer_->getSource(); + int BinaryBitmap::getWidth() const { + return getLuminanceSource()->getWidth(); + } + + int BinaryBitmap::getHeight() const { + return getLuminanceSource()->getHeight(); + } + + Ref BinaryBitmap::getLuminanceSource() const { + return binarizer_->getLuminanceSource(); } } diff --git a/cpp/core/src/zxing/BinaryBitmap.h b/cpp/core/src/zxing/BinaryBitmap.h index ddea910c1..99505733b 100644 --- a/cpp/core/src/zxing/BinaryBitmap.h +++ b/cpp/core/src/zxing/BinaryBitmap.h @@ -30,8 +30,6 @@ namespace zxing { class BinaryBitmap : public Counted { private: - Ref bits_; - Ref array_bits_; Ref binarizer_; int cached_y_; @@ -41,10 +39,18 @@ namespace zxing { Ref getBlackRow(int y, Ref row); Ref getBlackMatrix(); - Ref getSource(); - int getWidth(); - int getHeight(); + Ref getLuminanceSource() const; + + int getWidth() const; + int getHeight() const; + + bool isRotateSupported() const; + Ref rotateCounterClockwise(); + + bool isCropSupported() const; + Ref crop(int left, int top, int width, int height); + }; } diff --git a/cpp/core/src/zxing/LuminanceSource.cpp b/cpp/core/src/zxing/LuminanceSource.cpp index 6c8ef1e6e..9501d6ec5 100644 --- a/cpp/core/src/zxing/LuminanceSource.cpp +++ b/cpp/core/src/zxing/LuminanceSource.cpp @@ -19,6 +19,7 @@ */ #include +#include namespace zxing { @@ -28,16 +29,32 @@ LuminanceSource::LuminanceSource() { LuminanceSource::~LuminanceSource() { } -unsigned char* LuminanceSource::copyMatrix() { +unsigned char* LuminanceSource::getMatrix() { int width = getWidth(); int height = getHeight(); - unsigned char* matrix = new unsigned char[width*height]; + unsigned char* matrix = new unsigned char[width * height]; + unsigned char* row = new unsigned char[width]; for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - matrix[y*width+x] = getPixel(x, y); - } + getRow(y, row); + memcpy(&matrix[y * width], row, width); } return matrix; } +bool LuminanceSource::isCropSupported() const { + return false; +} + +Ref LuminanceSource::crop(int left, int top, int width, int height) { + throw IllegalArgumentException("This luminance source does not support cropping."); +} + +bool LuminanceSource::isRotateSupported() const { + return false; +} + +Ref LuminanceSource::rotateCounterClockwise() { + throw IllegalArgumentException("This luminance source does not support rotation."); +} + } diff --git a/cpp/core/src/zxing/LuminanceSource.h b/cpp/core/src/zxing/LuminanceSource.h index d39f06f38..00223ca3b 100644 --- a/cpp/core/src/zxing/LuminanceSource.h +++ b/cpp/core/src/zxing/LuminanceSource.h @@ -22,6 +22,7 @@ #define LUMINANCESOURCE_H_ #include +#include namespace zxing { @@ -33,8 +34,15 @@ public: virtual int getWidth() const = 0; virtual int getHeight() const = 0; - virtual unsigned char getPixel(int x, int y) const = 0; - virtual unsigned char* copyMatrix(); + virtual unsigned char* getRow(int y, unsigned char* row) = 0; + virtual unsigned char* getMatrix(); + + virtual bool isCropSupported() const; + virtual Ref crop(int left, int top, int width, int height); + + virtual bool isRotateSupported() const; + virtual Ref rotateCounterClockwise(); + }; } diff --git a/cpp/core/src/zxing/common/GlobalHistogramBinarizer.cpp b/cpp/core/src/zxing/common/GlobalHistogramBinarizer.cpp index 8b99611eb..d30f1a11b 100644 --- a/cpp/core/src/zxing/common/GlobalHistogramBinarizer.cpp +++ b/cpp/core/src/zxing/common/GlobalHistogramBinarizer.cpp @@ -31,7 +31,7 @@ const int LUMINANCE_SHIFT = 8 - LUMINANCE_BITS; const int LUMINANCE_BUCKETS = 1 << LUMINANCE_BITS; GlobalHistogramBinarizer::GlobalHistogramBinarizer(Ref source) : - Binarizer(source) { + Binarizer(source), cached_matrix_(NULL), cached_row_(NULL), cached_row_num_(-1) { } @@ -39,20 +39,26 @@ GlobalHistogramBinarizer::~GlobalHistogramBinarizer() { } -Ref GlobalHistogramBinarizer::estimateBlackRow(int y, - Ref row){ +Ref GlobalHistogramBinarizer::getBlackRow(int y, Ref row) { + + if (row == cached_row_num_) { + return cached_row_; + } + vector histogram(LUMINANCE_BUCKETS, 0); - LuminanceSource& source = *getSource(); + LuminanceSource& source = *getLuminanceSource(); int width = source.getWidth(); if (row == NULL || static_cast(row->getSize()) < width) { row = new BitArray(width); } else { row->clear(); } - + + //TODO(flyashi): cache this instead of allocating and deleting per row + unsigned char* row_pixels = new unsigned char[width]; + getLuminanceSource()->getRow(y,row_pixels); for (int x = 0; x < width; x++) { - unsigned char pixel = source.getPixel(x, y); - histogram[pixel >> LUMINANCE_SHIFT]++; + histogram[row_pixels[x] >> LUMINANCE_SHIFT]++; } int blackPoint = estimate(histogram) << LUMINANCE_SHIFT; @@ -60,10 +66,10 @@ Ref GlobalHistogramBinarizer::estimateBlackRow(int y, Ref array_ref(new BitArray(width)); BitArray& array = *array_ref; - int left = source.getPixel(0, y); - int center = source.getPixel(1, y); + int left = row_pixels[0]; + int center = row_pixels[1]; for (int x = 1; x < width - 1; x++) { - int right = source.getPixel(x+1, y); + int right = row_pixels[x + 1]; // A simple -1 4 -1 box filter with a weight of 2. int luminance = ((center << 2) - left - right) >> 1; if (luminance < blackPoint) { @@ -73,12 +79,21 @@ Ref GlobalHistogramBinarizer::estimateBlackRow(int y, center = right; } + cached_row_ = array_ref; + cached_row_num_ = y; + + delete [] row_pixels; return array_ref; } -Ref GlobalHistogramBinarizer::estimateBlackMatrix() { +Ref GlobalHistogramBinarizer::getBlackMatrix() { + + if (cached_matrix_ != NULL) { + return cached_matrix_; + } + // Faster than working with the reference - LuminanceSource& source = *getSource(); + LuminanceSource& source = *getLuminanceSource(); int width = source.getWidth(); int height = source.getHeight(); vector histogram(LUMINANCE_BUCKETS, 0); @@ -87,14 +102,15 @@ Ref GlobalHistogramBinarizer::estimateBlackMatrix() { // Quickly calculates the histogram by sampling four rows from the image. // This proved to be more robust on the blackbox tests than sampling a // diagonal as we used to do. + unsigned char* row = new unsigned char[width]; for (int y = 1; y < 5; y++) { - int row = height * y / 5; + int rownum = height * y / 5; int right = (width << 2) / 5; int sdf; + getLuminanceSource()->getRow(rownum,row); for (int x = width / 5; x < right; x++) { - unsigned char pixel = source.getPixel(x, row); - histogram[pixel >> LUMINANCE_SHIFT]++; - sdf = histogram[pixel >> LUMINANCE_SHIFT]; + histogram[row[x] >> LUMINANCE_SHIFT]++; + sdf = histogram[row[x] >> LUMINANCE_SHIFT]; } } @@ -103,11 +119,16 @@ Ref GlobalHistogramBinarizer::estimateBlackMatrix() { Ref matrix_ref(new BitMatrix(width, height)); BitMatrix& matrix = *matrix_ref; for (int y = 0; y < height; y++) { + getLuminanceSource()->getRow(y,row); for (int x = 0; x < width; x++) { - if (source.getPixel(x, y) <= blackPoint) + if (row[x] <= blackPoint) matrix.set(x, y); } } + + cached_matrix_ = matrix_ref; + + delete [] row; return matrix_ref; } @@ -179,5 +200,9 @@ int GlobalHistogramBinarizer::estimate(vector &histogram) { return bestValley; } +Ref GlobalHistogramBinarizer::createBinarizer(Ref source) { + return Ref (new GlobalHistogramBinarizer(source)); +} + } // namespace zxing diff --git a/cpp/core/src/zxing/common/GlobalHistogramBinarizer.h b/cpp/core/src/zxing/common/GlobalHistogramBinarizer.h index 42956e944..bff849898 100644 --- a/cpp/core/src/zxing/common/GlobalHistogramBinarizer.h +++ b/cpp/core/src/zxing/common/GlobalHistogramBinarizer.h @@ -30,13 +30,19 @@ namespace zxing { class GlobalHistogramBinarizer : public Binarizer { + private: + Ref cached_matrix_; + Ref cached_row_; + int cached_row_num_; + public: GlobalHistogramBinarizer(Ref source); virtual ~GlobalHistogramBinarizer(); - virtual Ref estimateBlackRow(int y, Ref row); - virtual Ref estimateBlackMatrix(); + virtual Ref getBlackRow(int y, Ref row); + virtual Ref getBlackMatrix(); static int estimate(std::vector &histogram); + Ref createBinarizer(Ref source); }; } diff --git a/cpp/core/src/zxing/common/LocalBlockBinarizer.cpp b/cpp/core/src/zxing/common/LocalBlockBinarizer.cpp deleted file mode 100644 index 135902a6d..000000000 --- a/cpp/core/src/zxing/common/LocalBlockBinarizer.cpp +++ /dev/null @@ -1,196 +0,0 @@ -/* - * LocalBlockBinarizer.cpp - * zxing - * - * Created by Ralf Kistner on 17/10/2009. - * Copyright 2008 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 - -namespace zxing { - -const int GLOBAL = 0; -const int THRESHOLD = 1; - -LocalBlockBinarizer::LocalBlockBinarizer(Ref source) : - Binarizer(source) { - -} - -LocalBlockBinarizer::~LocalBlockBinarizer() { -} - -Ref LocalBlockBinarizer::estimateBlackRow(int y, Ref row) { - //TODO: implement - return Ref(); -} - -// 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. -Ref LocalBlockBinarizer::estimateBlackMatrix() { - Ref source = getSource(); - unsigned char* luminances = source->copyMatrix(); - int width = source->getWidth(); - int height = source->getHeight(); - // Sharpening does not really help for 2d barcodes - // sharpenRow(luminances, width, height); - - int subWidth = width >> 3; - int subHeight = height >> 3; - - unsigned char* averages = new unsigned char[subWidth * subHeight]; - unsigned char* types = new unsigned char[subWidth * subHeight]; - - calculateBlackPoints(luminances, averages, types, subWidth, subHeight, width); - - Ref matrix(new BitMatrix(width, height)); - calculateThresholdForBlock(luminances, subWidth, subHeight, width, averages, types, *matrix); - - delete[] averages; - delete[] types; - delete[] luminances; - - return matrix; -} - -// For each 8x8 block in the image, calculate the average black point using a 5x5 grid -// of the blocks around it. Also handles the corner cases, but will ignore up to 7 pixels -// on the right edge and 7 pixels at the bottom of the image if the overall dimensions are not -// multiples of eight. In practice, leaving those pixels white does not seem to be a problem. -void LocalBlockBinarizer::calculateThresholdForBlock(const unsigned char* luminances, int subWidth, int subHeight, - int stride, const unsigned char* averages, const unsigned char* types, BitMatrix& matrix) { - // Calculate global average - int global = 0; - for (int y = 0; y < subHeight; y++) { - for (int x = 0; x < subWidth; x++) { - global += averages[y * subWidth + x]; - } - } - - global /= subWidth * subHeight; - - - for (int y = 0; y < subHeight; y++) { - for (int x = 0; x < subWidth; x++) { - int left = (x > 0) ? x : 1; - left = (left < subWidth - 1) ? left : subWidth - 2; - int top = (y > 0) ? y : 1; - top = (top < subHeight - 1) ? top : subHeight - 2; - int sum = 0; - int contrast = 0; - for (int z = -1; z <= 1; z++) { -// sum += averages[(top + z) * subWidth + left - 2]; - sum += averages[(top + z) * subWidth + left - 1]; - sum += averages[(top + z) * subWidth + left]; - sum += averages[(top + z) * subWidth + left + 1]; -// sum += averages[(top + z) * subWidth + left + 2]; - -// type += types[(top + z) * subWidth + left - 2]; - contrast += types[(top + z) * subWidth + left - 1]; - contrast += types[(top + z) * subWidth + left]; - contrast += types[(top + z) * subWidth + left + 1]; -// type += types[(top + z) * subWidth + left + 2]; - } - int average = sum / 9; - - - if (contrast > 2) - threshold8x8Block(luminances, x << 3, y << 3, average, stride, matrix); -// else if(average < global) // Black -// matrix.setRegion(x << 3, y << 3, 8, 8); - // If white, we don't need to do anything - the block is already cleared. - } - } -} - -// Applies a single threshold to an 8x8 block of pixels. -void LocalBlockBinarizer::threshold8x8Block(const unsigned char* luminances, int xoffset, int yoffset, int threshold, - int stride, BitMatrix& matrix) { - for (int y = 0; y < 8; y++) { - int offset = (yoffset + y) * stride + xoffset; - for (int x = 0; x < 8; x++) { - int pixel = luminances[offset + x]; - if (pixel < threshold) { - matrix.set(xoffset + x, yoffset + y); - } - } - } -} - -// Calculates a single black point for each 8x8 block of pixels and saves it away. -void LocalBlockBinarizer::calculateBlackPoints(const unsigned char* luminances, unsigned char* averages, - unsigned char* types, int subWidth, int subHeight, int stride) { - for (int y = 0; y < subHeight; y++) { - for (int x = 0; x < subWidth; x++) { - int sum = 0; - int min = 255; - int max = 0; - for (int yy = 0; yy < 8; yy++) { - int offset = ((y << 3) + yy) * stride + (x << 3); - const unsigned char* lumo = luminances + offset; - for (int xx = 0; xx < 8; xx++) { - int pixel = lumo[xx]; - sum += pixel; - if (pixel < min) { - min = pixel; - } - if (pixel > max) { - max = pixel; - } - } - } - - // If the contrast is inadequate, we treat the block as white. - // An arbitrary value is chosen here. Higher values mean less noise, but may also reduce - // the ability to recognise some barcodes. - int average = sum >> 6; - int type; - - if (max - min > 30) - type = THRESHOLD; - else - type = GLOBAL; - // int average = (max - min > 24) ? (sum >> 6) : (min-1); - averages[y * subWidth + x] = average; - types[y * subWidth + x] = type; - } - } -} - -// Applies a simple -1 4 -1 box filter with a weight of 2 to each row. -void LocalBlockBinarizer::sharpenRow(unsigned char* luminances, int width, int height) { - for (int y = 0; y < height; y++) { - int offset = y * width; - int left = luminances[offset]; - int center = luminances[offset + 1]; - for (int x = 1; x < width - 1; x++) { - unsigned char right = luminances[offset + x + 1]; - int pixel = ((center << 2) - left - right) >> 1; - // Must clamp values to 0..255 so they will fit in a byte. - if (pixel > 255) { - pixel = 255; - } else if (pixel < 0) { - pixel = 0; - } - luminances[offset + x] = (unsigned char)pixel; - left = center; - center = right; - } - } -} - -} diff --git a/cpp/core/src/zxing/common/LocalBlockBinarizer.h b/cpp/core/src/zxing/common/LocalBlockBinarizer.h deleted file mode 100644 index bae80bc75..000000000 --- a/cpp/core/src/zxing/common/LocalBlockBinarizer.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * LocalBlockBinarizer.h - * zxing - * - * Created by Ralf Kistner on 17/10/2009. - * Copyright 2008 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 LOCALBLOCKBINARIZER_H_ -#define LOCALBLOCKBINARIZER_H_ - -#include -#include - -namespace zxing { -class LocalBlockBinarizer : public Binarizer { -public: - LocalBlockBinarizer(Ref source); - virtual ~LocalBlockBinarizer(); - - virtual Ref estimateBlackMatrix(); - Ref estimateBlackRow(int y, Ref row); - -private: - - void calculateThresholdForBlock(const unsigned char* luminances, int subWidth, int subHeight, - int stride, const unsigned char* averages, const unsigned char* types, BitMatrix& matrix); - void sharpenRow(unsigned char* luminances, int width, int height); - void calculateBlackPoints(const unsigned char* luminances, unsigned char* averages, unsigned char* types, int subWidth, int subHeight, int stride); - void threshold8x8Block(const unsigned char* luminances, int xoffset, int yoffset, int threshold, - int stride, BitMatrix& matrix); -}; -} - -#endif /* LOCALBLOCKBINARIZER_H_ */ diff --git a/cpp/magick/src/MagickBitmapSource.cpp b/cpp/magick/src/MagickBitmapSource.cpp index 20085999e..71b775a07 100644 --- a/cpp/magick/src/MagickBitmapSource.cpp +++ b/cpp/magick/src/MagickBitmapSource.cpp @@ -24,6 +24,8 @@ using namespace Magick; +namespace zxing { + MagickBitmapSource::MagickBitmapSource(Image& image) : image_(image) { width = image.columns(); height = image.rows(); @@ -35,25 +37,30 @@ MagickBitmapSource::~MagickBitmapSource() { } -int MagickBitmapSource::getWidth() { +int MagickBitmapSource::getWidth() const { return width; } -int MagickBitmapSource::getHeight() { +int MagickBitmapSource::getHeight() const { return height; } -unsigned char MagickBitmapSource::getPixel(int x, int y) { - const PixelPacket* p = pixel_cache + y * width + x; - // We assume 16 bit values here +unsigned char* MagickBitmapSource::getRow(int y, unsigned char* row) { + int width = getWidth(); + if (row == NULL) { + row = new unsigned char[width]; + } + for (int x = 0; x < width; x++) { + const PixelPacket* p = pixel_cache + y * width + x; + // We assume 16 bit values here + row[x] = (unsigned char)((306 * ((int)p->red >> 8) + 601 * ((int)p->green >> 8) + 117 * ((int)p->blue >> 8)) >> 10); + } + return row; - //return (unsigned char)((((int)p->red + (int)p->green + (int)p->blue) >> 8) / 3); - - return (unsigned char)((306 * ((int)p->red >> 8) + 601 * ((int)p->green >> 8) + 117 * ((int)p->blue >> 8)) >> 10); } /** This is a more efficient implementation. */ -unsigned char* MagickBitmapSource::copyMatrix() { +unsigned char* MagickBitmapSource::getMatrix() { int width = getWidth(); int height = getHeight(); unsigned char* matrix = new unsigned char[width*height]; @@ -68,4 +75,5 @@ unsigned char* MagickBitmapSource::copyMatrix() { } return matrix; } +} diff --git a/cpp/magick/src/MagickBitmapSource.h b/cpp/magick/src/MagickBitmapSource.h index dd210846c..2bc3b9624 100644 --- a/cpp/magick/src/MagickBitmapSource.h +++ b/cpp/magick/src/MagickBitmapSource.h @@ -24,7 +24,9 @@ #include #include -class MagickBitmapSource : public zxing::LuminanceSource { +namespace zxing { + +class MagickBitmapSource : public LuminanceSource { private: Magick::Image& image_; int width; @@ -36,10 +38,12 @@ public: ~MagickBitmapSource(); - int getWidth(); - int getHeight(); - unsigned char getPixel(int x, int y); - unsigned char* copyMatrix(); + int getWidth() const; + int getHeight() const; + unsigned char* getRow(int y, unsigned char* row); + unsigned char* getMatrix(); }; +} + #endif /* MAGICKMONOCHROMEBITMAPSOURCE_H_ */ diff --git a/cpp/magick/src/example.cpp b/cpp/magick/src/example.cpp index cb119adec..0c07e1adf 100644 --- a/cpp/magick/src/example.cpp +++ b/cpp/magick/src/example.cpp @@ -75,7 +75,7 @@ int main(int argc, char** argv) { bool local = true; // Use local thresholding - test_image(image, local); + decode_image(image, local); } return 0; } diff --git a/cpp/magick/src/main.cpp b/cpp/magick/src/main.cpp index 65be40cec..292984d32 100644 --- a/cpp/magick/src/main.cpp +++ b/cpp/magick/src/main.cpp @@ -4,6 +4,7 @@ * * Created by Ralf Kistner on 16/10/2009. * Copyright 2008 ZXing authors All rights reserved. + * Modified by Yakov Okshtein (flyashi@gmail.com) to add 1D barcode support. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,10 +26,12 @@ #include "MagickBitmapSource.h" #include #include +#include +#include #include #include #include -#include +//#include #include #include #include @@ -106,28 +109,14 @@ void save_grid(Ref matrix, string filename, Ref image.write(filename); } -Ref decode(string out_prefix, Ref image, string& cell_grid, string& cell_transformed) { +Ref decode2D(string out_prefix, Ref image, string& cell_grid, string& cell_transformed) { + Decoder decoder; QREdgeDetector detector = QREdgeDetector(image->getBlackMatrix()); Ref detectorResult(detector.detect()); - if (out_prefix.size()) { - // Grid image - string gridfile = out_prefix + ".grid.gif"; - Ref transform = detectorResult->getTransform(); - int dimension = detectorResult->getBits()->getDimension(); - save_grid(image->getBlackMatrix(), gridfile, transform, dimension); - cell_grid = ""; - - // Transformed image - string tfile = out_prefix + ".transformed.png"; - save_matrix(detectorResult->getBits(), tfile, 5); - cell_transformed = ""; - } - - vector > points(detectorResult->getPoints()); Ref decoderResult(decoder.decode(detectorResult->getBits())); @@ -136,11 +125,26 @@ Ref decode(string out_prefix, Ref image, string& cell_grid decoderResult->getRawBytes(), points, BarcodeFormat_QR_CODE)); + return result; +} + +Ref decode1D(string out_prefix, Ref image, string& cell_grid, string& cell_transformed) { + + + Ref reader(new oned::MultiFormatUPCEANReader); + Ref result(new Result(*reader->decode(image))); return result; } - +//TODO(flyashi): Call MultiFormatReader directly +Ref decode(string out_prefix, Ref image, string& cell_grid, string& cell_transformed) { + try { + return decode1D(out_prefix,image,cell_grid,cell_transformed); + } catch (ReaderException re) { + return decode2D(out_prefix,image,cell_grid,cell_transformed); + } +} int test_image(Image& image, string out_prefix, bool localized) { @@ -159,7 +163,7 @@ int test_image(Image& image, string out_prefix, bool localized) { Ref source(new MagickBitmapSource(image)); if (localized) { - binarizer = new LocalBlockBinarizer(source); + //binarizer = new LocalBlockBinarizer(source); } else { binarizer = new GlobalHistogramBinarizer(source); } @@ -167,7 +171,7 @@ int test_image(Image& image, string out_prefix, bool localized) { if (out_prefix.size()) { string monofile = out_prefix + ".mono.png"; matrix = binarizer->getBlackMatrix(); - save_matrix(matrix, monofile); + //save_matrix(matrix, monofile); cell_mono = ""; } @@ -190,10 +194,8 @@ int test_image(Image& image, string out_prefix, bool localized) { res = -5; } - cout << "" << cell_mono << "" << endl; - cout << "" << cell_grid << "" << endl; - cout << "" << cell_transformed << "" << endl; - cout << "" << cell_result << "" << endl; + cout << cell_result; + return res; } @@ -213,16 +215,15 @@ int main(int argc, char** argv) { } string outfolder = argv[1]; - int total = argc - 2; + // int total = argc - 2; int gonly = 0; int lonly = 0; int both = 0; int neither = 0; - cout << "" << endl; for (int i = 2; i < argc; i++) { string infilename = argv[i]; - cerr << "Processing: " << infilename << endl; +// cerr << "Processing: " << infilename << endl; Image image; try { image.read(infilename); @@ -230,10 +231,6 @@ int main(int argc, char** argv) { cerr << "Unable to open image, ignoring" << endl; continue; } - cout << "" << endl; - cout << "" << endl; - - cout << "" << endl; int gresult = 1; @@ -241,36 +238,23 @@ int main(int argc, char** argv) { if (outfolder == string("-")) { gresult = test_image_global(image, ""); - lresult = test_image_local(image, ""); +// lresult = test_image_local(image, ""); } else { replace(infilename.begin(), infilename.end(), '/', '_'); string prefix = string(outfolder) + string("/") + infilename; gresult = test_image_global(image, prefix + ".g"); - lresult = test_image_local(image, prefix + ".l"); + // lresult = test_image_local(image, prefix + ".l"); } gresult = gresult == 0; - lresult = lresult == 0; + // lresult = lresult == 0; gonly += gresult && !lresult; lonly += lresult && !gresult; both += gresult && lresult; neither += !gresult && !lresult; - cout << "" << endl; } - cout << "
" << infilename << "
" << endl; - - cout << "" << endl; - cout << "" << endl; - cout << "" << endl; - cout << "" << endl; - cout << "" << endl; - cout << "" << endl; - - cout << "
Total" << total << "
Both correct" << both << "
Neither correct" << neither << "
Global only" << gonly << "
Local only" << lonly << "
" << endl; - cout << "" << endl; - return 0; }