mirror of
https://github.com/zxing/zxing.git
synced 2025-02-02 05:41:08 -08:00
tabs to spaces
git-svn-id: https://zxing.googlecode.com/svn/trunk@2487 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
parent
eb7b65365b
commit
036918d4c0
|
@ -34,271 +34,271 @@
|
||||||
namespace math_utils = zxing::common::detector::math_utils;
|
namespace math_utils = zxing::common::detector::math_utils;
|
||||||
|
|
||||||
namespace zxing {
|
namespace zxing {
|
||||||
namespace qrcode {
|
namespace qrcode {
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
Detector::Detector(Ref<BitMatrix> image) :
|
Detector::Detector(Ref<BitMatrix> image) :
|
||||||
image_(image) {
|
image_(image) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<BitMatrix> Detector::getImage() const {
|
Ref<BitMatrix> Detector::getImage() const {
|
||||||
return image_;
|
return image_;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<ResultPointCallback> Detector::getResultPointCallback() const {
|
Ref<ResultPointCallback> Detector::getResultPointCallback() const {
|
||||||
return callback_;
|
return callback_;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<DetectorResult> Detector::detect(DecodeHints const& hints) {
|
Ref<DetectorResult> Detector::detect(DecodeHints const& hints) {
|
||||||
callback_ = hints.getResultPointCallback();
|
callback_ = hints.getResultPointCallback();
|
||||||
FinderPatternFinder finder(image_, hints.getResultPointCallback());
|
FinderPatternFinder finder(image_, hints.getResultPointCallback());
|
||||||
Ref<FinderPatternInfo> info(finder.find(hints));
|
Ref<FinderPatternInfo> info(finder.find(hints));
|
||||||
return processFinderPatternInfo(info);
|
return processFinderPatternInfo(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<DetectorResult> Detector::processFinderPatternInfo(Ref<FinderPatternInfo> info){
|
Ref<DetectorResult> Detector::processFinderPatternInfo(Ref<FinderPatternInfo> info){
|
||||||
Ref<FinderPattern> topLeft(info->getTopLeft());
|
Ref<FinderPattern> topLeft(info->getTopLeft());
|
||||||
Ref<FinderPattern> topRight(info->getTopRight());
|
Ref<FinderPattern> topRight(info->getTopRight());
|
||||||
Ref<FinderPattern> bottomLeft(info->getBottomLeft());
|
Ref<FinderPattern> bottomLeft(info->getBottomLeft());
|
||||||
|
|
||||||
float moduleSize = calculateModuleSize(topLeft, topRight, bottomLeft);
|
float moduleSize = calculateModuleSize(topLeft, topRight, bottomLeft);
|
||||||
if (moduleSize < 1.0f) {
|
if (moduleSize < 1.0f) {
|
||||||
throw zxing::ReaderException("bad module size");
|
throw zxing::ReaderException("bad module size");
|
||||||
}
|
}
|
||||||
int dimension = computeDimension(topLeft, topRight, bottomLeft, moduleSize);
|
int dimension = computeDimension(topLeft, topRight, bottomLeft, moduleSize);
|
||||||
Version *provisionalVersion = Version::getProvisionalVersionForDimension(dimension);
|
Version *provisionalVersion = Version::getProvisionalVersionForDimension(dimension);
|
||||||
int modulesBetweenFPCenters = provisionalVersion->getDimensionForVersion() - 7;
|
int modulesBetweenFPCenters = provisionalVersion->getDimensionForVersion() - 7;
|
||||||
|
|
||||||
Ref<AlignmentPattern> alignmentPattern;
|
Ref<AlignmentPattern> alignmentPattern;
|
||||||
// Anything above version 1 has an alignment pattern
|
// Anything above version 1 has an alignment pattern
|
||||||
if (provisionalVersion->getAlignmentPatternCenters().size() > 0) {
|
if (provisionalVersion->getAlignmentPatternCenters().size() > 0) {
|
||||||
|
|
||||||
|
|
||||||
// Guess where a "bottom right" finder pattern would have been
|
// Guess where a "bottom right" finder pattern would have been
|
||||||
float bottomRightX = topRight->getX() - topLeft->getX() + bottomLeft->getX();
|
float bottomRightX = topRight->getX() - topLeft->getX() + bottomLeft->getX();
|
||||||
float bottomRightY = topRight->getY() - topLeft->getY() + bottomLeft->getY();
|
float bottomRightY = topRight->getY() - topLeft->getY() + bottomLeft->getY();
|
||||||
|
|
||||||
|
|
||||||
// Estimate that alignment pattern is closer by 3 modules
|
// Estimate that alignment pattern is closer by 3 modules
|
||||||
// from "bottom right" to known top left location
|
// from "bottom right" to known top left location
|
||||||
float correctionToTopLeft = 1.0f - 3.0f / (float)modulesBetweenFPCenters;
|
float correctionToTopLeft = 1.0f - 3.0f / (float)modulesBetweenFPCenters;
|
||||||
int estAlignmentX = (int)(topLeft->getX() + correctionToTopLeft * (bottomRightX - topLeft->getX()));
|
int estAlignmentX = (int)(topLeft->getX() + correctionToTopLeft * (bottomRightX - topLeft->getX()));
|
||||||
int estAlignmentY = (int)(topLeft->getY() + correctionToTopLeft * (bottomRightY - topLeft->getY()));
|
int estAlignmentY = (int)(topLeft->getY() + correctionToTopLeft * (bottomRightY - topLeft->getY()));
|
||||||
|
|
||||||
|
|
||||||
// Kind of arbitrary -- expand search radius before giving up
|
// Kind of arbitrary -- expand search radius before giving up
|
||||||
for (int i = 4; i <= 16; i <<= 1) {
|
for (int i = 4; i <= 16; i <<= 1) {
|
||||||
try {
|
try {
|
||||||
alignmentPattern = findAlignmentInRegion(moduleSize, estAlignmentX, estAlignmentY, (float)i);
|
alignmentPattern = findAlignmentInRegion(moduleSize, estAlignmentX, estAlignmentY, (float)i);
|
||||||
|
break;
|
||||||
|
} catch (zxing::ReaderException const& re) {
|
||||||
|
// try next round
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (alignmentPattern == 0) {
|
||||||
|
// Try anyway
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Ref<PerspectiveTransform> transform = createTransform(topLeft, topRight, bottomLeft, alignmentPattern, dimension);
|
||||||
|
Ref<BitMatrix> bits(sampleGrid(image_, dimension, transform));
|
||||||
|
std::vector<Ref<ResultPoint> > points(alignmentPattern == 0 ? 3 : 4);
|
||||||
|
points[0].reset(bottomLeft);
|
||||||
|
points[1].reset(topLeft);
|
||||||
|
points[2].reset(topRight);
|
||||||
|
if (alignmentPattern != 0) {
|
||||||
|
points[3].reset(alignmentPattern);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ref<DetectorResult> result(new DetectorResult(bits, points));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ref<PerspectiveTransform> Detector::createTransform(Ref<ResultPoint> topLeft, Ref<ResultPoint> topRight, Ref <
|
||||||
|
ResultPoint > bottomLeft, Ref<ResultPoint> alignmentPattern, int dimension) {
|
||||||
|
|
||||||
|
float dimMinusThree = (float)dimension - 3.5f;
|
||||||
|
float bottomRightX;
|
||||||
|
float bottomRightY;
|
||||||
|
float sourceBottomRightX;
|
||||||
|
float sourceBottomRightY;
|
||||||
|
if (alignmentPattern != 0) {
|
||||||
|
bottomRightX = alignmentPattern->getX();
|
||||||
|
bottomRightY = alignmentPattern->getY();
|
||||||
|
sourceBottomRightX = dimMinusThree - 3.0f;
|
||||||
|
sourceBottomRightY = sourceBottomRightX;
|
||||||
|
} else {
|
||||||
|
// Don't have an alignment pattern, just make up the bottom-right point
|
||||||
|
bottomRightX = (topRight->getX() - topLeft->getX()) + bottomLeft->getX();
|
||||||
|
bottomRightY = (topRight->getY() - topLeft->getY()) + bottomLeft->getY();
|
||||||
|
sourceBottomRightX = dimMinusThree;
|
||||||
|
sourceBottomRightY = dimMinusThree;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ref<PerspectiveTransform> transform(PerspectiveTransform::quadrilateralToQuadrilateral(3.5f, 3.5f, dimMinusThree, 3.5f, sourceBottomRightX,
|
||||||
|
sourceBottomRightY, 3.5f, dimMinusThree, topLeft->getX(), topLeft->getY(), topRight->getX(),
|
||||||
|
topRight->getY(), bottomRightX, bottomRightY, bottomLeft->getX(), bottomLeft->getY()));
|
||||||
|
|
||||||
|
return transform;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ref<BitMatrix> Detector::sampleGrid(Ref<BitMatrix> image, int dimension, Ref<PerspectiveTransform> transform) {
|
||||||
|
GridSampler &sampler = GridSampler::getInstance();
|
||||||
|
return sampler.sampleGrid(image, dimension, transform);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Detector::computeDimension(Ref<ResultPoint> topLeft, Ref<ResultPoint> topRight, Ref<ResultPoint> bottomLeft,
|
||||||
|
float moduleSize) {
|
||||||
|
int tltrCentersDimension =
|
||||||
|
math_utils::round(ResultPoint::distance(topLeft, topRight) / moduleSize);
|
||||||
|
int tlblCentersDimension =
|
||||||
|
math_utils::round(ResultPoint::distance(topLeft, bottomLeft) / moduleSize);
|
||||||
|
int dimension = ((tltrCentersDimension + tlblCentersDimension) >> 1) + 7;
|
||||||
|
switch (dimension & 0x03) { // mod 4
|
||||||
|
case 0:
|
||||||
|
dimension++;
|
||||||
break;
|
break;
|
||||||
} catch (zxing::ReaderException const& re) {
|
// 1? do nothing
|
||||||
// try next round
|
case 2:
|
||||||
|
dimension--;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
ostringstream s;
|
||||||
|
s << "Bad dimension: " << dimension;
|
||||||
|
throw zxing::ReaderException(s.str().c_str());
|
||||||
}
|
}
|
||||||
}
|
return dimension;
|
||||||
if (alignmentPattern == 0) {
|
|
||||||
// Try anyway
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
float Detector::calculateModuleSize(Ref<ResultPoint> topLeft, Ref<ResultPoint> topRight, Ref<ResultPoint> bottomLeft) {
|
||||||
|
// Take the average
|
||||||
Ref<PerspectiveTransform> transform = createTransform(topLeft, topRight, bottomLeft, alignmentPattern, dimension);
|
return (calculateModuleSizeOneWay(topLeft, topRight) + calculateModuleSizeOneWay(topLeft, bottomLeft)) / 2.0f;
|
||||||
Ref<BitMatrix> bits(sampleGrid(image_, dimension, transform));
|
|
||||||
std::vector<Ref<ResultPoint> > points(alignmentPattern == 0 ? 3 : 4);
|
|
||||||
points[0].reset(bottomLeft);
|
|
||||||
points[1].reset(topLeft);
|
|
||||||
points[2].reset(topRight);
|
|
||||||
if (alignmentPattern != 0) {
|
|
||||||
points[3].reset(alignmentPattern);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ref<DetectorResult> result(new DetectorResult(bits, points));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ref<PerspectiveTransform> Detector::createTransform(Ref<ResultPoint> topLeft, Ref<ResultPoint> topRight, Ref <
|
|
||||||
ResultPoint > bottomLeft, Ref<ResultPoint> alignmentPattern, int dimension) {
|
|
||||||
|
|
||||||
float dimMinusThree = (float)dimension - 3.5f;
|
|
||||||
float bottomRightX;
|
|
||||||
float bottomRightY;
|
|
||||||
float sourceBottomRightX;
|
|
||||||
float sourceBottomRightY;
|
|
||||||
if (alignmentPattern != 0) {
|
|
||||||
bottomRightX = alignmentPattern->getX();
|
|
||||||
bottomRightY = alignmentPattern->getY();
|
|
||||||
sourceBottomRightX = dimMinusThree - 3.0f;
|
|
||||||
sourceBottomRightY = sourceBottomRightX;
|
|
||||||
} else {
|
|
||||||
// Don't have an alignment pattern, just make up the bottom-right point
|
|
||||||
bottomRightX = (topRight->getX() - topLeft->getX()) + bottomLeft->getX();
|
|
||||||
bottomRightY = (topRight->getY() - topLeft->getY()) + bottomLeft->getY();
|
|
||||||
sourceBottomRightX = dimMinusThree;
|
|
||||||
sourceBottomRightY = dimMinusThree;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ref<PerspectiveTransform> transform(PerspectiveTransform::quadrilateralToQuadrilateral(3.5f, 3.5f, dimMinusThree, 3.5f, sourceBottomRightX,
|
|
||||||
sourceBottomRightY, 3.5f, dimMinusThree, topLeft->getX(), topLeft->getY(), topRight->getX(),
|
|
||||||
topRight->getY(), bottomRightX, bottomRightY, bottomLeft->getX(), bottomLeft->getY()));
|
|
||||||
|
|
||||||
return transform;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ref<BitMatrix> Detector::sampleGrid(Ref<BitMatrix> image, int dimension, Ref<PerspectiveTransform> transform) {
|
|
||||||
GridSampler &sampler = GridSampler::getInstance();
|
|
||||||
return sampler.sampleGrid(image, dimension, transform);
|
|
||||||
}
|
|
||||||
|
|
||||||
int Detector::computeDimension(Ref<ResultPoint> topLeft, Ref<ResultPoint> topRight, Ref<ResultPoint> bottomLeft,
|
|
||||||
float moduleSize) {
|
|
||||||
int tltrCentersDimension =
|
|
||||||
math_utils::round(ResultPoint::distance(topLeft, topRight) / moduleSize);
|
|
||||||
int tlblCentersDimension =
|
|
||||||
math_utils::round(ResultPoint::distance(topLeft, bottomLeft) / moduleSize);
|
|
||||||
int dimension = ((tltrCentersDimension + tlblCentersDimension) >> 1) + 7;
|
|
||||||
switch (dimension & 0x03) { // mod 4
|
|
||||||
case 0:
|
|
||||||
dimension++;
|
|
||||||
break;
|
|
||||||
// 1? do nothing
|
|
||||||
case 2:
|
|
||||||
dimension--;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
ostringstream s;
|
|
||||||
s << "Bad dimension: " << dimension;
|
|
||||||
throw zxing::ReaderException(s.str().c_str());
|
|
||||||
}
|
|
||||||
return dimension;
|
|
||||||
}
|
|
||||||
|
|
||||||
float Detector::calculateModuleSize(Ref<ResultPoint> topLeft, Ref<ResultPoint> topRight, Ref<ResultPoint> bottomLeft) {
|
|
||||||
// Take the average
|
|
||||||
return (calculateModuleSizeOneWay(topLeft, topRight) + calculateModuleSizeOneWay(topLeft, bottomLeft)) / 2.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
float Detector::calculateModuleSizeOneWay(Ref<ResultPoint> pattern, Ref<ResultPoint> otherPattern) {
|
|
||||||
float moduleSizeEst1 = sizeOfBlackWhiteBlackRunBothWays((int)pattern->getX(), (int)pattern->getY(),
|
|
||||||
(int)otherPattern->getX(), (int)otherPattern->getY());
|
|
||||||
float moduleSizeEst2 = sizeOfBlackWhiteBlackRunBothWays((int)otherPattern->getX(), (int)otherPattern->getY(),
|
|
||||||
(int)pattern->getX(), (int)pattern->getY());
|
|
||||||
if (isnan(moduleSizeEst1)) {
|
|
||||||
return moduleSizeEst2;
|
|
||||||
}
|
|
||||||
if (isnan(moduleSizeEst2)) {
|
|
||||||
return moduleSizeEst1;
|
|
||||||
}
|
|
||||||
// Average them, and divide by 7 since we've counted the width of 3 black modules,
|
|
||||||
// and 1 white and 1 black module on either side. Ergo, divide sum by 14.
|
|
||||||
return (moduleSizeEst1 + moduleSizeEst2) / 14.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
float Detector::sizeOfBlackWhiteBlackRunBothWays(int fromX, int fromY, int toX, int toY) {
|
|
||||||
|
|
||||||
float result = sizeOfBlackWhiteBlackRun(fromX, fromY, toX, toY);
|
|
||||||
|
|
||||||
// Now count other way -- don't run off image though of course
|
|
||||||
float scale = 1.0f;
|
|
||||||
int otherToX = fromX - (toX - fromX);
|
|
||||||
if (otherToX < 0) {
|
|
||||||
scale = (float) fromX / (float) (fromX - otherToX);
|
|
||||||
otherToX = 0;
|
|
||||||
} else if (otherToX >= (int)image_->getWidth()) {
|
|
||||||
scale = (float) (image_->getWidth() - 1 - fromX) / (float) (otherToX - fromX);
|
|
||||||
otherToX = image_->getWidth() - 1;
|
|
||||||
}
|
|
||||||
int otherToY = (int) (fromY - (toY - fromY) * scale);
|
|
||||||
|
|
||||||
scale = 1.0f;
|
|
||||||
if (otherToY < 0) {
|
|
||||||
scale = (float) fromY / (float) (fromY - otherToY);
|
|
||||||
otherToY = 0;
|
|
||||||
} else if (otherToY >= (int)image_->getHeight()) {
|
|
||||||
scale = (float) (image_->getHeight() - 1 - fromY) / (float) (otherToY - fromY);
|
|
||||||
otherToY = image_->getHeight() - 1;
|
|
||||||
}
|
|
||||||
otherToX = (int) (fromX + (otherToX - fromX) * scale);
|
|
||||||
|
|
||||||
result += sizeOfBlackWhiteBlackRun(fromX, fromY, otherToX, otherToY);
|
|
||||||
|
|
||||||
// Middle pixel is double-counted this way; subtract 1
|
|
||||||
return result - 1.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
float Detector::sizeOfBlackWhiteBlackRun(int fromX, int fromY, int toX, int toY) {
|
|
||||||
// Mild variant of Bresenham's algorithm;
|
|
||||||
// see http://en.wikipedia.org/wiki/Bresenham's_line_algorithm
|
|
||||||
bool steep = abs(toY - fromY) > abs(toX - fromX);
|
|
||||||
if (steep) {
|
|
||||||
int temp = fromX;
|
|
||||||
fromX = fromY;
|
|
||||||
fromY = temp;
|
|
||||||
temp = toX;
|
|
||||||
toX = toY;
|
|
||||||
toY = temp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int dx = abs(toX - fromX);
|
float Detector::calculateModuleSizeOneWay(Ref<ResultPoint> pattern, Ref<ResultPoint> otherPattern) {
|
||||||
int dy = abs(toY - fromY);
|
float moduleSizeEst1 = sizeOfBlackWhiteBlackRunBothWays((int)pattern->getX(), (int)pattern->getY(),
|
||||||
int error = -dx >> 1;
|
(int)otherPattern->getX(), (int)otherPattern->getY());
|
||||||
int xstep = fromX < toX ? 1 : -1;
|
float moduleSizeEst2 = sizeOfBlackWhiteBlackRunBothWays((int)otherPattern->getX(), (int)otherPattern->getY(),
|
||||||
int ystep = fromY < toY ? 1 : -1;
|
(int)pattern->getX(), (int)pattern->getY());
|
||||||
|
if (isnan(moduleSizeEst1)) {
|
||||||
|
return moduleSizeEst2;
|
||||||
|
}
|
||||||
|
if (isnan(moduleSizeEst2)) {
|
||||||
|
return moduleSizeEst1;
|
||||||
|
}
|
||||||
|
// Average them, and divide by 7 since we've counted the width of 3 black modules,
|
||||||
|
// and 1 white and 1 black module on either side. Ergo, divide sum by 14.
|
||||||
|
return (moduleSizeEst1 + moduleSizeEst2) / 14.0f;
|
||||||
|
}
|
||||||
|
|
||||||
// In black pixels, looking for white, first or second time.
|
float Detector::sizeOfBlackWhiteBlackRunBothWays(int fromX, int fromY, int toX, int toY) {
|
||||||
int state = 0;
|
|
||||||
// Loop up until x == toX, but not beyond
|
|
||||||
int xLimit = toX + xstep;
|
|
||||||
for (int x = fromX, y = fromY; x != xLimit; x += xstep) {
|
|
||||||
int realX = steep ? y : x;
|
|
||||||
int realY = steep ? x : y;
|
|
||||||
|
|
||||||
// Does current pixel mean we have moved white to black or vice versa?
|
float result = sizeOfBlackWhiteBlackRun(fromX, fromY, toX, toY);
|
||||||
if (!((state == 1) ^ image_->get(realX, realY))) {
|
|
||||||
if (state == 2) {
|
// Now count other way -- don't run off image though of course
|
||||||
return math_utils::distance(x, y, fromX, fromY);
|
float scale = 1.0f;
|
||||||
|
int otherToX = fromX - (toX - fromX);
|
||||||
|
if (otherToX < 0) {
|
||||||
|
scale = (float) fromX / (float) (fromX - otherToX);
|
||||||
|
otherToX = 0;
|
||||||
|
} else if (otherToX >= (int)image_->getWidth()) {
|
||||||
|
scale = (float) (image_->getWidth() - 1 - fromX) / (float) (otherToX - fromX);
|
||||||
|
otherToX = image_->getWidth() - 1;
|
||||||
|
}
|
||||||
|
int otherToY = (int) (fromY - (toY - fromY) * scale);
|
||||||
|
|
||||||
|
scale = 1.0f;
|
||||||
|
if (otherToY < 0) {
|
||||||
|
scale = (float) fromY / (float) (fromY - otherToY);
|
||||||
|
otherToY = 0;
|
||||||
|
} else if (otherToY >= (int)image_->getHeight()) {
|
||||||
|
scale = (float) (image_->getHeight() - 1 - fromY) / (float) (otherToY - fromY);
|
||||||
|
otherToY = image_->getHeight() - 1;
|
||||||
|
}
|
||||||
|
otherToX = (int) (fromX + (otherToX - fromX) * scale);
|
||||||
|
|
||||||
|
result += sizeOfBlackWhiteBlackRun(fromX, fromY, otherToX, otherToY);
|
||||||
|
|
||||||
|
// Middle pixel is double-counted this way; subtract 1
|
||||||
|
return result - 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
float Detector::sizeOfBlackWhiteBlackRun(int fromX, int fromY, int toX, int toY) {
|
||||||
|
// Mild variant of Bresenham's algorithm;
|
||||||
|
// see http://en.wikipedia.org/wiki/Bresenham's_line_algorithm
|
||||||
|
bool steep = abs(toY - fromY) > abs(toX - fromX);
|
||||||
|
if (steep) {
|
||||||
|
int temp = fromX;
|
||||||
|
fromX = fromY;
|
||||||
|
fromY = temp;
|
||||||
|
temp = toX;
|
||||||
|
toX = toY;
|
||||||
|
toY = temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dx = abs(toX - fromX);
|
||||||
|
int dy = abs(toY - fromY);
|
||||||
|
int error = -dx >> 1;
|
||||||
|
int xstep = fromX < toX ? 1 : -1;
|
||||||
|
int ystep = fromY < toY ? 1 : -1;
|
||||||
|
|
||||||
|
// In black pixels, looking for white, first or second time.
|
||||||
|
int state = 0;
|
||||||
|
// Loop up until x == toX, but not beyond
|
||||||
|
int xLimit = toX + xstep;
|
||||||
|
for (int x = fromX, y = fromY; x != xLimit; x += xstep) {
|
||||||
|
int realX = steep ? y : x;
|
||||||
|
int realY = steep ? x : y;
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
state++;
|
||||||
}
|
}
|
||||||
state++;
|
|
||||||
}
|
|
||||||
|
|
||||||
error += dy;
|
error += dy;
|
||||||
if (error > 0) {
|
if (error > 0) {
|
||||||
if (y == toY) {
|
if (y == toY) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
y += ystep;
|
||||||
|
error -= dx;
|
||||||
}
|
}
|
||||||
y += ystep;
|
|
||||||
error -= dx;
|
|
||||||
}
|
}
|
||||||
|
// Found black-white-black; give the benefit of the doubt that the next pixel outside the image
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
// else we didn't find even black-white-black; no estimate is really possible
|
||||||
|
return NAN;
|
||||||
}
|
}
|
||||||
// Found black-white-black; give the benefit of the doubt that the next pixel outside the image
|
|
||||||
// is "white" so this last point at (toX+xStep,toY) is the right ending. This is really a
|
Ref<AlignmentPattern> Detector::findAlignmentInRegion(float overallEstModuleSize, int estAlignmentX, int estAlignmentY,
|
||||||
// small approximation; (toX+xStep,toY+yStep) might be really correct. Ignore this.
|
float allowanceFactor) {
|
||||||
if (state == 2) {
|
// Look for an alignment pattern (3 modules in size) around where it
|
||||||
return math_utils::distance(toX + xstep, toY, fromX, fromY);
|
// should be
|
||||||
|
int allowance = (int)(allowanceFactor * overallEstModuleSize);
|
||||||
|
int alignmentAreaLeftX = max(0, estAlignmentX - allowance);
|
||||||
|
int alignmentAreaRightX = min((int)(image_->getWidth() - 1), estAlignmentX + allowance);
|
||||||
|
if (alignmentAreaRightX - alignmentAreaLeftX < overallEstModuleSize * 3) {
|
||||||
|
throw zxing::ReaderException("region too small to hold alignment pattern");
|
||||||
|
}
|
||||||
|
int alignmentAreaTopY = max(0, estAlignmentY - allowance);
|
||||||
|
int alignmentAreaBottomY = min((int)(image_->getHeight() - 1), estAlignmentY + allowance);
|
||||||
|
if (alignmentAreaBottomY - alignmentAreaTopY < overallEstModuleSize * 3) {
|
||||||
|
throw zxing::ReaderException("region too small to hold alignment pattern");
|
||||||
|
}
|
||||||
|
|
||||||
|
AlignmentPatternFinder alignmentFinder(image_, alignmentAreaLeftX, alignmentAreaTopY, alignmentAreaRightX
|
||||||
|
- alignmentAreaLeftX, alignmentAreaBottomY - alignmentAreaTopY, overallEstModuleSize, callback_);
|
||||||
|
return alignmentFinder.find();
|
||||||
}
|
}
|
||||||
// else we didn't find even black-white-black; no estimate is really possible
|
|
||||||
return NAN;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ref<AlignmentPattern> Detector::findAlignmentInRegion(float overallEstModuleSize, int estAlignmentX, int estAlignmentY,
|
|
||||||
float allowanceFactor) {
|
|
||||||
// Look for an alignment pattern (3 modules in size) around where it
|
|
||||||
// should be
|
|
||||||
int allowance = (int)(allowanceFactor * overallEstModuleSize);
|
|
||||||
int alignmentAreaLeftX = max(0, estAlignmentX - allowance);
|
|
||||||
int alignmentAreaRightX = min((int)(image_->getWidth() - 1), estAlignmentX + allowance);
|
|
||||||
if (alignmentAreaRightX - alignmentAreaLeftX < overallEstModuleSize * 3) {
|
|
||||||
throw zxing::ReaderException("region too small to hold alignment pattern");
|
|
||||||
}
|
}
|
||||||
int alignmentAreaTopY = max(0, estAlignmentY - allowance);
|
|
||||||
int alignmentAreaBottomY = min((int)(image_->getHeight() - 1), estAlignmentY + allowance);
|
|
||||||
if (alignmentAreaBottomY - alignmentAreaTopY < overallEstModuleSize * 3) {
|
|
||||||
throw zxing::ReaderException("region too small to hold alignment pattern");
|
|
||||||
}
|
|
||||||
|
|
||||||
AlignmentPatternFinder alignmentFinder(image_, alignmentAreaLeftX, alignmentAreaTopY, alignmentAreaRightX
|
|
||||||
- alignmentAreaLeftX, alignmentAreaBottomY - alignmentAreaTopY, overallEstModuleSize, callback_);
|
|
||||||
return alignmentFinder.find();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue