Make C++ consistent with Java for pdf417

A bunch of small changes that result in C++ and Java equiv. for pdf417.

- A little bit of java re-reporting in pdf417
- A little bit of java re-reporting/consistency elsewhere

There a few places related to latching that differed between the java
and C++. I looked for a discussion of this on the group and didn't find
any (but may have missed it.) I reverted to the java code which fixed
one of the tests. The comments referenced standards-compliance vs. real
world encoders. That may need to be revisited?

git-svn-id: https://zxing.googlecode.com/svn/trunk@2673 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
smparkes@smparkes.net 2013-04-21 19:14:23 +00:00
parent d245a5cca7
commit b549267e6f
14 changed files with 261 additions and 286 deletions

View file

@ -22,7 +22,7 @@
#include <zxing/ResultPoint.h>
#include <zxing/common/detector/MathUtils.h>
namespace math_utils = zxing::common::detector::math_utils;
using zxing::common::detector::MathUtils;
namespace zxing {
@ -88,10 +88,10 @@ void ResultPoint::orderBestPatterns(std::vector<Ref<ResultPoint> > &patterns) {
}
float ResultPoint::distance(Ref<ResultPoint> pattern1, Ref<ResultPoint> pattern2) {
return math_utils::distance(pattern1->posX_,
pattern1->posY_,
pattern2->posX_,
pattern2->posY_);
return MathUtils::distance(pattern1->posX_,
pattern1->posY_,
pattern2->posX_,
pattern2->posY_);
}
float ResultPoint::distance(float x1, float x2, float y1, float y2) {

View file

@ -38,8 +38,7 @@ using zxing::ArrayRef;
using zxing::ResultPoint;
using zxing::BitArray;
using zxing::BitMatrix;
namespace math_utils = zxing::common::detector::math_utils;
using zxing::common::detector::MathUtils;
Detector::Detector(Ref<BitMatrix> image):
image_(image),
@ -145,21 +144,21 @@ Detector::getMatrixCornerPoints(std::vector<Ref<Point> > bullEyeCornerPoints) {
int dy = bullEyeCornerPoints[0]->getY() - bullEyeCornerPoints[2]->getY();
dy += dy > 0 ? 1 : -1;
int targetcx = math_utils::round(bullEyeCornerPoints[2]->getX() - ratio * dx);
int targetcy = math_utils::round(bullEyeCornerPoints[2]->getY() - ratio * dy);
int targetcx = MathUtils::round(bullEyeCornerPoints[2]->getX() - ratio * dx);
int targetcy = MathUtils::round(bullEyeCornerPoints[2]->getY() - ratio * dy);
int targetax = math_utils::round(bullEyeCornerPoints[0]->getX() + ratio * dx);
int targetay = math_utils::round(bullEyeCornerPoints[0]->getY() + ratio * dy);
int targetax = MathUtils::round(bullEyeCornerPoints[0]->getX() + ratio * dx);
int targetay = MathUtils::round(bullEyeCornerPoints[0]->getY() + ratio * dy);
dx = bullEyeCornerPoints[1]->getX() - bullEyeCornerPoints[3]->getX();
dx += dx > 0 ? 1 : -1;
dy = bullEyeCornerPoints[1]->getY() - bullEyeCornerPoints[3]->getY();
dy += dy > 0 ? 1 : -1;
int targetdx = math_utils::round(bullEyeCornerPoints[3]->getX() - ratio * dx);
int targetdy = math_utils::round(bullEyeCornerPoints[3]->getY() - ratio * dy);
int targetbx = math_utils::round(bullEyeCornerPoints[1]->getX() + ratio * dx);
int targetby = math_utils::round(bullEyeCornerPoints[1]->getY() + ratio * dy);
int targetdx = MathUtils::round(bullEyeCornerPoints[3]->getX() - ratio * dx);
int targetdy = MathUtils::round(bullEyeCornerPoints[3]->getY() - ratio * dy);
int targetbx = MathUtils::round(bullEyeCornerPoints[1]->getX() + ratio * dx);
int targetby = MathUtils::round(bullEyeCornerPoints[1]->getY() + ratio * dy);
if (!isValid(targetax, targetay) ||
!isValid(targetbx, targetby) ||
@ -272,18 +271,18 @@ std::vector<Ref<Point> > Detector::getBullEyeCornerPoints(Ref<zxing::aztec::Poin
int dx = pina->getX() - pind->getX();
int dy = pina->getY() - pinc->getY();
int targetcx = math_utils::round(pinc->getX() - ratio * dx);
int targetcy = math_utils::round(pinc->getY() - ratio * dy);
int targetax = math_utils::round(pina->getX() + ratio * dx);
int targetay = math_utils::round(pina->getY() + ratio * dy);
int targetcx = MathUtils::round(pinc->getX() - ratio * dx);
int targetcy = MathUtils::round(pinc->getY() - ratio * dy);
int targetax = MathUtils::round(pina->getX() + ratio * dx);
int targetay = MathUtils::round(pina->getY() + ratio * dy);
dx = pinb->getX() - pind->getX();
dy = pinb->getY() - pind->getY();
int targetdx = math_utils::round(pind->getX() - ratio * dx);
int targetdy = math_utils::round(pind->getY() - ratio * dy);
int targetbx = math_utils::round(pinb->getX() + ratio * dx);
int targetby = math_utils::round(pinb->getY() + ratio * dy);
int targetdx = MathUtils::round(pind->getX() - ratio * dx);
int targetdy = MathUtils::round(pind->getY() - ratio * dy);
int targetbx = MathUtils::round(pinb->getX() + ratio * dx);
int targetby = MathUtils::round(pinb->getY() + ratio * dy);
if (!isValid(targetax, targetay) ||
!isValid(targetbx, targetby) ||
@ -325,8 +324,8 @@ Ref<Point> Detector::getMatrixCenter() {
}
int cx = math_utils::round((pointA->getX() + pointD->getX() + pointB->getX() + pointC->getX()) / 4.0f);
int cy = math_utils::round((pointA->getY() + pointD->getY() + pointB->getY() + pointC->getY()) / 4.0f);
int cx = MathUtils::round((pointA->getX() + pointD->getX() + pointB->getX() + pointC->getX()) / 4.0f);
int cy = MathUtils::round((pointA->getY() + pointD->getY() + pointB->getY() + pointC->getY()) / 4.0f);
try {
@ -346,8 +345,8 @@ Ref<Point> Detector::getMatrixCenter() {
}
cx = math_utils::round((pointA->getX() + pointD->getX() + pointB->getX() + pointC->getX()) / 4.0f);
cy = math_utils::round((pointA->getY() + pointD->getY() + pointB->getY() + pointC->getY()) / 4.0f);
cx = MathUtils::round((pointA->getX() + pointD->getX() + pointB->getX() + pointC->getX()) / 4.0f);
cy = MathUtils::round((pointA->getY() + pointD->getY() + pointB->getY() + pointC->getY()) / 4.0f);
return Ref<Point>(new Point(cx, cy));
@ -436,7 +435,7 @@ Ref<BitArray> Detector::sampleLine(Ref<zxing::aztec::Point> p1, Ref<zxing::aztec
float py = float(p1->getY());
for (int i = 0; i < size; i++) {
if (image_->get(math_utils::round(px), math_utils::round(py))) res->set(i);
if (image_->get(MathUtils::round(px), MathUtils::round(py))) res->set(i);
px+=dx;
py+=dy;
}
@ -498,7 +497,7 @@ int Detector::getColor(Ref<zxing::aztec::Point> p1, Ref<zxing::aztec::Point> p2)
for (int i = 0; i < d; i++) {
px += dx;
py += dy;
if (image_->get(math_utils::round(px), math_utils::round(py)) != colorModel) {
if (image_->get(MathUtils::round(px), MathUtils::round(py)) != colorModel) {
error ++;
}
}

View file

@ -29,6 +29,10 @@ String::String(const std::string &text) :
text_(text) {
}
String::String(int capacity) {
text_.reserve(capacity);
}
const std::string& String::getText() const {
return text_;
}

View file

@ -35,6 +35,7 @@ private:
std::string text_;
public:
explicit String(const std::string &text);
explicit String(int);
char charAt(int) const;
Ref<String> substring(int) const;
const std::string& getText() const;

View file

@ -0,0 +1,43 @@
// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
#ifndef __ZXING_COMMON_DETECTOR_MATH_H__
#define __ZXING_COMMON_DETECTOR_MATH_H__
/*
* Copyright 2012 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 <cmath>
namespace zxing {
namespace common {
namespace detector {
class Math {
private:
Math();
~Math();
public:
// Java standard Math.round
static inline int round(float a) {
return (int)std::floor(a +0.5f);
}
};
}
}
}
#endif

View file

@ -19,28 +19,39 @@
#include <cmath>
namespace zxing { namespace common { namespace detector { namespace math_utils {
namespace zxing {
namespace common {
namespace detector {
class MathUtils {
private:
MathUtils();
~MathUtils();
public:
/**
* Ends up being a bit faster than {@link Math#round(float)}. This merely rounds its
* argument to the nearest int, where x.5 rounds up to x+1.
*/
static inline int round(float d) {
return (int) (d + 0.5f);
}
static inline float distance(float aX, float aY, float bX, float bY) {
float xDiff = aX - bX;
float yDiff = aY - bY;
return sqrt(xDiff * xDiff + yDiff * yDiff);
}
static inline float distance(int aX, int aY, int bX, int bY) {
int xDiff = aX - bX;
int yDiff = aY - bY;
return sqrt(float(xDiff * xDiff + yDiff * yDiff));
}
};
/**
* Ends up being a bit faster than {@link Math#round(float)}. This merely rounds its
* argument to the nearest int, where x.5 rounds up to x+1.
*/
inline int round(float d) {
return (int) (d + 0.5f);
}
inline float distance(float aX, float aY, float bX, float bY) {
float xDiff = aX - bX;
float yDiff = aY - bY;
return sqrt(xDiff * xDiff + yDiff * yDiff);
}
inline float distance(int aX, int aY, int bX, int bY) {
int xDiff = aX - bX;
int yDiff = aY - bY;
return sqrt(float(xDiff * xDiff + yDiff * yDiff));
}
}}}}
#endif

View file

@ -24,12 +24,11 @@
#include <zxing/common/detector/MathUtils.h>
#include <sstream>
namespace math_utils = zxing::common::detector::math_utils;
using std::vector;
using zxing::Ref;
using zxing::ResultPoint;
using zxing::WhiteRectangleDetector;
using zxing::common::detector::MathUtils;
// VC++
using zxing::BitMatrix;
@ -232,13 +231,13 @@ std::vector<Ref<ResultPoint> > WhiteRectangleDetector::detect() {
Ref<ResultPoint>
WhiteRectangleDetector::getBlackPointOnSegment(int aX_, int aY_, int bX_, int bY_) {
float aX = float(aX_), aY = float(aY_), bX = float(bX_), bY = float(bY_);
int dist = math_utils::round(math_utils::distance(aX, aY, bX, bY));
int dist = MathUtils::round(MathUtils::distance(aX, aY, bX, bY));
float xStep = (bX - aX) / dist;
float yStep = (bY - aY) / dist;
for (int i = 0; i < dist; i++) {
int x = math_utils::round(aX + i * xStep);
int y = math_utils::round(aY + i * yStep);
int x = MathUtils::round(aX + i * xStep);
int y = MathUtils::round(aY + i * yStep);
if (image_->get(x, y)) {
Ref<ResultPoint> point(new ResultPoint(float(x), float(y)));
return point;

View file

@ -28,7 +28,6 @@
#include <sstream>
#include <cstdlib>
namespace math_utils = zxing::common::detector::math_utils;
using zxing::Ref;
using zxing::BitMatrix;
@ -38,6 +37,7 @@ using zxing::PerspectiveTransform;
using zxing::NotFoundException;
using zxing::datamatrix::Detector;
using zxing::datamatrix::ResultPointsAndTransitions;
using zxing::common::detector::MathUtils;
namespace {
typedef std::map<Ref<ResultPoint>, int> PointMap;
@ -346,7 +346,7 @@ bool Detector::isValid(Ref<ResultPoint> p) {
}
int Detector::distance(Ref<ResultPoint> a, Ref<ResultPoint> b) {
return math_utils::round(ResultPoint::distance(a, b));
return MathUtils::round(ResultPoint::distance(a, b));
}
Ref<ResultPointsAndTransitions> Detector::transitionsBetween(Ref<ResultPoint> from,

View file

@ -118,12 +118,12 @@ int PDF417Reader::moduleSize(ArrayRef<int> leftTopBlack, Ref<BitMatrix> image) {
throw NotFoundException("PDF417Reader::moduleSize: not found!");
}
int nModuleSize = (int)(((unsigned)(x - leftTopBlack[0])) >> 3); // We've crossed left first bar, which is 8x
if (nModuleSize == 0) {
int moduleSize = (int)(((unsigned)(x - leftTopBlack[0])) >> 3); // We've crossed left first bar, which is 8x
if (moduleSize == 0) {
throw NotFoundException("PDF417Reader::moduleSize: is zero!");
}
return nModuleSize;
return moduleSize;
}
int PDF417Reader::findPatternStart(int x, int y, Ref<BitMatrix> image) {

View file

@ -28,8 +28,6 @@ using zxing::Ref;
using zxing::DecoderResult;
using zxing::String;
// VC++
const int DecodedBitStreamParser::TEXT_COMPACTION_MODE_LATCH = 900;
const int DecodedBitStreamParser::BYTE_COMPACTION_MODE_LATCH = 901;
const int DecodedBitStreamParser::NUMERIC_COMPACTION_MODE_LATCH = 902;
@ -60,40 +58,27 @@ const char DecodedBitStreamParser::MIXED_CHARS[] = {
'\r', '\t', ',', ':', '#', '-', '.', '$', '/', '+', '%', '*',
'=', '^'};
ArrayRef<BigInteger> DecodedBitStreamParser::AExp900_;
/**
* Table containing values for the exponent of 900.
* This is used in the numeric compaction decode algorithm.
* Hint: will be initialized only once (because of zero check), so it can be
* called by the constructor.
*/
void DecodedBitStreamParser::InitExp900()
{
if(&(*AExp900_) == 0) {
BigInteger nineHundred(900);
AExp900_ = new Array<BigInteger>(EXP900_SIZE);
AExp900_[0] = BigInteger(1);
for (int i=1;i<AExp900_->size();i++) {
AExp900_[i] = AExp900_[i-1] * nineHundred;
}
ArrayRef<BigInteger> DecodedBitStreamParser::initEXP900() {
ArrayRef<BigInteger> EXP900 (16);
EXP900[0] = BigInteger(1);
BigInteger nineHundred (900);
EXP900[1] = nineHundred;
for (int i = 2; i < EXP900->size(); i++) {
EXP900[i] = EXP900[i - 1] * nineHundred;
}
return EXP900;
}
/**
* Constructor will initialize exp900 table the first time.
*/
DecodedBitStreamParser::DecodedBitStreamParser()
{
InitExp900();
}
ArrayRef<BigInteger> DecodedBitStreamParser::EXP900 = initEXP900();
DecodedBitStreamParser::DecodedBitStreamParser(){}
/**
* PDF417 main decoder.
**/
Ref<DecoderResult> DecodedBitStreamParser::decode(ArrayRef<int> codewords)
{
Ref<String> result(new String(""));
Ref<String> result (new String(100));
// Get compaction mode
int codeIndex = 1;
int code = codewords[codeIndex++];
@ -125,13 +110,10 @@ Ref<DecoderResult> DecodedBitStreamParser::decode(ArrayRef<int> codewords)
if (codeIndex < codewords->size()) {
code = codewords[codeIndex++];
} else {
throw FormatException("PDF417:DecodedBitStreamParser:decode: codeword overflow");
throw FormatException();
}
}
ArrayRef<char> dummybuf(1);
dummybuf[0]= '\0';
return Ref<DecoderResult>(new DecoderResult(dummybuf, result));
return Ref<DecoderResult>(new DecoderResult(ArrayRef<char>(), result));
}
/**
@ -144,12 +126,13 @@ Ref<DecoderResult> DecodedBitStreamParser::decode(ArrayRef<int> codewords)
* @param result The decoded data is appended to the result.
* @return The next index into the codeword array.
*/
int DecodedBitStreamParser::textCompaction(ArrayRef<int> codewords, int codeIndex, Ref<String> result)
{
int DecodedBitStreamParser::textCompaction(ArrayRef<int> codewords,
int codeIndex,
Ref<String> result) {
// 2 character per codeword
ArrayRef<int> textCompactionData = new Array<int>(codewords[0] << 1);
ArrayRef<int> textCompactionData (codewords[0] << 1);
// Used to hold the byte compaction value if there is a mode shift
ArrayRef<int> byteCompactionData = new Array<int>(codewords[0] << 1);
ArrayRef<int> byteCompactionData (codewords[0] << 1);
int index = 0;
bool end = false;
@ -162,8 +145,7 @@ int DecodedBitStreamParser::textCompaction(ArrayRef<int> codewords, int codeInde
} else {
switch (code) {
case TEXT_COMPACTION_MODE_LATCH:
codeIndex--;
end = true;
textCompactionData[index++] = TEXT_COMPACTION_MODE_LATCH;
break;
case BYTE_COMPACTION_MODE_LATCH:
codeIndex--;
@ -246,10 +228,7 @@ void DecodedBitStreamParser::decodeTextCompaction(ArrayRef<int> textCompactionDa
subMode = PUNCT_SHIFT;
} else if (subModeCh == MODE_SHIFT_TO_BYTE_COMPACTION_MODE) {
result->append((char) byteCompactionData[i]);
// 2012-11-27 hfn after fix by srowen in java code:
// the pdf417 specs say we have to return to the last latched
// sub-mode. But I checked different encoder implementations and
// all of them return to alpha sub-mode after Shift-to-Byte
} else if (subModeCh == TEXT_COMPACTION_MODE_LATCH) {
subMode = ALPHA;
}
}
@ -274,10 +253,7 @@ void DecodedBitStreamParser::decodeTextCompaction(ArrayRef<int> textCompactionDa
subMode = PUNCT_SHIFT;
} else if (subModeCh == MODE_SHIFT_TO_BYTE_COMPACTION_MODE) {
result->append((char) byteCompactionData[i]);
// 2012-11-27 hfn after fix by srowen in java code:
// the pdf417 specs say we have to return to the last latched
// sub-mode. But I checked different encoder implementations and
// all of them return to alpha sub-mode after Shift-to-Byte
} else if (subModeCh == TEXT_COMPACTION_MODE_LATCH) {
subMode = ALPHA;
}
}
@ -302,10 +278,7 @@ void DecodedBitStreamParser::decodeTextCompaction(ArrayRef<int> textCompactionDa
subMode = PUNCT_SHIFT;
} else if (subModeCh == MODE_SHIFT_TO_BYTE_COMPACTION_MODE) {
result->append((char) byteCompactionData[i]);
// 2012-11-27 hfn after fix by srowen in java code:
// the pdf417 specs say we have to return to the last latched
// sub-mode. But I checked different encoder implementations and
// all of them return to alpha sub-mode after Shift-to-Byte
} else if (subModeCh == TEXT_COMPACTION_MODE_LATCH) {
subMode = ALPHA;
}
}
@ -320,10 +293,7 @@ void DecodedBitStreamParser::decodeTextCompaction(ArrayRef<int> textCompactionDa
subMode = ALPHA;
} else if (subModeCh == MODE_SHIFT_TO_BYTE_COMPACTION_MODE) {
result->append((char) byteCompactionData[i]);
// 2012-11-27 hfn after fix by srowen in java code:
// the pdf417 specs say we have to return to the last latched
// sub-mode. But I checked different encoder implementations and
// all of them return to alpha sub-mode after Shift-to-Byte
} else if (subModeCh == TEXT_COMPACTION_MODE_LATCH) {
subMode = ALPHA;
}
}
@ -338,7 +308,11 @@ void DecodedBitStreamParser::decodeTextCompaction(ArrayRef<int> textCompactionDa
if (subModeCh == 26) {
ch = ' ';
} else {
// is this even possible?
if (subModeCh == 26) {
ch = ' ';
} else if (subModeCh == TEXT_COMPACTION_MODE_LATCH) {
subMode = ALPHA;
}
}
}
break;
@ -356,11 +330,6 @@ void DecodedBitStreamParser::decodeTextCompaction(ArrayRef<int> textCompactionDa
// PS before Shift-to-Byte is used as a padding character,
// see 5.4.2.4 of the specification
result->append((char) byteCompactionData[i]);
// 2012-11-27 hfn after fix by srowen in java code:
// the pdf417 specs say we have to return to the last latched
// sub-mode. But I checked different encoder implementations and
// all of them return to alpha sub-mode after Shift-to-Byte
subMode = ALPHA;
} else if (subModeCh == TEXT_COMPACTION_MODE_LATCH) {
subMode = ALPHA;
}
@ -386,8 +355,9 @@ void DecodedBitStreamParser::decodeTextCompaction(ArrayRef<int> textCompactionDa
* @param result The decoded data is appended to the result.
* @return The next index into the codeword array.
*/
int DecodedBitStreamParser::byteCompaction(int mode, ArrayRef<int> codewords, int codeIndex, Ref<String> result)
{
int DecodedBitStreamParser::byteCompaction(int mode,
ArrayRef<int> codewords,
int codeIndex, Ref<String> result) {
if (mode == BYTE_COMPACTION_MODE_LATCH) {
// Total number of Byte Compaction characters to be encoded
// is not a multiple of 6
@ -491,8 +461,9 @@ int DecodedBitStreamParser::byteCompaction(int mode, ArrayRef<int> codewords, in
* @param result The decoded data is appended to the result.
* @return The next index into the codeword array.
*/
int DecodedBitStreamParser::numericCompaction(ArrayRef<int> codewords, int codeIndex, Ref<String> result)
{
int DecodedBitStreamParser::numericCompaction(ArrayRef<int> codewords,
int codeIndex,
Ref<String> result) {
int count = 0;
bool end = false;
@ -577,10 +548,9 @@ int DecodedBitStreamParser::numericCompaction(ArrayRef<int> codewords, int codeI
*/
Ref<String> DecodedBitStreamParser::decodeBase900toBase10(ArrayRef<int> codewords, int count)
{
InitExp900();
BigInteger result = BigInteger(0);
for (int i = 0; i < count; i++) {
result = result + (AExp900_[count - i - 1] * BigInteger(codewords[i]));
result = result + (EXP900[count - i - 1] * BigInteger(codewords[i]));
}
string resultString = bigIntegerToString(result);
if (resultString[0] != '1') {

View file

@ -61,8 +61,8 @@ class DecodedBitStreamParser {
static const char PUNCT_CHARS[];
static const char MIXED_CHARS[];
static ArrayRef<BigInteger> AExp900_;
static void InitExp900();
static ArrayRef<BigInteger> EXP900;
static ArrayRef<BigInteger> initEXP900();
static int textCompaction(ArrayRef<int> codewords, int codeIndex, Ref<String> result);
static void decodeTextCompaction(ArrayRef<int> textCompactionData,

View file

@ -15,16 +15,18 @@
* limitations under the License.
*/
#include <vector>
#include <limits>
#include <zxing/pdf417/detector/Detector.h>
#include <zxing/pdf417/detector/LinesSampler.h>
#include <zxing/common/GridSampler.h>
#include <zxing/common/detector/Math.h>
#include <zxing/common/detector/MathUtils.h>
using std::vector;
using std::max;
using std::numeric_limits;
using zxing::pdf417::detector::Detector;
using zxing::common::detector::Math;
using zxing::common::detector::MathUtils;
using zxing::Ref;
using zxing::ArrayRef;
using zxing::DetectorResult;
@ -49,51 +51,33 @@ using zxing::Line;
* @author creatale GmbH (christoph.schulz@creatale.de)
*/
const int Detector::MAX_AVG_VARIANCE = (int) ((1 << 8) * 0.42f);
const int Detector::MAX_INDIVIDUAL_VARIANCE = (int) ((1 << 8) * 0.8f);
const int Detector::MAX_AVG_VARIANCE= (int) (PATTERN_MATCH_RESULT_SCALE_FACTOR * 0.42f);
const int Detector::MAX_INDIVIDUAL_VARIANCE = (int) (PATTERN_MATCH_RESULT_SCALE_FACTOR * 0.8f);
// B S B S B S B S Bar/Space pattern
// 11111111 0 1 0 1 0 1 000
const int Detector::START_PATTERN[] = {8, 1, 1, 1, 1, 1, 1, 3};
const int Detector::START_PATTERN_LENGTH = sizeof(START_PATTERN) / sizeof(int);
// 11111111 0 1 0 1 0 1 000
const int Detector::START_PATTERN_REVERSE[] = {3, 1, 1, 1, 1, 1, 1, 8};
const int Detector::START_PATTERN_REVERSE_LENGTH = sizeof(START_PATTERN_REVERSE) / sizeof(int);
// 1111111 0 1 000 1 0 1 00 1
const int Detector::STOP_PATTERN[] = {7, 1, 1, 3, 1, 1, 1, 2, 1};
const int Detector::STOP_PATTERN_LENGTH = sizeof(STOP_PATTERN) / sizeof(int);
// B S B S B S B S B Bar/Space pattern
// 1111111 0 1 000 1 0 1 00 1
const int Detector::STOP_PATTERN_REVERSE[] = {1, 2, 1, 1, 1, 3, 1, 1, 7};
const int Detector::STOP_PATTERN_REVERSE_LENGTH = sizeof(STOP_PATTERN_REVERSE) / sizeof(int);
const int Detector::SIZEOF_START_PATTERN = sizeof(START_PATTERN) / sizeof(int);
const int Detector::SIZEOF_START_PATTERN_REVERSE = sizeof(START_PATTERN_REVERSE) / sizeof(int);
const int Detector::SIZEOF_STOP_PATTERN = sizeof(STOP_PATTERN) / sizeof(int);
const int Detector::SIZEOF_STOP_PATTERN_REVERSE = sizeof(STOP_PATTERN_REVERSE) / sizeof(int);
const int Detector::COUNT_VERTICES = 16;
Detector::Detector(Ref<BinaryBitmap> image) : image_(image) {}
Detector::Detector(Ref<BinaryBitmap> image)
: image_(image) {
}
/**
* <p>Detects a PDF417 Code in an image, simply.</p>
*
* @return {@link DetectorResult} encapsulating results of detecting a PDF417 Code
* @throws NotFoundException if no QR Code can be found
*/
Ref<DetectorResult> Detector::detect() {
DecodeHints defaultHints;
return detect(defaultHints);
return detect(DecodeHints());
}
/**
* <p>Detects a PDF417 Code in an image. Only checks 0 and 180 degree rotations.</p>
*
* @param hints optional hints to detector
* @return {@link DetectorResult} encapsulating results of detecting a PDF417 Code
* @throws NotFoundException if no PDF417 Code can be found
*/
Ref<DetectorResult> Detector::detect(DecodeHints const& hints) {
(void)hints;
// Fetch the 1 bit matrix once up front.
@ -101,19 +85,18 @@ Ref<DetectorResult> Detector::detect(DecodeHints const& hints) {
// Try to find the vertices assuming the image is upright.
const int rowStep = 8;
vector<Ref<ResultPoint> > vertices;
vertices = findVertices(matrix, rowStep);
if (vertices.empty()) {
ArrayRef< Ref<ResultPoint> > vertices (findVertices(matrix, rowStep));
if (!vertices) {
// Maybe the image is rotated 180 degrees?
vertices = findVertices180(matrix, rowStep);
if (!vertices.empty()) {
if (vertices) {
correctVertices(matrix, vertices, true);
}
} else {
correctVertices(matrix, vertices, false);
}
if (vertices.empty()) {
if (!vertices) {
throw NotFoundException("No vertices found.");
}
@ -127,21 +110,19 @@ Ref<DetectorResult> Detector::detect(DecodeHints const& hints) {
if (dimension < 1) {
throw NotFoundException("Bad dimension.");
}
int yDimension = max(computeYDimension(vertices[12], vertices[14],
vertices[13], vertices[15], moduleWidth), dimension);
vertices[13], vertices[15], moduleWidth), dimension);
// Deskew and sample lines from image.
Ref<BitMatrix> linesMatrix = sampleLines(vertices, dimension, yDimension);
LinesSampler sampler(linesMatrix, dimension);
Ref<BitMatrix> linesGrid(sampler.sample());
Ref<BitMatrix> linesGrid(LinesSampler(linesMatrix, dimension).sample());
//TODO: verify vertices (was vertices[5 4 6 7]).
ArrayRef< Ref<ResultPoint> > points(4);
points[0] = new ResultPoint(0.0f, (float)linesMatrix->getHeight());
points[1] = new ResultPoint(0.0f, 0.0f);
points[2] = new ResultPoint((float)linesMatrix->getWidth(), 0.0f);
points[3] = new ResultPoint((float)linesMatrix->getWidth(), (float)linesMatrix->getHeight());
points[0] = vertices[5];
points[1] = vertices[4];
points[2] = vertices[6];
points[3] = vertices[7];
return Ref<DetectorResult>(new DetectorResult(linesGrid, points));
}
@ -161,20 +142,20 @@ Ref<DetectorResult> Detector::detect(DecodeHints const& hints) {
* vertices[6] x, y top right codeword area
* vertices[7] x, y bottom right codeword area
*/
vector<Ref<ResultPoint> > Detector::findVertices(Ref<BitMatrix> matrix, int rowStep)
ArrayRef< Ref<ResultPoint> > Detector::findVertices(Ref<BitMatrix> matrix, int rowStep)
{
const int height = matrix->getHeight();
const int width = matrix->getWidth();
vector<Ref<ResultPoint> > result(COUNT_VERTICES);
ArrayRef< Ref<ResultPoint> > result(16);
bool found = false;
ArrayRef<int> counters(new Array<int>(SIZEOF_START_PATTERN));
ArrayRef<int> counters(new Array<int>(START_PATTERN_LENGTH));
// Top Left
for (int i = 0; i < height; i += rowStep) {
ArrayRef<int> loc = findGuardPattern(matrix, 0, i, width, false, START_PATTERN,
SIZEOF_START_PATTERN, counters);
START_PATTERN_LENGTH, counters);
if (loc) {
result[0] = new ResultPoint((float)loc[0], (float)i);
result[4] = new ResultPoint((float)loc[1], (float)i);
@ -185,9 +166,9 @@ vector<Ref<ResultPoint> > Detector::findVertices(Ref<BitMatrix> matrix, int rowS
// Bottom left
if (found) { // Found the Top Left vertex
found = false;
for (long i = height - 1; i > 0; i -= rowStep) {
for (int i = height - 1; i > 0; i -= rowStep) {
ArrayRef<int> loc = findGuardPattern(matrix, 0, i, width, false, START_PATTERN,
SIZEOF_START_PATTERN, counters);
START_PATTERN_LENGTH, counters);
if (loc) {
result[1] = new ResultPoint((float)loc[0], (float)i);
result[5] = new ResultPoint((float)loc[1], (float)i);
@ -197,14 +178,14 @@ vector<Ref<ResultPoint> > Detector::findVertices(Ref<BitMatrix> matrix, int rowS
}
}
counters = new Array<int>(SIZEOF_STOP_PATTERN);
counters = new Array<int>(STOP_PATTERN_LENGTH);
// Top right
if (found) { // Found the Bottom Left vertex
found = false;
for (int i = 0; i < height; i += rowStep) {
ArrayRef<int> loc = findGuardPattern(matrix, 0, i, width, false, STOP_PATTERN,
SIZEOF_STOP_PATTERN, counters);
STOP_PATTERN_LENGTH, counters);
if (loc) {
result[2] = new ResultPoint((float)loc[1], (float)i);
result[6] = new ResultPoint((float)loc[0], (float)i);
@ -216,9 +197,9 @@ vector<Ref<ResultPoint> > Detector::findVertices(Ref<BitMatrix> matrix, int rowS
// Bottom right
if (found) { // Found the Top right vertex
found = false;
for (long i = height - 1; i > 0; i -= rowStep) {
for (int i = height - 1; i > 0; i -= rowStep) {
ArrayRef<int> loc = findGuardPattern(matrix, 0, i, width, false, STOP_PATTERN,
SIZEOF_STOP_PATTERN, counters);
STOP_PATTERN_LENGTH, counters);
if (loc) {
result[3] = new ResultPoint((float)loc[1], (float)i);
result[7] = new ResultPoint((float)loc[0], (float)i);
@ -228,48 +209,24 @@ vector<Ref<ResultPoint> > Detector::findVertices(Ref<BitMatrix> matrix, int rowS
}
}
if (!found) {
// Do not return partial results (instead of returning null).
result.clear();
}
return result;
return found ? result : ArrayRef< Ref<ResultPoint> >();
}
/**
* Locate the vertices and the codewords area of a black blob using the Start
* and Stop patterns as locators. This assumes that the image is rotated 180
* degrees and if it locates the start and stop patterns at it will re-map
* the vertices for a 0 degree rotation.
* TODO: Change assumption about barcode location.
*
* @param matrix the scanned barcode image.
* @param rowStep the step size for iterating rows (every n-th row).
* @return an array containing the vertices:
* vertices[0] x, y top left barcode
* vertices[1] x, y bottom left barcode
* vertices[2] x, y top right barcode
* vertices[3] x, y bottom right barcode
* vertices[4] x, y top left codeword area
* vertices[5] x, y bottom left codeword area
* vertices[6] x, y top right codeword area
* vertices[7] x, y bottom right codeword area
*/
vector<Ref<ResultPoint> > Detector::findVertices180(Ref<BitMatrix> matrix, int rowStep)
{
ArrayRef< Ref<ResultPoint> > Detector::findVertices180(Ref<BitMatrix> matrix, int rowStep) {
const int height = matrix->getHeight();
const int width = matrix->getWidth();
const int halfWidth = width >> 1;
vector<Ref<ResultPoint> > result(COUNT_VERTICES);
ArrayRef< Ref<ResultPoint> > result(16);
bool found = false;
ArrayRef<int> counters = new Array<int>(SIZEOF_START_PATTERN_REVERSE);
ArrayRef<int> counters = new Array<int>(START_PATTERN_REVERSE_LENGTH);
// Top Left
for (int i = height - 1; i > 0; i -= rowStep) {
ArrayRef<int> loc = findGuardPattern(matrix, halfWidth, i, halfWidth, true, START_PATTERN_REVERSE,
SIZEOF_START_PATTERN_REVERSE, counters);
ArrayRef<int> loc =
findGuardPattern(matrix, halfWidth, i, halfWidth, true, START_PATTERN_REVERSE,
START_PATTERN_REVERSE_LENGTH, counters);
if (loc) {
result[0] = new ResultPoint((float)loc[1], (float)i);
result[4] = new ResultPoint((float)loc[0], (float)i);
@ -281,8 +238,9 @@ vector<Ref<ResultPoint> > Detector::findVertices180(Ref<BitMatrix> matrix, int r
if (found) { // Found the Top Left vertex
found = false;
for (int i = 0; i < height; i += rowStep) {
ArrayRef<int> loc = findGuardPattern(matrix, halfWidth, i, halfWidth, true, START_PATTERN_REVERSE,
SIZEOF_START_PATTERN_REVERSE, counters);
ArrayRef<int> loc =
findGuardPattern(matrix, halfWidth, i, halfWidth, true, START_PATTERN_REVERSE,
START_PATTERN_REVERSE_LENGTH, counters);
if (loc) {
result[1] = new ResultPoint((float)loc[1], (float)i);
result[5] = new ResultPoint((float)loc[0], (float)i);
@ -292,14 +250,14 @@ vector<Ref<ResultPoint> > Detector::findVertices180(Ref<BitMatrix> matrix, int r
}
}
counters = new Array<int>(SIZEOF_STOP_PATTERN_REVERSE);
counters = new Array<int>(STOP_PATTERN_REVERSE_LENGTH);
// Top Right
if (found) { // Found the Bottom Left vertex
found = false;
for (int i = height - 1; i > 0; i -= rowStep) {
ArrayRef<int> loc = findGuardPattern(matrix, 0, i, halfWidth, false, STOP_PATTERN_REVERSE,
SIZEOF_STOP_PATTERN_REVERSE, counters);
STOP_PATTERN_REVERSE_LENGTH, counters);
if (loc) {
result[2] = new ResultPoint((float)loc[0], (float)i);
result[6] = new ResultPoint((float)loc[1], (float)i);
@ -313,7 +271,7 @@ vector<Ref<ResultPoint> > Detector::findVertices180(Ref<BitMatrix> matrix, int r
found = false;
for (int i = 0; i < height; i += rowStep) {
ArrayRef<int> loc = findGuardPattern(matrix, 0, i, halfWidth, false, STOP_PATTERN_REVERSE,
SIZEOF_STOP_PATTERN_REVERSE, counters);
STOP_PATTERN_REVERSE_LENGTH, counters);
if (loc) {
result[3] = new ResultPoint((float)loc[0], (float)i);
result[7] = new ResultPoint((float)loc[1], (float)i);
@ -323,12 +281,7 @@ vector<Ref<ResultPoint> > Detector::findVertices180(Ref<BitMatrix> matrix, int r
}
}
if (!found) {
// Do not return partial results (instead of returning null).
result.clear();
}
return result;
return found ? result : ArrayRef< Ref<ResultPoint> >();
}
/**
@ -348,7 +301,7 @@ ArrayRef<int> Detector::findGuardPattern(Ref<BitMatrix> matrix,
bool whiteFirst,
const int pattern[],
int patternSize,
ArrayRef<int> counters) {
ArrayRef<int>& counters) {
counters->values().assign(counters->size(), 0);
int patternLength = patternSize;
bool isWhite = whiteFirst;
@ -399,7 +352,8 @@ ArrayRef<int> Detector::findGuardPattern(Ref<BitMatrix> matrix,
* variance between counters and patterns equals the pattern length,
* higher values mean even more variance
*/
int Detector::patternMatchVariance(ArrayRef<int> counters, const int pattern[],
int Detector::patternMatchVariance(ArrayRef<int>& counters,
const int pattern[],
int maxIndividualVariance)
{
int numCounters = counters->size();
@ -451,7 +405,7 @@ int Detector::patternMatchVariance(ArrayRef<int> counters, const int pattern[],
* @param upsideDown true if rotated by 180 degree.
*/
void Detector::correctVertices(Ref<BitMatrix> matrix,
vector<Ref<ResultPoint> > &vertices,
ArrayRef< Ref<ResultPoint> >& vertices,
bool upsideDown)
{
bool isLowLeft = abs(vertices[4]->getY() - vertices[5]->getY()) < 20.0;
@ -487,7 +441,7 @@ void Detector::correctVertices(Ref<BitMatrix> matrix,
* @param rowStep +1 if corner should be exceeded towards the bottom, -1 towards the top.
*/
void Detector::findWideBarTopBottom(Ref<BitMatrix> matrix,
vector<Ref<ResultPoint> > &vertices,
ArrayRef< Ref<ResultPoint> > &vertices,
int offsetVertice,
int startWideBar,
int lenWideBar,
@ -502,10 +456,10 @@ void Detector::findWideBarTopBottom(Ref<BitMatrix> matrix,
float barDiff = verticeEnd->getX() - verticeStart->getX();
float barStart = verticeStart->getX() + barDiff * (float)startWideBar / (float)lenPattern;
float barEnd = verticeStart->getX() + barDiff * (float)endWideBar / (float)lenPattern;
int x = round((barStart + barEnd) / 2.0f);
int x = Math::round((barStart + barEnd) / 2.0f);
// Start vertically between the preliminary vertices.
int yStart = round(verticeStart->getY());
int yStart = Math::round(verticeStart->getY());
int y = yStart;
// Find offset of thin bar to the right as additional safeguard.
@ -557,11 +511,11 @@ void Detector::findWideBarTopBottom(Ref<BitMatrix> matrix,
* @return Returns true when the result is valid and lies inside the matrix. Otherwise throws an
* exception.
**/
void Detector::findCrossingPoint(vector<Ref<ResultPoint> > &vertices,
void Detector::findCrossingPoint(ArrayRef< Ref<ResultPoint> >& vertices,
int idxResult,
int idxLineA1, int idxLineA2,
int idxLineB1, int idxLineB2,
Ref<BitMatrix> matrix)
Ref<BitMatrix>& matrix)
{
Point p1(vertices[idxLineA1]->getX(), vertices[idxLineA1]->getY());
Point p2(vertices[idxLineA2]->getX(), vertices[idxLineA2]->getY());
@ -574,13 +528,13 @@ void Detector::findCrossingPoint(vector<Ref<ResultPoint> > &vertices,
throw NotFoundException("PDF:Detector: cannot find the crossing of parallel lines!");
}
int x = round(result.x);
int y = round(result.y);
int x = Math::round(result.x);
int y = Math::round(result.y);
if (x < 0 || x >= (int)matrix->getWidth() || y < 0 || y >= (int)matrix->getHeight()) {
throw NotFoundException("PDF:Detector: crossing points out of region!");
}
vertices[idxResult] = new ResultPoint(result.x, result.y);
vertices[idxResult] = Ref<ResultPoint>(new ResultPoint(result.x, result.y));
}
/**
@ -620,8 +574,7 @@ Point Detector::intersection(Line a, Line b) {
* vertices[7] x, y bottom right codeword area
* @return the module size.
*/
float Detector::computeModuleWidth(vector<Ref<ResultPoint> > &vertices)
{
float Detector::computeModuleWidth(ArrayRef< Ref<ResultPoint> >& vertices) {
float pixels1 = ResultPoint::distance(vertices[0], vertices[4]);
float pixels2 = ResultPoint::distance(vertices[1], vertices[5]);
float moduleWidth1 = (pixels1 + pixels2) / (17 * 2.0f);
@ -642,14 +595,15 @@ float Detector::computeModuleWidth(vector<Ref<ResultPoint> > &vertices)
* @param moduleWidth estimated module size
* @return the number of modules in a row.
*/
int Detector::computeDimension(Ref<ResultPoint> topLeft,
Ref<ResultPoint> topRight,
Ref<ResultPoint> bottomLeft,
Ref<ResultPoint> bottomRight,
int Detector::computeDimension(Ref<ResultPoint> const& topLeft,
Ref<ResultPoint> const& topRight,
Ref<ResultPoint> const& bottomLeft,
Ref<ResultPoint> const& bottomRight,
float moduleWidth)
{
int topRowDimension = round(ResultPoint::distance(topLeft, topRight) / moduleWidth);
int bottomRowDimension = round(ResultPoint::distance(bottomLeft, bottomRight) / moduleWidth);
int topRowDimension = MathUtils::round(ResultPoint::distance(topLeft, topRight) / moduleWidth);
int bottomRowDimension =
MathUtils::round(ResultPoint::distance(bottomLeft, bottomRight) / moduleWidth);
return ((((topRowDimension + bottomRowDimension) >> 1) + 8) / 17) * 17;
}
@ -664,14 +618,16 @@ int Detector::computeDimension(Ref<ResultPoint> topLeft,
* @param moduleWidth estimated module size
* @return the number of modules in a row.
*/
int Detector::computeYDimension(Ref<ResultPoint> topLeft,
Ref<ResultPoint> topRight,
Ref<ResultPoint> bottomLeft,
Ref<ResultPoint> bottomRight,
int Detector::computeYDimension(Ref<ResultPoint> const& topLeft,
Ref<ResultPoint> const& topRight,
Ref<ResultPoint> const& bottomLeft,
Ref<ResultPoint> const& bottomRight,
float moduleWidth)
{
int leftColumnDimension = round(ResultPoint::distance(topLeft, bottomLeft) / moduleWidth);
int rightColumnDimension = round(ResultPoint::distance(topRight, bottomRight) / moduleWidth);
int leftColumnDimension =
MathUtils::round(ResultPoint::distance(topLeft, bottomLeft) / moduleWidth);
int rightColumnDimension =
MathUtils::round(ResultPoint::distance(topRight, bottomRight) / moduleWidth);
return (leftColumnDimension + rightColumnDimension) >> 1;
}
@ -683,8 +639,9 @@ int Detector::computeYDimension(Ref<ResultPoint> topLeft,
* @param yDimension y dimension
* @return an over-sampled BitMatrix.
*/
Ref<BitMatrix> Detector::sampleLines(const vector<Ref<ResultPoint> >& vertices, int dimensionY, int dimension)
{
Ref<BitMatrix> Detector::sampleLines(ArrayRef< Ref<ResultPoint> > const& vertices,
int dimensionY,
int dimension) {
const int sampleDimensionX = dimension * 8;
const int sampleDimensionY = dimensionY * 4;
Ref<PerspectiveTransform> transform(
@ -704,12 +661,3 @@ Ref<BitMatrix> Detector::sampleLines(const vector<Ref<ResultPoint> >& vertices,
return linesMatrix;
}
/**
* Ends up being a bit faster than Math.round(). This merely rounds its
* argument to the nearest int, where x.5 rounds up.
*/
int Detector::round(float d)
{
return (int)(d + 0.5f);
}

View file

@ -32,22 +32,24 @@ namespace detector {
class Detector {
private:
static const int INTEGER_MATH_SHIFT = 8;
static const int PATTERN_MATCH_RESULT_SCALE_FACTOR = 1 << INTEGER_MATH_SHIFT;
static const int MAX_AVG_VARIANCE;
static const int MAX_INDIVIDUAL_VARIANCE;
static const int START_PATTERN[];
static const int START_PATTERN_LENGTH;
static const int START_PATTERN_REVERSE[];
static const int START_PATTERN_REVERSE_LENGTH;
static const int STOP_PATTERN[];
static const int STOP_PATTERN_LENGTH;
static const int STOP_PATTERN_REVERSE[];
static const int SIZEOF_START_PATTERN;
static const int SIZEOF_START_PATTERN_REVERSE;
static const int SIZEOF_STOP_PATTERN;
static const int SIZEOF_STOP_PATTERN_REVERSE;
static const int COUNT_VERTICES;
static const int STOP_PATTERN_REVERSE_LENGTH;
Ref<BinaryBitmap> image_;
static std::vector<Ref<ResultPoint> > findVertices(Ref<BitMatrix> matrix, int rowStep);
static std::vector<Ref<ResultPoint> > findVertices180(Ref<BitMatrix> matrix, int rowStep);
static ArrayRef< Ref<ResultPoint> > findVertices(Ref<BitMatrix> matrix, int rowStep);
static ArrayRef< Ref<ResultPoint> > findVertices180(Ref<BitMatrix> matrix, int rowStep);
static ArrayRef<int> findGuardPattern(Ref<BitMatrix> matrix,
int column,
@ -56,41 +58,39 @@ private:
bool whiteFirst,
const int pattern[],
int patternSize,
ArrayRef<int> counters);
static int patternMatchVariance(ArrayRef<int> counters, const int pattern[],
ArrayRef<int>& counters);
static int patternMatchVariance(ArrayRef<int>& counters, const int pattern[],
int maxIndividualVariance);
static void correctVertices(Ref<BitMatrix> matrix,
std::vector<Ref<ResultPoint> > &vertices,
ArrayRef< Ref<ResultPoint> >& vertices,
bool upsideDown);
static void findWideBarTopBottom(Ref<BitMatrix> matrix,
std::vector<Ref<ResultPoint> > &vertices,
ArrayRef< Ref<ResultPoint> >& vertices,
int offsetVertice,
int startWideBar,
int lenWideBar,
int lenPattern,
int nIncrement);
static void findCrossingPoint(std::vector<Ref<ResultPoint> > &vertices,
static void findCrossingPoint(ArrayRef< Ref<ResultPoint> >& vertices,
int idxResult,
int idxLineA1,int idxLineA2,
int idxLineB1,int idxLineB2,
Ref<BitMatrix> matrix);
Ref<BitMatrix>& matrix);
static Point intersection(Line a, Line b);
static float computeModuleWidth(std::vector<Ref<ResultPoint> > &vertices);
static int computeDimension(Ref<ResultPoint> topLeft,
Ref<ResultPoint> topRight,
Ref<ResultPoint> bottomLeft,
Ref<ResultPoint> bottomRight,
static float computeModuleWidth(ArrayRef< Ref<ResultPoint> >& vertices);
static int computeDimension(Ref<ResultPoint> const& topLeft,
Ref<ResultPoint> const& topRight,
Ref<ResultPoint> const& bottomLeft,
Ref<ResultPoint> const& bottomRight,
float moduleWidth);
int computeYDimension(Ref<ResultPoint> topLeft,
Ref<ResultPoint> topRight,
Ref<ResultPoint> bottomLeft,
Ref<ResultPoint> bottomRight,
int computeYDimension(Ref<ResultPoint> const& topLeft,
Ref<ResultPoint> const& topRight,
Ref<ResultPoint> const& bottomLeft,
Ref<ResultPoint> const& bottomRight,
float moduleWidth);
Ref<BitMatrix> sampleLines(const std::vector<Ref<ResultPoint> > &vertices, int dimensionY, int dimension);
static int round(float d);
Ref<BitMatrix> sampleLines(ArrayRef< Ref<ResultPoint> > const& vertices, int dimensionY, int dimension);
public:
Detector(Ref<BinaryBitmap> image);

View file

@ -31,7 +31,6 @@
#include <sstream>
#include <cstdlib>
namespace math_utils = zxing::common::detector::math_utils;
using std::ostringstream;
using std::min;
@ -44,6 +43,7 @@ using zxing::ResultPointCallback;
using zxing::DetectorResult;
using zxing::PerspectiveTransform;
using zxing::qrcode::AlignmentPattern;
using zxing::common::detector::MathUtils;
// VC++
using zxing::DecodeHints;
@ -166,9 +166,9 @@ Ref<BitMatrix> Detector::sampleGrid(Ref<BitMatrix> image, int dimension, Ref<Per
int Detector::computeDimension(Ref<ResultPoint> topLeft, Ref<ResultPoint> topRight, Ref<ResultPoint> bottomLeft,
float moduleSize) {
int tltrCentersDimension =
math_utils::round(ResultPoint::distance(topLeft, topRight) / moduleSize);
MathUtils::round(ResultPoint::distance(topLeft, topRight) / moduleSize);
int tlblCentersDimension =
math_utils::round(ResultPoint::distance(topLeft, bottomLeft) / moduleSize);
MathUtils::round(ResultPoint::distance(topLeft, bottomLeft) / moduleSize);
int dimension = ((tltrCentersDimension + tlblCentersDimension) >> 1) + 7;
switch (dimension & 0x03) { // mod 4
case 0:
@ -269,7 +269,7 @@ float Detector::sizeOfBlackWhiteBlackRun(int fromX, int fromY, int toX, int toY)
// Does current pixel mean we have moved white to black or vice versa?
if (!((state == 1) ^ image_->get(realX, realY))) {
if (state == 2) {
return math_utils::distance(x, y, fromX, fromY);
return MathUtils::distance(x, y, fromX, fromY);
}
state++;
}
@ -287,7 +287,7 @@ float Detector::sizeOfBlackWhiteBlackRun(int fromX, int fromY, int toX, int toY)
// is "white" so this last point at (toX+xStep,toY) is the right ending. This is really a
// small approximation; (toX+xStep,toY+yStep) might be really correct. Ignore this.
if (state == 2) {
return math_utils::distance(toX + xstep, toY, fromX, fromY);
return MathUtils::distance(toX + xstep, toY, fromX, fromY);
}
// else we didn't find even black-white-black; no estimate is really possible
return nan();