QRAlignmentPatternFinder.cpp Example File
appdemos/qtws/QZXing/zxing/zxing/qrcode/detector/QRAlignmentPatternFinder.cpp
#include <zxing/qrcode/detector/AlignmentPatternFinder.h>
#include <zxing/ReaderException.h>
#include <zxing/common/BitArray.h>
#include <vector>
#include <cmath>
#include <cstdlib>
using std::abs;
using std::vector;
using zxing::Ref;
using zxing::qrcode::AlignmentPatternFinder;
using zxing::qrcode::AlignmentPattern;
using zxing::BitMatrix;
using zxing::ResultPointCallback;
float AlignmentPatternFinder::centerFromEnd(vector<int>& stateCount, int end) {
return (float)(end - stateCount[2]) - stateCount[1] / 2.0f;
}
bool AlignmentPatternFinder::foundPatternCross(vector<int> &stateCount) {
float maxVariance = moduleSize_ / 2.0f;
for (int i = 0; i < 3; i++) {
if (abs(moduleSize_ - stateCount[i]) >= maxVariance) {
return false;
}
}
return true;
}
float AlignmentPatternFinder::crossCheckVertical(int startI, int centerJ, int maxCount,
int originalStateCountTotal) {
int maxI = image_->getHeight();
vector<int> stateCount(3, 0);
int i = startI;
while (i >= 0 && image_->get(centerJ, i) && stateCount[1] <= maxCount) {
stateCount[1]++;
i--;
}
if (i < 0 || stateCount[1] > maxCount) {
return nan();
}
while (i >= 0 && !image_->get(centerJ, i) && stateCount[0] <= maxCount) {
stateCount[0]++;
i--;
}
if (stateCount[0] > maxCount) {
return nan();
}
i = startI + 1;
while (i < maxI && image_->get(centerJ, i) && stateCount[1] <= maxCount) {
stateCount[1]++;
i++;
}
if (i == maxI || stateCount[1] > maxCount) {
return nan();
}
while (i < maxI && !image_->get(centerJ, i) && stateCount[2] <= maxCount) {
stateCount[2]++;
i++;
}
if (stateCount[2] > maxCount) {
return nan();
}
int stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2];
if (5 * abs(stateCountTotal - originalStateCountTotal) >= 2 * originalStateCountTotal) {
return nan();
}
return foundPatternCross(stateCount) ? centerFromEnd(stateCount, i) : nan();
}
Ref<AlignmentPattern> AlignmentPatternFinder::handlePossibleCenter(vector<int> &stateCount, int i, int j) {
int stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2];
float centerJ = centerFromEnd(stateCount, j);
float centerI = crossCheckVertical(i, (int)centerJ, 2 * stateCount[1], stateCountTotal);
if (!isnan_z(centerI)) {
float estimatedModuleSize = (float)(stateCount[0] + stateCount[1] + stateCount[2]) / 3.0f;
int max = possibleCenters_->size();
for (int index = 0; index < max; index++) {
Ref<AlignmentPattern> center((*possibleCenters_)[index]);
if (center->aboutEquals(estimatedModuleSize, centerI, centerJ)) {
return center->combineEstimate(centerI, centerJ, estimatedModuleSize);
}
}
AlignmentPattern *tmp = new AlignmentPattern(centerJ, centerI, estimatedModuleSize);
tmp->retain();
possibleCenters_->push_back(tmp);
if (callback_ != 0) {
callback_->foundPossibleResultPoint(*tmp);
}
}
Ref<AlignmentPattern> result;
return result;
}
AlignmentPatternFinder::AlignmentPatternFinder(Ref<BitMatrix> image, int startX, int startY, int width,
int height, float moduleSize,
Ref<ResultPointCallback>const& callback) :
image_(image), possibleCenters_(new vector<AlignmentPattern *> ()), startX_(startX), startY_(startY),
width_(width), height_(height), moduleSize_(moduleSize), callback_(callback) {
}
AlignmentPatternFinder::~AlignmentPatternFinder() {
for (int i = 0; i < int(possibleCenters_->size()); i++) {
(*possibleCenters_)[i]->release();
(*possibleCenters_)[i] = 0;
}
delete possibleCenters_;
}
Ref<AlignmentPattern> AlignmentPatternFinder::find() {
int maxJ = startX_ + width_;
int middleI = startY_ + (height_ >> 1);
vector<int> stateCount(3, 0);
for (int iGen = 0; iGen < height_; iGen++) {
int i = middleI + ((iGen & 0x01) == 0 ? ((iGen + 1) >> 1) : -((iGen + 1) >> 1));
stateCount[0] = 0;
stateCount[1] = 0;
stateCount[2] = 0;
int j = startX_;
while (j < maxJ && !image_->get(j, i)) {
j++;
}
int currentState = 0;
while (j < maxJ) {
if (image_->get(j, i)) {
if (currentState == 1) {
stateCount[currentState]++;
} else {
if (currentState == 2) {
if (foundPatternCross(stateCount)) {
Ref<AlignmentPattern> confirmed(handlePossibleCenter(stateCount, i, j));
if (confirmed != 0) {
return confirmed;
}
}
stateCount[0] = stateCount[2];
stateCount[1] = 1;
stateCount[2] = 0;
currentState = 1;
} else {
stateCount[++currentState]++;
}
}
} else {
if (currentState == 1) {
currentState++;
}
stateCount[currentState]++;
}
j++;
}
if (foundPatternCross(stateCount)) {
Ref<AlignmentPattern> confirmed(handlePossibleCenter(stateCount, i, maxJ));
if (confirmed != 0) {
return confirmed;
}
}
}
if (possibleCenters_->size() > 0) {
Ref<AlignmentPattern> center((*possibleCenters_)[0]);
return center;
}
throw zxing::ReaderException("Could not find alignment pattern");
}