C++ port: fixed warnings for Symbian build

git-svn-id: https://zxing.googlecode.com/svn/trunk@1145 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
ralf.kistner@gmail.com 2009-12-09 11:06:01 +00:00
parent 5472325ffe
commit a1083bebd4
4 changed files with 530 additions and 524 deletions

View file

@ -1,37 +1,37 @@
/* /*
* DecoderResult.cpp * DecoderResult.cpp
* zxing * zxing
* *
* Created by Christian Brunschen on 20/05/2008. * Created by Christian Brunschen on 20/05/2008.
* Copyright 2008 ZXing authors All rights reserved. * Copyright 2008 ZXing authors All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
#include <zxing/common/DecoderResult.h> #include <zxing/common/DecoderResult.h>
namespace zxing { namespace zxing {
DecoderResult::DecoderResult(ArrayRef<unsigned char> rawBytes, Ref<String> text) : DecoderResult::DecoderResult(ArrayRef<unsigned char> rawBytes, Ref<String> text) :
rawBytes_(rawBytes), text_(text) { rawBytes_(rawBytes), text_(text) {
} }
ArrayRef<unsigned char> DecoderResult::getRawBytes() { ArrayRef<unsigned char> DecoderResult::getRawBytes() {
return rawBytes_; return rawBytes_;
} }
Ref<String> DecoderResult::getText() { Ref<String> DecoderResult::getText() {
return text_; return text_;
} }
} }

View file

@ -1,261 +1,265 @@
/* /*
* Detector.cpp * Detector.cpp
* zxing * zxing
* *
* Created by Christian Brunschen on 14/05/2008. * Created by Christian Brunschen on 14/05/2008.
* Copyright 2008 ZXing authors All rights reserved. * Copyright 2008 ZXing authors All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
#include <zxing/qrcode/detector/Detector.h> #include <zxing/qrcode/detector/Detector.h>
#include <zxing/qrcode/detector/FinderPatternFinder.h> #include <zxing/qrcode/detector/FinderPatternFinder.h>
#include <zxing/qrcode/detector/FinderPattern.h> #include <zxing/qrcode/detector/FinderPattern.h>
#include <zxing/qrcode/detector/AlignmentPattern.h> #include <zxing/qrcode/detector/AlignmentPattern.h>
#include <zxing/qrcode/detector/AlignmentPatternFinder.h> #include <zxing/qrcode/detector/AlignmentPatternFinder.h>
#include <zxing/qrcode/Version.h> #include <zxing/qrcode/Version.h>
#include <zxing/common/GridSampler.h> #include <zxing/common/GridSampler.h>
#include <cmath> #include <cmath>
#include <sstream> #include <sstream>
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<DetectorResult> Detector::detect() { Ref<BitMatrix> Detector::getImage() {
FinderPatternFinder finder(image_); return image_;
Ref<FinderPatternInfo> info(finder.find()); }
Ref<FinderPattern> topLeft(info->getTopLeft()); Ref<DetectorResult> Detector::detect() {
Ref<FinderPattern> topRight(info->getTopRight()); FinderPatternFinder finder(image_);
Ref<FinderPattern> bottomLeft(info->getBottomLeft()); Ref<FinderPatternInfo> info(finder.find());
float moduleSize = calculateModuleSize(topLeft, topRight, bottomLeft); Ref<FinderPattern> topLeft(info->getTopLeft());
int dimension = computeDimension(topLeft, topRight, bottomLeft, moduleSize); Ref<FinderPattern> topRight(info->getTopRight());
Version *provisionalVersion = Version::getProvisionalVersionForDimension(dimension); Ref<FinderPattern> bottomLeft(info->getBottomLeft());
int modulesBetweenFPCenters = provisionalVersion->getDimensionForVersion() - 7;
float moduleSize = calculateModuleSize(topLeft, topRight, bottomLeft);
Ref<AlignmentPattern> alignmentPattern; int dimension = computeDimension(topLeft, topRight, bottomLeft, moduleSize);
// Anything above version 1 has an alignment pattern Version *provisionalVersion = Version::getProvisionalVersionForDimension(dimension);
if (provisionalVersion->getAlignmentPatternCenters().size() > 0) { int modulesBetweenFPCenters = provisionalVersion->getDimensionForVersion() - 7;
Ref<AlignmentPattern> alignmentPattern;
// Guess where a "bottom right" finder pattern would have been // Anything above version 1 has an alignment pattern
float bottomRightX = topRight->getX() - topLeft->getX() + bottomLeft->getX(); if (provisionalVersion->getAlignmentPatternCenters().size() > 0) {
float bottomRightY = topRight->getY() - topLeft->getY() + bottomLeft->getY();
// Guess where a "bottom right" finder pattern would have been
// Estimate that alignment pattern is closer by 3 modules float bottomRightX = topRight->getX() - topLeft->getX() + bottomLeft->getX();
// from "bottom right" to known top left location float bottomRightY = topRight->getY() - topLeft->getY() + bottomLeft->getY();
float correctionToTopLeft = 1.0f - 3.0f / (float)modulesBetweenFPCenters;
int estAlignmentX = (int)(topLeft->getX() + correctionToTopLeft * (bottomRightX - topLeft->getX()));
int estAlignmentY = (int)(topLeft->getY() + correctionToTopLeft * (bottomRightY - topLeft->getY())); // Estimate that alignment pattern is closer by 3 modules
// from "bottom right" to known top left location
float correctionToTopLeft = 1.0f - 3.0f / (float)modulesBetweenFPCenters;
// Kind of arbitrary -- expand search radius before giving up int estAlignmentX = (int)(topLeft->getX() + correctionToTopLeft * (bottomRightX - topLeft->getX()));
for (int i = 4; i <= 16; i <<= 1) { int estAlignmentY = (int)(topLeft->getY() + correctionToTopLeft * (bottomRightY - topLeft->getY()));
try {
alignmentPattern = findAlignmentInRegion(moduleSize, estAlignmentX, estAlignmentY, (float)i);
break; // Kind of arbitrary -- expand search radius before giving up
} catch (zxing::ReaderException re) { for (int i = 4; i <= 16; i <<= 1) {
// try next round try {
} alignmentPattern = findAlignmentInRegion(moduleSize, estAlignmentX, estAlignmentY, (float)i);
} break;
if (alignmentPattern == 0) { } catch (zxing::ReaderException re) {
// Try anyway // 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); Ref<PerspectiveTransform> transform = createTransform(topLeft, topRight, bottomLeft, alignmentPattern, dimension);
points[2].reset(topRight); Ref<BitMatrix> bits(sampleGrid(image_, dimension, transform));
if (alignmentPattern != 0) { std::vector<Ref<ResultPoint> > points(alignmentPattern == 0 ? 3 : 4);
points[3].reset(alignmentPattern); points[0].reset(bottomLeft);
} points[1].reset(topLeft);
points[2].reset(topRight);
Ref<DetectorResult> result(new DetectorResult(bits, points, transform)); if (alignmentPattern != 0) {
return result; points[3].reset(alignmentPattern);
} }
Ref<PerspectiveTransform> Detector::createTransform(Ref<ResultPoint> topLeft, Ref<ResultPoint> topRight, Ref < Ref<DetectorResult> result(new DetectorResult(bits, points, transform));
ResultPoint > bottomLeft, Ref<ResultPoint> alignmentPattern, int dimension) { return result;
}
float dimMinusThree = (float)dimension - 3.5f;
float bottomRightX; Ref<PerspectiveTransform> Detector::createTransform(Ref<ResultPoint> topLeft, Ref<ResultPoint> topRight, Ref <
float bottomRightY; ResultPoint > bottomLeft, Ref<ResultPoint> alignmentPattern, int dimension) {
float sourceBottomRightX;
float sourceBottomRightY; float dimMinusThree = (float)dimension - 3.5f;
if (alignmentPattern != 0) { float bottomRightX;
bottomRightX = alignmentPattern->getX(); float bottomRightY;
bottomRightY = alignmentPattern->getY(); float sourceBottomRightX;
sourceBottomRightX = sourceBottomRightY = dimMinusThree - 3.0f; float sourceBottomRightY;
} else { if (alignmentPattern != 0) {
// Don't have an alignment pattern, just make up the bottom-right point bottomRightX = alignmentPattern->getX();
bottomRightX = (topRight->getX() - topLeft->getX()) + bottomLeft->getX(); bottomRightY = alignmentPattern->getY();
bottomRightY = (topRight->getY() - topLeft->getY()) + bottomLeft->getY(); sourceBottomRightX = sourceBottomRightY = dimMinusThree - 3.0f;
sourceBottomRightX = sourceBottomRightY = dimMinusThree; } else {
} // Don't have an alignment pattern, just make up the bottom-right point
bottomRightX = (topRight->getX() - topLeft->getX()) + bottomLeft->getX();
Ref<PerspectiveTransform> transform(PerspectiveTransform::quadrilateralToQuadrilateral(3.5f, 3.5f, dimMinusThree, 3.5f, sourceBottomRightX, bottomRightY = (topRight->getY() - topLeft->getY()) + bottomLeft->getY();
sourceBottomRightY, 3.5f, dimMinusThree, topLeft->getX(), topLeft->getY(), topRight->getX(), sourceBottomRightX = sourceBottomRightY = dimMinusThree;
topRight->getY(), bottomRightX, bottomRightY, bottomLeft->getX(), bottomLeft->getY())); }
return transform; 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()));
Ref<BitMatrix> Detector::sampleGrid(Ref<BitMatrix> image, int dimension, Ref<PerspectiveTransform> transform) {
GridSampler &sampler = GridSampler::getInstance(); return transform;
return sampler.sampleGrid(image, dimension, transform); }
}
Ref<BitMatrix> Detector::sampleGrid(Ref<BitMatrix> image, int dimension, Ref<PerspectiveTransform> transform) {
int Detector::computeDimension(Ref<ResultPoint> topLeft, Ref<ResultPoint> topRight, Ref<ResultPoint> bottomLeft, GridSampler &sampler = GridSampler::getInstance();
float moduleSize) { return sampler.sampleGrid(image, dimension, transform);
int tltrCentersDimension = lround(FinderPatternFinder::distance(topLeft, topRight) / moduleSize); }
int tlblCentersDimension = lround(FinderPatternFinder::distance(topLeft, bottomLeft) / moduleSize);
int dimension = ((tltrCentersDimension + tlblCentersDimension) >> 1) + 7; int Detector::computeDimension(Ref<ResultPoint> topLeft, Ref<ResultPoint> topRight, Ref<ResultPoint> bottomLeft,
switch (dimension & 0x03) { // mod 4 float moduleSize) {
case 0: int tltrCentersDimension = lround(FinderPatternFinder::distance(topLeft, topRight) / moduleSize);
dimension++; int tlblCentersDimension = lround(FinderPatternFinder::distance(topLeft, bottomLeft) / moduleSize);
break; int dimension = ((tltrCentersDimension + tlblCentersDimension) >> 1) + 7;
// 1? do nothing switch (dimension & 0x03) { // mod 4
case 2: case 0:
dimension--; dimension++;
break; break;
case 3: // 1? do nothing
ostringstream s; case 2:
s << "Bad dimension: " << dimension; dimension--;
throw zxing::ReaderException(s.str().c_str()); break;
} case 3:
return dimension; ostringstream s;
} s << "Bad dimension: " << dimension;
throw zxing::ReaderException(s.str().c_str());
float Detector::calculateModuleSize(Ref<ResultPoint> topLeft, Ref<ResultPoint> topRight, Ref<ResultPoint> bottomLeft) { }
// Take the average return dimension;
return (calculateModuleSizeOneWay(topLeft, topRight) + calculateModuleSizeOneWay(topLeft, bottomLeft)) / 2.0f; }
}
float Detector::calculateModuleSize(Ref<ResultPoint> topLeft, Ref<ResultPoint> topRight, Ref<ResultPoint> bottomLeft) {
float Detector::calculateModuleSizeOneWay(Ref<ResultPoint> pattern, Ref<ResultPoint> otherPattern) { // Take the average
float moduleSizeEst1 = sizeOfBlackWhiteBlackRunBothWays((int)pattern->getX(), (int)pattern->getY(), return (calculateModuleSizeOneWay(topLeft, topRight) + calculateModuleSizeOneWay(topLeft, bottomLeft)) / 2.0f;
(int)otherPattern->getX(), (int)otherPattern->getY()); }
float moduleSizeEst2 = sizeOfBlackWhiteBlackRunBothWays((int)otherPattern->getX(), (int)otherPattern->getY(),
(int)pattern->getX(), (int)pattern->getY()); float Detector::calculateModuleSizeOneWay(Ref<ResultPoint> pattern, Ref<ResultPoint> otherPattern) {
if (isnan(moduleSizeEst1)) { float moduleSizeEst1 = sizeOfBlackWhiteBlackRunBothWays((int)pattern->getX(), (int)pattern->getY(),
return moduleSizeEst2; (int)otherPattern->getX(), (int)otherPattern->getY());
} float moduleSizeEst2 = sizeOfBlackWhiteBlackRunBothWays((int)otherPattern->getX(), (int)otherPattern->getY(),
if (isnan(moduleSizeEst2)) { (int)pattern->getX(), (int)pattern->getY());
return moduleSizeEst1; if (isnan(moduleSizeEst1)) {
} return moduleSizeEst2;
// 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. if (isnan(moduleSizeEst2)) {
return (moduleSizeEst1 + moduleSizeEst2) / 14.0f; return moduleSizeEst1;
} }
// Average them, and divide by 7 since we've counted the width of 3 black modules,
float Detector::sizeOfBlackWhiteBlackRunBothWays(int fromX, int fromY, int toX, int toY) { // and 1 white and 1 black module on either side. Ergo, divide sum by 14.
return (moduleSizeEst1 + moduleSizeEst2) / 14.0f;
float result = sizeOfBlackWhiteBlackRun(fromX, fromY, toX, toY); }
float Detector::sizeOfBlackWhiteBlackRunBothWays(int fromX, int fromY, int toX, int toY) {
// Now count other way -- don't run off image though of course
int otherToX = fromX - (toX - fromX); float result = sizeOfBlackWhiteBlackRun(fromX, fromY, toX, toY);
if (otherToX < 0) {
// "to" should the be the first value not included, so, the first value off
// the edge is -1 // Now count other way -- don't run off image though of course
otherToX = -1; int otherToX = fromX - (toX - fromX);
} else if (otherToX >= (int)image_->getWidth()) { if (otherToX < 0) {
otherToX = image_->getWidth(); // "to" should the be the first value not included, so, the first value off
} // the edge is -1
int otherToY = fromY - (toY - fromY); otherToX = -1;
if (otherToY < 0) { } else if (otherToX >= (int)image_->getWidth()) {
otherToY = -1; otherToX = image_->getWidth();
} else if (otherToY >= (int)image_->getHeight()) { }
otherToY = image_->getHeight(); int otherToY = fromY - (toY - fromY);
} if (otherToY < 0) {
result += sizeOfBlackWhiteBlackRun(fromX, fromY, otherToX, otherToY); otherToY = -1;
return result - 1.0f; // -1 because we counted the middle pixel twice } else if (otherToY >= (int)image_->getHeight()) {
} otherToY = image_->getHeight();
}
float Detector::sizeOfBlackWhiteBlackRun(int fromX, int fromY, int toX, int toY) { result += sizeOfBlackWhiteBlackRun(fromX, fromY, otherToX, otherToY);
// Mild variant of Bresenham's algorithm; return result - 1.0f; // -1 because we counted the middle pixel twice
// see http://en.wikipedia.org/wiki/Bresenham's_line_algorithm }
bool steep = abs(toY - fromY) > abs(toX - fromX);
if (steep) { float Detector::sizeOfBlackWhiteBlackRun(int fromX, int fromY, int toX, int toY) {
int temp = fromX; // Mild variant of Bresenham's algorithm;
fromX = fromY; // see http://en.wikipedia.org/wiki/Bresenham's_line_algorithm
fromY = temp; bool steep = abs(toY - fromY) > abs(toX - fromX);
temp = toX; if (steep) {
toX = toY; int temp = fromX;
toY = temp; fromX = fromY;
} fromY = temp;
temp = toX;
int dx = abs(toX - fromX); toX = toY;
int dy = abs(toY - fromY); toY = temp;
int error = -dx >> 1; }
int ystep = fromY < toY ? 1 : -1;
int xstep = fromX < toX ? 1 : -1; int dx = abs(toX - fromX);
int state = 0; // In black pixels, looking for white, first or second time int dy = abs(toY - fromY);
for (int x = fromX, y = fromY; x != toX; x += xstep) { int error = -dx >> 1;
int ystep = fromY < toY ? 1 : -1;
int realX = steep ? y : x; int xstep = fromX < toX ? 1 : -1;
int realY = steep ? x : y; int state = 0; // In black pixels, looking for white, first or second time
if (state == 1) { // In white pixels, looking for black for (int x = fromX, y = fromY; x != toX; x += xstep) {
if (image_->get(realX, realY)) {
state++; int realX = steep ? y : x;
} int realY = steep ? x : y;
} else { if (state == 1) { // In white pixels, looking for black
if (!image_->get(realX, realY)) { if (image_->get(realX, realY)) {
state++; state++;
} }
} } else {
if (!image_->get(realX, realY)) {
if (state == 3) { // Found black, white, black, and stumbled back onto white; done state++;
int diffX = x - fromX; }
int diffY = y - fromY; }
return (float)sqrt((double)(diffX * diffX + diffY * diffY));
} if (state == 3) { // Found black, white, black, and stumbled back onto white; done
error += dy; int diffX = x - fromX;
if (error > 0) { int diffY = y - fromY;
y += ystep; return (float)sqrt((double)(diffX * diffX + diffY * diffY));
error -= dx; }
} error += dy;
} if (error > 0) {
int diffX = toX - fromX; y += ystep;
int diffY = toY - fromY; error -= dx;
return (float)sqrt((double)(diffX * diffX + diffY * diffY)); }
} }
int diffX = toX - fromX;
Ref<AlignmentPattern> Detector::findAlignmentInRegion(float overallEstModuleSize, int estAlignmentX, int estAlignmentY, int diffY = toY - fromY;
float allowanceFactor) { return (float)sqrt((double)(diffX * diffX + diffY * diffY));
// Look for an alignment pattern (3 modules in size) around where it }
// should be
int allowance = (int)(allowanceFactor * overallEstModuleSize); Ref<AlignmentPattern> Detector::findAlignmentInRegion(float overallEstModuleSize, int estAlignmentX, int estAlignmentY,
int alignmentAreaLeftX = max(0, estAlignmentX - allowance); float allowanceFactor) {
int alignmentAreaRightX = min((int)(image_->getWidth() - 1), estAlignmentX + allowance); // Look for an alignment pattern (3 modules in size) around where it
int alignmentAreaTopY = max(0, estAlignmentY - allowance); // should be
int alignmentAreaBottomY = min((int)(image_->getHeight() - 1), estAlignmentY + allowance); int allowance = (int)(allowanceFactor * overallEstModuleSize);
int alignmentAreaLeftX = max(0, estAlignmentX - allowance);
AlignmentPatternFinder alignmentFinder(image_, alignmentAreaLeftX, alignmentAreaTopY, alignmentAreaRightX int alignmentAreaRightX = min((int)(image_->getWidth() - 1), estAlignmentX + allowance);
- alignmentAreaLeftX, alignmentAreaBottomY - alignmentAreaTopY, overallEstModuleSize); int alignmentAreaTopY = max(0, estAlignmentY - allowance);
return alignmentFinder.find(); int alignmentAreaBottomY = min((int)(image_->getHeight() - 1), estAlignmentY + allowance);
}
AlignmentPatternFinder alignmentFinder(image_, alignmentAreaLeftX, alignmentAreaTopY, alignmentAreaRightX
} - alignmentAreaLeftX, alignmentAreaBottomY - alignmentAreaTopY, overallEstModuleSize);
} return alignmentFinder.find();
}
}
}

View file

@ -1,58 +1,60 @@
#ifndef __DETECTOR_H__ #ifndef __DETECTOR_H__
#define __DETECTOR_H__ #define __DETECTOR_H__
/* /*
* Detector.h * Detector.h
* zxing * zxing
* *
* Created by Christian Brunschen on 14/05/2008. * Created by Christian Brunschen on 14/05/2008.
* Copyright 2008 ZXing authors All rights reserved. * Copyright 2008 ZXing authors All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
#include <zxing/common/Counted.h> #include <zxing/common/Counted.h>
#include <zxing/common/DetectorResult.h> #include <zxing/common/DetectorResult.h>
#include <zxing/common/BitMatrix.h> #include <zxing/common/BitMatrix.h>
#include <zxing/qrcode/detector/AlignmentPattern.h> #include <zxing/qrcode/detector/AlignmentPattern.h>
#include <zxing/common/PerspectiveTransform.h> #include <zxing/common/PerspectiveTransform.h>
namespace zxing { namespace zxing {
namespace qrcode { namespace qrcode {
class Detector : public Counted { class Detector : public Counted {
protected: private:
Ref<BitMatrix> image_; Ref<BitMatrix> image_;
protected:
static Ref<BitMatrix> sampleGrid(Ref<BitMatrix> image, int dimension, Ref<PerspectiveTransform>); Ref<BitMatrix> getImage();
static int computeDimension(Ref<ResultPoint> topLeft, Ref<ResultPoint> topRight, Ref<ResultPoint> bottomLeft,
float moduleSize); static Ref<BitMatrix> sampleGrid(Ref<BitMatrix> image, int dimension, Ref<PerspectiveTransform>);
float calculateModuleSize(Ref<ResultPoint> topLeft, Ref<ResultPoint> topRight, Ref<ResultPoint> bottomLeft); static int computeDimension(Ref<ResultPoint> topLeft, Ref<ResultPoint> topRight, Ref<ResultPoint> bottomLeft,
float calculateModuleSizeOneWay(Ref<ResultPoint> pattern, Ref<ResultPoint> otherPattern); float moduleSize);
float sizeOfBlackWhiteBlackRunBothWays(int fromX, int fromY, int toX, int toY); float calculateModuleSize(Ref<ResultPoint> topLeft, Ref<ResultPoint> topRight, Ref<ResultPoint> bottomLeft);
float sizeOfBlackWhiteBlackRun(int fromX, int fromY, int toX, int toY); float calculateModuleSizeOneWay(Ref<ResultPoint> pattern, Ref<ResultPoint> otherPattern);
Ref<AlignmentPattern> findAlignmentInRegion(float overallEstModuleSize, int estAlignmentX, int estAlignmentY, float sizeOfBlackWhiteBlackRunBothWays(int fromX, int fromY, int toX, int toY);
float allowanceFactor); float sizeOfBlackWhiteBlackRun(int fromX, int fromY, int toX, int toY);
public: Ref<AlignmentPattern> findAlignmentInRegion(float overallEstModuleSize, int estAlignmentX, int estAlignmentY,
float allowanceFactor);
virtual Ref<PerspectiveTransform> createTransform(Ref<ResultPoint> topLeft, Ref<ResultPoint> topRight, Ref < public:
ResultPoint > bottomLeft, Ref<ResultPoint> alignmentPattern, int dimension);
virtual Ref<PerspectiveTransform> createTransform(Ref<ResultPoint> topLeft, Ref<ResultPoint> topRight, Ref <
Detector(Ref<BitMatrix> image); ResultPoint > bottomLeft, Ref<ResultPoint> alignmentPattern, int dimension);
Ref<DetectorResult> detect();
}; Detector(Ref<BitMatrix> image);
} Ref<DetectorResult> detect();
} };
}
#endif // __DETECTOR_H__ }
#endif // __DETECTOR_H__

View file

@ -1,168 +1,168 @@
/* /*
* QREdgeDetector.cpp * QREdgeDetector.cpp
* zxing * zxing
* *
* Created by Ralf Kistner on 7/12/2009. * Created by Ralf Kistner on 7/12/2009.
* Copyright 2008 ZXing authors All rights reserved. * Copyright 2008 ZXing authors All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
#include <zxing/qrcode/detector/QREdgeDetector.h> #include <zxing/qrcode/detector/QREdgeDetector.h>
#include <zxing/common/EdgeDetector.h> #include <zxing/common/EdgeDetector.h>
using namespace std; using namespace std;
namespace zxing { namespace zxing {
namespace qrcode { namespace qrcode {
static const float patternEdgeThreshold = 2; static const float patternEdgeThreshold = 2;
static const int patternEdgeWidth = 3; static const int patternEdgeWidth = 3;
static const float patternEdgeSearchRatio = 1.1; static const float patternEdgeSearchRatio = 1.1;
static const int patternEdgeSkip = 2; static const int patternEdgeSkip = 2;
static const float accurateEdgeThreshold = 3.3; static const float accurateEdgeThreshold = 3.3;
static const int accurateEdgeWidth = 7; static const int accurateEdgeWidth = 7;
static const int accurateEdgeSkip = 2; static const int accurateEdgeSkip = 2;
static Point guessLastPattern(Point topLeft, Point topRight, Point bottomLeft) { static Point guessLastPattern(Point topLeft, Point topRight, Point bottomLeft) {
return Point(topRight.x - topLeft.x + bottomLeft.x, topRight.y - topLeft.y + bottomLeft.y); return Point(topRight.x - topLeft.x + bottomLeft.x, topRight.y - topLeft.y + bottomLeft.y);
} }
static Point rp(Ref<ResultPoint> rp) { static Point rp(Ref<ResultPoint> rp) {
return Point(rp->getX(), rp->getY()); return Point(rp->getX(), rp->getY());
} }
QREdgeDetector::QREdgeDetector(Ref<BitMatrix> image) : Detector(image) { } QREdgeDetector::QREdgeDetector(Ref<BitMatrix> image) : Detector(image) { }
Ref<PerspectiveTransform> QREdgeDetector::createTransform(Ref<ResultPoint> topLeft, Ref<ResultPoint> topRight, Ref < Ref<PerspectiveTransform> QREdgeDetector::createTransform(Ref<ResultPoint> topLeft, Ref<ResultPoint> topRight, Ref <
ResultPoint > bottomLeft, Ref<ResultPoint> alignmentPattern, int dimension) { ResultPoint > bottomLeft, Ref<ResultPoint> alignmentPattern, int dimension) {
if(alignmentPattern == NULL) { if(alignmentPattern == NULL) {
Point corner = findCorner(*image_.object_, rp(topLeft), rp(topRight), rp(bottomLeft), dimension); Point corner = findCorner(*Detector::getImage(), rp(topLeft), rp(topRight), rp(bottomLeft), dimension);
return get1CornerTransform(rp(topLeft), rp(topRight), rp(bottomLeft), corner, dimension); return get1CornerTransform(rp(topLeft), rp(topRight), rp(bottomLeft), corner, dimension);
} else { } else {
return Detector::createTransform(topLeft, topRight, bottomLeft, alignmentPattern, dimension); return Detector::createTransform(topLeft, topRight, bottomLeft, alignmentPattern, dimension);
} }
} }
Point QREdgeDetector::findCorner(const BitMatrix& image, Point topLeft, Point topRight, Point bottomLeft, int dimension) { Point QREdgeDetector::findCorner(const BitMatrix& image, Point topLeft, Point topRight, Point bottomLeft, int dimension) {
Point bottomRight = guessLastPattern(topLeft, topRight, bottomLeft); Point bottomRight = guessLastPattern(topLeft, topRight, bottomLeft);
Line bottomEst = findPatternEdge(image, bottomLeft, topLeft, bottomRight, false); Line bottomEst = findPatternEdge(image, bottomLeft, topLeft, bottomRight, false);
Line rightEst = findPatternEdge(image, topRight, topLeft, bottomRight, true); Line rightEst = findPatternEdge(image, topRight, topLeft, bottomRight, true);
//return EdgeDetector::intersection(bottomEst, rightEst); //return EdgeDetector::intersection(bottomEst, rightEst);
Line bottom = EdgeDetector::findLine(image, bottomEst, false, accurateEdgeWidth, accurateEdgeThreshold, accurateEdgeSkip); Line bottom = EdgeDetector::findLine(image, bottomEst, false, accurateEdgeWidth, accurateEdgeThreshold, accurateEdgeSkip);
Line right = EdgeDetector::findLine(image, rightEst, true, accurateEdgeWidth, accurateEdgeThreshold, accurateEdgeSkip); Line right = EdgeDetector::findLine(image, rightEst, true, accurateEdgeWidth, accurateEdgeThreshold, accurateEdgeSkip);
return EdgeDetector::intersection(bottom, right); return EdgeDetector::intersection(bottom, right);
} }
Line QREdgeDetector::findPatternEdge(const BitMatrix& image, Point pattern, Point opposite, Point direction, bool invert) { Line QREdgeDetector::findPatternEdge(const BitMatrix& image, Point pattern, Point opposite, Point direction, bool invert) {
Point start = endOfReverseBlackWhiteBlackRun(image, pattern, opposite); Point start = endOfReverseBlackWhiteBlackRun(image, pattern, opposite);
float dx = pattern.x - start.x; float dx = pattern.x - start.x;
float dy = pattern.y - start.y; float dy = pattern.y - start.y;
float dist = sqrt(dx*dx + dy*dy); float dist = sqrt(dx*dx + dy*dy);
float dirX = direction.x - pattern.x; float dirX = direction.x - pattern.x;
float dirY = direction.y - pattern.y; float dirY = direction.y - pattern.y;
float dirSize = sqrt(dirX*dirX + dirY*dirY); float dirSize = sqrt(dirX*dirX + dirY*dirY);
float nx = dirX/dirSize; float nx = dirX/dirSize;
float ny = dirY/dirSize; float ny = dirY/dirSize;
float search = dist * patternEdgeSearchRatio; float search = dist * patternEdgeSearchRatio;
Point a(start.x + nx*search, start.y + ny*search); Point a(start.x + nx*search, start.y + ny*search);
Point b(start.x - nx*search, start.y - ny*search); Point b(start.x - nx*search, start.y - ny*search);
return EdgeDetector::findLine(image, Line(a, b), invert, patternEdgeWidth, patternEdgeThreshold, patternEdgeSkip); return EdgeDetector::findLine(image, Line(a, b), invert, patternEdgeWidth, patternEdgeThreshold, patternEdgeSkip);
} }
Ref<PerspectiveTransform> QREdgeDetector::get1CornerTransform(Point topLeft, Point topRight, Point bottomLeft, Point corner, int dimension) { Ref<PerspectiveTransform> QREdgeDetector::get1CornerTransform(Point topLeft, Point topRight, Point bottomLeft, Point corner, int dimension) {
float dimMinusThree = (float) dimension - 3.5f; float dimMinusThree = (float) dimension - 3.5f;
Ref<PerspectiveTransform> transform(PerspectiveTransform::quadrilateralToQuadrilateral(3.5f, 3.5f, dimMinusThree, 3.5f, dimension, Ref<PerspectiveTransform> transform(PerspectiveTransform::quadrilateralToQuadrilateral(3.5f, 3.5f, dimMinusThree, 3.5f, dimension,
dimension, 3.5f, dimMinusThree, topLeft.x, topLeft.y, topRight.x, dimension, 3.5f, dimMinusThree, topLeft.x, topLeft.y, topRight.x,
topRight.y, corner.x, corner.y, bottomLeft.x, bottomLeft.y)); topRight.y, corner.x, corner.y, bottomLeft.x, bottomLeft.y));
return transform; return transform;
} }
// Adapted from "sizeOfBlackWhiteBlackRun" in zxing::qrcode::Detector // Adapted from "sizeOfBlackWhiteBlackRun" in zxing::qrcode::Detector
Point QREdgeDetector::endOfReverseBlackWhiteBlackRun(const BitMatrix& image, Point from, Point to) { Point QREdgeDetector::endOfReverseBlackWhiteBlackRun(const BitMatrix& image, Point from, Point to) {
float fromX = from.x; int fromX = (int)from.x;
float fromY = from.y; int fromY = (int)from.y;
float toX = to.x; int toX = (int)to.x;
float toY = to.y; int toY = (int)to.y;
bool steep = abs(toY - fromY) > abs(toX - fromX); bool steep = abs(toY - fromY) > abs(toX - fromX);
if (steep) { if (steep) {
int temp = fromX; int temp = fromX;
fromX = fromY; fromX = fromY;
fromY = temp; fromY = temp;
temp = toX; temp = toX;
toX = toY; toX = toY;
toY = temp; toY = temp;
} }
int dx = abs(toX - fromX); int dx = abs(toX - fromX);
int dy = abs(toY - fromY); int dy = abs(toY - fromY);
int error = -dx >> 1; int error = -dx >> 1;
int ystep = fromY < toY ? -1 : 1; int ystep = fromY < toY ? -1 : 1;
int xstep = fromX < toX ? -1 : 1; int xstep = fromX < toX ? -1 : 1;
int state = 0; // In black pixels, looking for white, first or second time int state = 0; // In black pixels, looking for white, first or second time
// In case there are no points, prepopulate to from // In case there are no points, prepopulate to from
int realX = from.x; int realX = fromX;
int realY = from.y; int realY = fromY;
for (int x = fromX, y = fromY; x != toX; x += xstep) { for (int x = fromX, y = fromY; x != toX; x += xstep) {
realX = steep ? y : x; realX = steep ? y : x;
realY = steep ? x : y; realY = steep ? x : y;
if(realX < 0 || realY < 0 || realX >= (int)image.getWidth() || realY >= (int)image.getHeight()) if(realX < 0 || realY < 0 || realX >= (int)image.getWidth() || realY >= (int)image.getHeight())
break; break;
if (state == 1) { // In white pixels, looking for black if (state == 1) { // In white pixels, looking for black
if (image.get(realX, realY)) { if (image.get(realX, realY)) {
state++; state++;
} }
} else { } else {
if (!image.get(realX, realY)) { if (!image.get(realX, realY)) {
state++; state++;
} }
} }
if (state == 3) { // Found black, white, black, and stumbled back onto white; done if (state == 3) { // Found black, white, black, and stumbled back onto white; done
return Point(realX, realY); return Point(realX, realY);
} }
error += dy; error += dy;
if (error > 0) { if (error > 0) {
y += ystep; y += ystep;
error -= dx; error -= dx;
} }
} }
// B-W-B run not found, return the last point visited. // B-W-B run not found, return the last point visited.
return Point(realX, realY); return Point(realX, realY);
} }
} // namespace qrcode } // namespace qrcode
} // namespace zxing } // namespace zxing