mirror of
https://github.com/zxing/zxing.git
synced 2025-01-12 19:57:27 -08:00
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:
parent
5472325ffe
commit
a1083bebd4
|
@ -1,37 +1,37 @@
|
|||
/*
|
||||
* DecoderResult.cpp
|
||||
* zxing
|
||||
*
|
||||
* Created by Christian Brunschen on 20/05/2008.
|
||||
* Copyright 2008 ZXing authors All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <zxing/common/DecoderResult.h>
|
||||
|
||||
namespace zxing {
|
||||
|
||||
DecoderResult::DecoderResult(ArrayRef<unsigned char> rawBytes, Ref<String> text) :
|
||||
rawBytes_(rawBytes), text_(text) {
|
||||
}
|
||||
|
||||
ArrayRef<unsigned char> DecoderResult::getRawBytes() {
|
||||
return rawBytes_;
|
||||
}
|
||||
|
||||
Ref<String> DecoderResult::getText() {
|
||||
return text_;
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* DecoderResult.cpp
|
||||
* zxing
|
||||
*
|
||||
* Created by Christian Brunschen on 20/05/2008.
|
||||
* Copyright 2008 ZXing authors All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <zxing/common/DecoderResult.h>
|
||||
|
||||
namespace zxing {
|
||||
|
||||
DecoderResult::DecoderResult(ArrayRef<unsigned char> rawBytes, Ref<String> text) :
|
||||
rawBytes_(rawBytes), text_(text) {
|
||||
}
|
||||
|
||||
ArrayRef<unsigned char> DecoderResult::getRawBytes() {
|
||||
return rawBytes_;
|
||||
}
|
||||
|
||||
Ref<String> DecoderResult::getText() {
|
||||
return text_;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,261 +1,265 @@
|
|||
/*
|
||||
* Detector.cpp
|
||||
* zxing
|
||||
*
|
||||
* Created by Christian Brunschen on 14/05/2008.
|
||||
* Copyright 2008 ZXing authors All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <zxing/qrcode/detector/Detector.h>
|
||||
#include <zxing/qrcode/detector/FinderPatternFinder.h>
|
||||
#include <zxing/qrcode/detector/FinderPattern.h>
|
||||
#include <zxing/qrcode/detector/AlignmentPattern.h>
|
||||
#include <zxing/qrcode/detector/AlignmentPatternFinder.h>
|
||||
#include <zxing/qrcode/Version.h>
|
||||
#include <zxing/common/GridSampler.h>
|
||||
#include <cmath>
|
||||
#include <sstream>
|
||||
|
||||
namespace zxing {
|
||||
namespace qrcode {
|
||||
|
||||
using namespace std;
|
||||
|
||||
Detector::Detector(Ref<BitMatrix> image) :
|
||||
image_(image) {
|
||||
}
|
||||
|
||||
Ref<DetectorResult> Detector::detect() {
|
||||
FinderPatternFinder finder(image_);
|
||||
Ref<FinderPatternInfo> info(finder.find());
|
||||
|
||||
Ref<FinderPattern> topLeft(info->getTopLeft());
|
||||
Ref<FinderPattern> topRight(info->getTopRight());
|
||||
Ref<FinderPattern> bottomLeft(info->getBottomLeft());
|
||||
|
||||
float moduleSize = calculateModuleSize(topLeft, topRight, bottomLeft);
|
||||
int dimension = computeDimension(topLeft, topRight, bottomLeft, moduleSize);
|
||||
Version *provisionalVersion = Version::getProvisionalVersionForDimension(dimension);
|
||||
int modulesBetweenFPCenters = provisionalVersion->getDimensionForVersion() - 7;
|
||||
|
||||
Ref<AlignmentPattern> alignmentPattern;
|
||||
// Anything above version 1 has an alignment pattern
|
||||
if (provisionalVersion->getAlignmentPatternCenters().size() > 0) {
|
||||
|
||||
|
||||
// Guess where a "bottom right" finder pattern would have been
|
||||
float bottomRightX = topRight->getX() - topLeft->getX() + bottomLeft->getX();
|
||||
float bottomRightY = topRight->getY() - topLeft->getY() + bottomLeft->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;
|
||||
int estAlignmentX = (int)(topLeft->getX() + correctionToTopLeft * (bottomRightX - topLeft->getX()));
|
||||
int estAlignmentY = (int)(topLeft->getY() + correctionToTopLeft * (bottomRightY - topLeft->getY()));
|
||||
|
||||
|
||||
// Kind of arbitrary -- expand search radius before giving up
|
||||
for (int i = 4; i <= 16; i <<= 1) {
|
||||
try {
|
||||
alignmentPattern = findAlignmentInRegion(moduleSize, estAlignmentX, estAlignmentY, (float)i);
|
||||
break;
|
||||
} catch (zxing::ReaderException 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, transform));
|
||||
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 = sourceBottomRightY = dimMinusThree - 3.0f;
|
||||
} 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 = 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 = lround(FinderPatternFinder::distance(topLeft, topRight) / moduleSize);
|
||||
int tlblCentersDimension = lround(FinderPatternFinder::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
|
||||
int otherToX = fromX - (toX - fromX);
|
||||
if (otherToX < 0) {
|
||||
// "to" should the be the first value not included, so, the first value off
|
||||
// the edge is -1
|
||||
otherToX = -1;
|
||||
} else if (otherToX >= (int)image_->getWidth()) {
|
||||
otherToX = image_->getWidth();
|
||||
}
|
||||
int otherToY = fromY - (toY - fromY);
|
||||
if (otherToY < 0) {
|
||||
otherToY = -1;
|
||||
} else if (otherToY >= (int)image_->getHeight()) {
|
||||
otherToY = image_->getHeight();
|
||||
}
|
||||
result += sizeOfBlackWhiteBlackRun(fromX, fromY, otherToX, otherToY);
|
||||
return result - 1.0f; // -1 because we counted the middle pixel twice
|
||||
}
|
||||
|
||||
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 ystep = fromY < toY ? 1 : -1;
|
||||
int xstep = fromX < toX ? 1 : -1;
|
||||
int state = 0; // In black pixels, looking for white, first or second time
|
||||
for (int x = fromX, y = fromY; x != toX; x += xstep) {
|
||||
|
||||
int realX = steep ? y : x;
|
||||
int realY = steep ? x : y;
|
||||
if (state == 1) { // In white pixels, looking for black
|
||||
if (image_->get(realX, realY)) {
|
||||
state++;
|
||||
}
|
||||
} else {
|
||||
if (!image_->get(realX, realY)) {
|
||||
state++;
|
||||
}
|
||||
}
|
||||
|
||||
if (state == 3) { // Found black, white, black, and stumbled back onto white; done
|
||||
int diffX = x - fromX;
|
||||
int diffY = y - fromY;
|
||||
return (float)sqrt((double)(diffX * diffX + diffY * diffY));
|
||||
}
|
||||
error += dy;
|
||||
if (error > 0) {
|
||||
y += ystep;
|
||||
error -= dx;
|
||||
}
|
||||
}
|
||||
int diffX = toX - fromX;
|
||||
int diffY = toY - fromY;
|
||||
return (float)sqrt((double)(diffX * diffX + diffY * diffY));
|
||||
}
|
||||
|
||||
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);
|
||||
int alignmentAreaTopY = max(0, estAlignmentY - allowance);
|
||||
int alignmentAreaBottomY = min((int)(image_->getHeight() - 1), estAlignmentY + allowance);
|
||||
|
||||
AlignmentPatternFinder alignmentFinder(image_, alignmentAreaLeftX, alignmentAreaTopY, alignmentAreaRightX
|
||||
- alignmentAreaLeftX, alignmentAreaBottomY - alignmentAreaTopY, overallEstModuleSize);
|
||||
return alignmentFinder.find();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Detector.cpp
|
||||
* zxing
|
||||
*
|
||||
* Created by Christian Brunschen on 14/05/2008.
|
||||
* Copyright 2008 ZXing authors All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <zxing/qrcode/detector/Detector.h>
|
||||
#include <zxing/qrcode/detector/FinderPatternFinder.h>
|
||||
#include <zxing/qrcode/detector/FinderPattern.h>
|
||||
#include <zxing/qrcode/detector/AlignmentPattern.h>
|
||||
#include <zxing/qrcode/detector/AlignmentPatternFinder.h>
|
||||
#include <zxing/qrcode/Version.h>
|
||||
#include <zxing/common/GridSampler.h>
|
||||
#include <cmath>
|
||||
#include <sstream>
|
||||
|
||||
namespace zxing {
|
||||
namespace qrcode {
|
||||
|
||||
using namespace std;
|
||||
|
||||
Detector::Detector(Ref<BitMatrix> image) :
|
||||
image_(image) {
|
||||
}
|
||||
|
||||
Ref<BitMatrix> Detector::getImage() {
|
||||
return image_;
|
||||
}
|
||||
|
||||
Ref<DetectorResult> Detector::detect() {
|
||||
FinderPatternFinder finder(image_);
|
||||
Ref<FinderPatternInfo> info(finder.find());
|
||||
|
||||
Ref<FinderPattern> topLeft(info->getTopLeft());
|
||||
Ref<FinderPattern> topRight(info->getTopRight());
|
||||
Ref<FinderPattern> bottomLeft(info->getBottomLeft());
|
||||
|
||||
float moduleSize = calculateModuleSize(topLeft, topRight, bottomLeft);
|
||||
int dimension = computeDimension(topLeft, topRight, bottomLeft, moduleSize);
|
||||
Version *provisionalVersion = Version::getProvisionalVersionForDimension(dimension);
|
||||
int modulesBetweenFPCenters = provisionalVersion->getDimensionForVersion() - 7;
|
||||
|
||||
Ref<AlignmentPattern> alignmentPattern;
|
||||
// Anything above version 1 has an alignment pattern
|
||||
if (provisionalVersion->getAlignmentPatternCenters().size() > 0) {
|
||||
|
||||
|
||||
// Guess where a "bottom right" finder pattern would have been
|
||||
float bottomRightX = topRight->getX() - topLeft->getX() + bottomLeft->getX();
|
||||
float bottomRightY = topRight->getY() - topLeft->getY() + bottomLeft->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;
|
||||
int estAlignmentX = (int)(topLeft->getX() + correctionToTopLeft * (bottomRightX - topLeft->getX()));
|
||||
int estAlignmentY = (int)(topLeft->getY() + correctionToTopLeft * (bottomRightY - topLeft->getY()));
|
||||
|
||||
|
||||
// Kind of arbitrary -- expand search radius before giving up
|
||||
for (int i = 4; i <= 16; i <<= 1) {
|
||||
try {
|
||||
alignmentPattern = findAlignmentInRegion(moduleSize, estAlignmentX, estAlignmentY, (float)i);
|
||||
break;
|
||||
} catch (zxing::ReaderException 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, transform));
|
||||
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 = sourceBottomRightY = dimMinusThree - 3.0f;
|
||||
} 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 = 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 = lround(FinderPatternFinder::distance(topLeft, topRight) / moduleSize);
|
||||
int tlblCentersDimension = lround(FinderPatternFinder::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
|
||||
int otherToX = fromX - (toX - fromX);
|
||||
if (otherToX < 0) {
|
||||
// "to" should the be the first value not included, so, the first value off
|
||||
// the edge is -1
|
||||
otherToX = -1;
|
||||
} else if (otherToX >= (int)image_->getWidth()) {
|
||||
otherToX = image_->getWidth();
|
||||
}
|
||||
int otherToY = fromY - (toY - fromY);
|
||||
if (otherToY < 0) {
|
||||
otherToY = -1;
|
||||
} else if (otherToY >= (int)image_->getHeight()) {
|
||||
otherToY = image_->getHeight();
|
||||
}
|
||||
result += sizeOfBlackWhiteBlackRun(fromX, fromY, otherToX, otherToY);
|
||||
return result - 1.0f; // -1 because we counted the middle pixel twice
|
||||
}
|
||||
|
||||
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 ystep = fromY < toY ? 1 : -1;
|
||||
int xstep = fromX < toX ? 1 : -1;
|
||||
int state = 0; // In black pixels, looking for white, first or second time
|
||||
for (int x = fromX, y = fromY; x != toX; x += xstep) {
|
||||
|
||||
int realX = steep ? y : x;
|
||||
int realY = steep ? x : y;
|
||||
if (state == 1) { // In white pixels, looking for black
|
||||
if (image_->get(realX, realY)) {
|
||||
state++;
|
||||
}
|
||||
} else {
|
||||
if (!image_->get(realX, realY)) {
|
||||
state++;
|
||||
}
|
||||
}
|
||||
|
||||
if (state == 3) { // Found black, white, black, and stumbled back onto white; done
|
||||
int diffX = x - fromX;
|
||||
int diffY = y - fromY;
|
||||
return (float)sqrt((double)(diffX * diffX + diffY * diffY));
|
||||
}
|
||||
error += dy;
|
||||
if (error > 0) {
|
||||
y += ystep;
|
||||
error -= dx;
|
||||
}
|
||||
}
|
||||
int diffX = toX - fromX;
|
||||
int diffY = toY - fromY;
|
||||
return (float)sqrt((double)(diffX * diffX + diffY * diffY));
|
||||
}
|
||||
|
||||
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);
|
||||
int alignmentAreaTopY = max(0, estAlignmentY - allowance);
|
||||
int alignmentAreaBottomY = min((int)(image_->getHeight() - 1), estAlignmentY + allowance);
|
||||
|
||||
AlignmentPatternFinder alignmentFinder(image_, alignmentAreaLeftX, alignmentAreaTopY, alignmentAreaRightX
|
||||
- alignmentAreaLeftX, alignmentAreaBottomY - alignmentAreaTopY, overallEstModuleSize);
|
||||
return alignmentFinder.find();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,58 +1,60 @@
|
|||
#ifndef __DETECTOR_H__
|
||||
#define __DETECTOR_H__
|
||||
|
||||
/*
|
||||
* Detector.h
|
||||
* zxing
|
||||
*
|
||||
* Created by Christian Brunschen on 14/05/2008.
|
||||
* Copyright 2008 ZXing authors All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <zxing/common/Counted.h>
|
||||
#include <zxing/common/DetectorResult.h>
|
||||
#include <zxing/common/BitMatrix.h>
|
||||
#include <zxing/qrcode/detector/AlignmentPattern.h>
|
||||
#include <zxing/common/PerspectiveTransform.h>
|
||||
|
||||
namespace zxing {
|
||||
namespace qrcode {
|
||||
|
||||
class Detector : public Counted {
|
||||
protected:
|
||||
Ref<BitMatrix> image_;
|
||||
|
||||
|
||||
static Ref<BitMatrix> sampleGrid(Ref<BitMatrix> image, int dimension, Ref<PerspectiveTransform>);
|
||||
static int computeDimension(Ref<ResultPoint> topLeft, Ref<ResultPoint> topRight, Ref<ResultPoint> bottomLeft,
|
||||
float moduleSize);
|
||||
float calculateModuleSize(Ref<ResultPoint> topLeft, Ref<ResultPoint> topRight, Ref<ResultPoint> bottomLeft);
|
||||
float calculateModuleSizeOneWay(Ref<ResultPoint> pattern, Ref<ResultPoint> otherPattern);
|
||||
float sizeOfBlackWhiteBlackRunBothWays(int fromX, int fromY, int toX, int toY);
|
||||
float sizeOfBlackWhiteBlackRun(int fromX, int fromY, int toX, int toY);
|
||||
Ref<AlignmentPattern> findAlignmentInRegion(float overallEstModuleSize, int estAlignmentX, int estAlignmentY,
|
||||
float allowanceFactor);
|
||||
public:
|
||||
|
||||
virtual Ref<PerspectiveTransform> createTransform(Ref<ResultPoint> topLeft, Ref<ResultPoint> topRight, Ref <
|
||||
ResultPoint > bottomLeft, Ref<ResultPoint> alignmentPattern, int dimension);
|
||||
|
||||
Detector(Ref<BitMatrix> image);
|
||||
Ref<DetectorResult> detect();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // __DETECTOR_H__
|
||||
#ifndef __DETECTOR_H__
|
||||
#define __DETECTOR_H__
|
||||
|
||||
/*
|
||||
* Detector.h
|
||||
* zxing
|
||||
*
|
||||
* Created by Christian Brunschen on 14/05/2008.
|
||||
* Copyright 2008 ZXing authors All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <zxing/common/Counted.h>
|
||||
#include <zxing/common/DetectorResult.h>
|
||||
#include <zxing/common/BitMatrix.h>
|
||||
#include <zxing/qrcode/detector/AlignmentPattern.h>
|
||||
#include <zxing/common/PerspectiveTransform.h>
|
||||
|
||||
namespace zxing {
|
||||
namespace qrcode {
|
||||
|
||||
class Detector : public Counted {
|
||||
private:
|
||||
Ref<BitMatrix> image_;
|
||||
|
||||
protected:
|
||||
Ref<BitMatrix> getImage();
|
||||
|
||||
static Ref<BitMatrix> sampleGrid(Ref<BitMatrix> image, int dimension, Ref<PerspectiveTransform>);
|
||||
static int computeDimension(Ref<ResultPoint> topLeft, Ref<ResultPoint> topRight, Ref<ResultPoint> bottomLeft,
|
||||
float moduleSize);
|
||||
float calculateModuleSize(Ref<ResultPoint> topLeft, Ref<ResultPoint> topRight, Ref<ResultPoint> bottomLeft);
|
||||
float calculateModuleSizeOneWay(Ref<ResultPoint> pattern, Ref<ResultPoint> otherPattern);
|
||||
float sizeOfBlackWhiteBlackRunBothWays(int fromX, int fromY, int toX, int toY);
|
||||
float sizeOfBlackWhiteBlackRun(int fromX, int fromY, int toX, int toY);
|
||||
Ref<AlignmentPattern> findAlignmentInRegion(float overallEstModuleSize, int estAlignmentX, int estAlignmentY,
|
||||
float allowanceFactor);
|
||||
public:
|
||||
|
||||
virtual Ref<PerspectiveTransform> createTransform(Ref<ResultPoint> topLeft, Ref<ResultPoint> topRight, Ref <
|
||||
ResultPoint > bottomLeft, Ref<ResultPoint> alignmentPattern, int dimension);
|
||||
|
||||
Detector(Ref<BitMatrix> image);
|
||||
Ref<DetectorResult> detect();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif // __DETECTOR_H__
|
||||
|
|
|
@ -1,168 +1,168 @@
|
|||
/*
|
||||
* QREdgeDetector.cpp
|
||||
* zxing
|
||||
*
|
||||
* Created by Ralf Kistner on 7/12/2009.
|
||||
* Copyright 2008 ZXing authors All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <zxing/qrcode/detector/QREdgeDetector.h>
|
||||
#include <zxing/common/EdgeDetector.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace zxing {
|
||||
namespace qrcode {
|
||||
|
||||
static const float patternEdgeThreshold = 2;
|
||||
static const int patternEdgeWidth = 3;
|
||||
static const float patternEdgeSearchRatio = 1.1;
|
||||
static const int patternEdgeSkip = 2;
|
||||
|
||||
static const float accurateEdgeThreshold = 3.3;
|
||||
static const int accurateEdgeWidth = 7;
|
||||
static const int accurateEdgeSkip = 2;
|
||||
|
||||
static Point guessLastPattern(Point topLeft, Point topRight, Point bottomLeft) {
|
||||
return Point(topRight.x - topLeft.x + bottomLeft.x, topRight.y - topLeft.y + bottomLeft.y);
|
||||
}
|
||||
|
||||
static Point rp(Ref<ResultPoint> rp) {
|
||||
return Point(rp->getX(), rp->getY());
|
||||
}
|
||||
|
||||
QREdgeDetector::QREdgeDetector(Ref<BitMatrix> image) : Detector(image) { }
|
||||
|
||||
Ref<PerspectiveTransform> QREdgeDetector::createTransform(Ref<ResultPoint> topLeft, Ref<ResultPoint> topRight, Ref <
|
||||
ResultPoint > bottomLeft, Ref<ResultPoint> alignmentPattern, int dimension) {
|
||||
|
||||
if(alignmentPattern == NULL) {
|
||||
Point corner = findCorner(*image_.object_, rp(topLeft), rp(topRight), rp(bottomLeft), dimension);
|
||||
return get1CornerTransform(rp(topLeft), rp(topRight), rp(bottomLeft), corner, dimension);
|
||||
} else {
|
||||
return Detector::createTransform(topLeft, topRight, bottomLeft, alignmentPattern, dimension);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Point QREdgeDetector::findCorner(const BitMatrix& image, Point topLeft, Point topRight, Point bottomLeft, int dimension) {
|
||||
Point bottomRight = guessLastPattern(topLeft, topRight, bottomLeft);
|
||||
|
||||
Line bottomEst = findPatternEdge(image, bottomLeft, topLeft, bottomRight, false);
|
||||
Line rightEst = findPatternEdge(image, topRight, topLeft, bottomRight, true);
|
||||
|
||||
//return EdgeDetector::intersection(bottomEst, rightEst);
|
||||
|
||||
Line bottom = EdgeDetector::findLine(image, bottomEst, false, accurateEdgeWidth, accurateEdgeThreshold, accurateEdgeSkip);
|
||||
Line right = EdgeDetector::findLine(image, rightEst, true, accurateEdgeWidth, accurateEdgeThreshold, accurateEdgeSkip);
|
||||
|
||||
|
||||
return EdgeDetector::intersection(bottom, right);
|
||||
}
|
||||
|
||||
Line QREdgeDetector::findPatternEdge(const BitMatrix& image, Point pattern, Point opposite, Point direction, bool invert) {
|
||||
Point start = endOfReverseBlackWhiteBlackRun(image, pattern, opposite);
|
||||
|
||||
float dx = pattern.x - start.x;
|
||||
float dy = pattern.y - start.y;
|
||||
float dist = sqrt(dx*dx + dy*dy);
|
||||
|
||||
float dirX = direction.x - pattern.x;
|
||||
float dirY = direction.y - pattern.y;
|
||||
float dirSize = sqrt(dirX*dirX + dirY*dirY);
|
||||
|
||||
float nx = dirX/dirSize;
|
||||
float ny = dirY/dirSize;
|
||||
|
||||
float search = dist * patternEdgeSearchRatio;
|
||||
Point a(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);
|
||||
}
|
||||
|
||||
|
||||
Ref<PerspectiveTransform> QREdgeDetector::get1CornerTransform(Point topLeft, Point topRight, Point bottomLeft, Point corner, int dimension) {
|
||||
float dimMinusThree = (float) dimension - 3.5f;
|
||||
|
||||
Ref<PerspectiveTransform> transform(PerspectiveTransform::quadrilateralToQuadrilateral(3.5f, 3.5f, dimMinusThree, 3.5f, dimension,
|
||||
dimension, 3.5f, dimMinusThree, topLeft.x, topLeft.y, topRight.x,
|
||||
topRight.y, corner.x, corner.y, bottomLeft.x, bottomLeft.y));
|
||||
|
||||
return transform;
|
||||
}
|
||||
|
||||
// Adapted from "sizeOfBlackWhiteBlackRun" in zxing::qrcode::Detector
|
||||
Point QREdgeDetector::endOfReverseBlackWhiteBlackRun(const BitMatrix& image, Point from, Point to) {
|
||||
float fromX = from.x;
|
||||
float fromY = from.y;
|
||||
float toX = to.x;
|
||||
float toY = to.y;
|
||||
|
||||
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 ystep = fromY < toY ? -1 : 1;
|
||||
int xstep = fromX < toX ? -1 : 1;
|
||||
int state = 0; // In black pixels, looking for white, first or second time
|
||||
|
||||
// In case there are no points, prepopulate to from
|
||||
int realX = from.x;
|
||||
int realY = from.y;
|
||||
for (int x = fromX, y = fromY; x != toX; x += xstep) {
|
||||
realX = steep ? y : x;
|
||||
realY = steep ? x : y;
|
||||
|
||||
if(realX < 0 || realY < 0 || realX >= (int)image.getWidth() || realY >= (int)image.getHeight())
|
||||
break;
|
||||
|
||||
if (state == 1) { // In white pixels, looking for black
|
||||
if (image.get(realX, realY)) {
|
||||
state++;
|
||||
}
|
||||
} else {
|
||||
if (!image.get(realX, realY)) {
|
||||
state++;
|
||||
}
|
||||
}
|
||||
|
||||
if (state == 3) { // Found black, white, black, and stumbled back onto white; done
|
||||
return Point(realX, realY);
|
||||
}
|
||||
error += dy;
|
||||
if (error > 0) {
|
||||
y += ystep;
|
||||
error -= dx;
|
||||
}
|
||||
}
|
||||
|
||||
// B-W-B run not found, return the last point visited.
|
||||
return Point(realX, realY);
|
||||
}
|
||||
|
||||
} // namespace qrcode
|
||||
} // namespace zxing
|
||||
/*
|
||||
* QREdgeDetector.cpp
|
||||
* zxing
|
||||
*
|
||||
* Created by Ralf Kistner on 7/12/2009.
|
||||
* Copyright 2008 ZXing authors All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <zxing/qrcode/detector/QREdgeDetector.h>
|
||||
#include <zxing/common/EdgeDetector.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace zxing {
|
||||
namespace qrcode {
|
||||
|
||||
static const float patternEdgeThreshold = 2;
|
||||
static const int patternEdgeWidth = 3;
|
||||
static const float patternEdgeSearchRatio = 1.1;
|
||||
static const int patternEdgeSkip = 2;
|
||||
|
||||
static const float accurateEdgeThreshold = 3.3;
|
||||
static const int accurateEdgeWidth = 7;
|
||||
static const int accurateEdgeSkip = 2;
|
||||
|
||||
static Point guessLastPattern(Point topLeft, Point topRight, Point bottomLeft) {
|
||||
return Point(topRight.x - topLeft.x + bottomLeft.x, topRight.y - topLeft.y + bottomLeft.y);
|
||||
}
|
||||
|
||||
static Point rp(Ref<ResultPoint> rp) {
|
||||
return Point(rp->getX(), rp->getY());
|
||||
}
|
||||
|
||||
QREdgeDetector::QREdgeDetector(Ref<BitMatrix> image) : Detector(image) { }
|
||||
|
||||
Ref<PerspectiveTransform> QREdgeDetector::createTransform(Ref<ResultPoint> topLeft, Ref<ResultPoint> topRight, Ref <
|
||||
ResultPoint > bottomLeft, Ref<ResultPoint> alignmentPattern, int dimension) {
|
||||
|
||||
if(alignmentPattern == NULL) {
|
||||
Point corner = findCorner(*Detector::getImage(), rp(topLeft), rp(topRight), rp(bottomLeft), dimension);
|
||||
return get1CornerTransform(rp(topLeft), rp(topRight), rp(bottomLeft), corner, dimension);
|
||||
} else {
|
||||
return Detector::createTransform(topLeft, topRight, bottomLeft, alignmentPattern, dimension);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Point QREdgeDetector::findCorner(const BitMatrix& image, Point topLeft, Point topRight, Point bottomLeft, int dimension) {
|
||||
Point bottomRight = guessLastPattern(topLeft, topRight, bottomLeft);
|
||||
|
||||
Line bottomEst = findPatternEdge(image, bottomLeft, topLeft, bottomRight, false);
|
||||
Line rightEst = findPatternEdge(image, topRight, topLeft, bottomRight, true);
|
||||
|
||||
//return EdgeDetector::intersection(bottomEst, rightEst);
|
||||
|
||||
Line bottom = EdgeDetector::findLine(image, bottomEst, false, accurateEdgeWidth, accurateEdgeThreshold, accurateEdgeSkip);
|
||||
Line right = EdgeDetector::findLine(image, rightEst, true, accurateEdgeWidth, accurateEdgeThreshold, accurateEdgeSkip);
|
||||
|
||||
|
||||
return EdgeDetector::intersection(bottom, right);
|
||||
}
|
||||
|
||||
Line QREdgeDetector::findPatternEdge(const BitMatrix& image, Point pattern, Point opposite, Point direction, bool invert) {
|
||||
Point start = endOfReverseBlackWhiteBlackRun(image, pattern, opposite);
|
||||
|
||||
float dx = pattern.x - start.x;
|
||||
float dy = pattern.y - start.y;
|
||||
float dist = sqrt(dx*dx + dy*dy);
|
||||
|
||||
float dirX = direction.x - pattern.x;
|
||||
float dirY = direction.y - pattern.y;
|
||||
float dirSize = sqrt(dirX*dirX + dirY*dirY);
|
||||
|
||||
float nx = dirX/dirSize;
|
||||
float ny = dirY/dirSize;
|
||||
|
||||
float search = dist * patternEdgeSearchRatio;
|
||||
Point a(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);
|
||||
}
|
||||
|
||||
|
||||
Ref<PerspectiveTransform> QREdgeDetector::get1CornerTransform(Point topLeft, Point topRight, Point bottomLeft, Point corner, int dimension) {
|
||||
float dimMinusThree = (float) dimension - 3.5f;
|
||||
|
||||
Ref<PerspectiveTransform> transform(PerspectiveTransform::quadrilateralToQuadrilateral(3.5f, 3.5f, dimMinusThree, 3.5f, dimension,
|
||||
dimension, 3.5f, dimMinusThree, topLeft.x, topLeft.y, topRight.x,
|
||||
topRight.y, corner.x, corner.y, bottomLeft.x, bottomLeft.y));
|
||||
|
||||
return transform;
|
||||
}
|
||||
|
||||
// Adapted from "sizeOfBlackWhiteBlackRun" in zxing::qrcode::Detector
|
||||
Point QREdgeDetector::endOfReverseBlackWhiteBlackRun(const BitMatrix& image, Point from, Point to) {
|
||||
int fromX = (int)from.x;
|
||||
int fromY = (int)from.y;
|
||||
int toX = (int)to.x;
|
||||
int toY = (int)to.y;
|
||||
|
||||
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 ystep = fromY < toY ? -1 : 1;
|
||||
int xstep = fromX < toX ? -1 : 1;
|
||||
int state = 0; // In black pixels, looking for white, first or second time
|
||||
|
||||
// In case there are no points, prepopulate to from
|
||||
int realX = fromX;
|
||||
int realY = fromY;
|
||||
for (int x = fromX, y = fromY; x != toX; x += xstep) {
|
||||
realX = steep ? y : x;
|
||||
realY = steep ? x : y;
|
||||
|
||||
if(realX < 0 || realY < 0 || realX >= (int)image.getWidth() || realY >= (int)image.getHeight())
|
||||
break;
|
||||
|
||||
if (state == 1) { // In white pixels, looking for black
|
||||
if (image.get(realX, realY)) {
|
||||
state++;
|
||||
}
|
||||
} else {
|
||||
if (!image.get(realX, realY)) {
|
||||
state++;
|
||||
}
|
||||
}
|
||||
|
||||
if (state == 3) { // Found black, white, black, and stumbled back onto white; done
|
||||
return Point(realX, realY);
|
||||
}
|
||||
error += dy;
|
||||
if (error > 0) {
|
||||
y += ystep;
|
||||
error -= dx;
|
||||
}
|
||||
}
|
||||
|
||||
// B-W-B run not found, return the last point visited.
|
||||
return Point(realX, realY);
|
||||
}
|
||||
|
||||
} // namespace qrcode
|
||||
} // namespace zxing
|
||||
|
|
Loading…
Reference in a new issue