mirror of
https://github.com/zxing/zxing.git
synced 2025-01-12 19:57:27 -08:00
Make C++ consistent with Java for pdf417
A bunch of small changes that result in C++ and Java equiv. for pdf417. - A little bit of java re-reporting in pdf417 - A little bit of java re-reporting/consistency elsewhere There a few places related to latching that differed between the java and C++. I looked for a discussion of this on the group and didn't find any (but may have missed it.) I reverted to the java code which fixed one of the tests. The comments referenced standards-compliance vs. real world encoders. That may need to be revisited? git-svn-id: https://zxing.googlecode.com/svn/trunk@2673 59b500cc-1b3d-0410-9834-0bbf25fbcc57
This commit is contained in:
parent
d245a5cca7
commit
b549267e6f
|
@ -22,7 +22,7 @@
|
||||||
#include <zxing/ResultPoint.h>
|
#include <zxing/ResultPoint.h>
|
||||||
#include <zxing/common/detector/MathUtils.h>
|
#include <zxing/common/detector/MathUtils.h>
|
||||||
|
|
||||||
namespace math_utils = zxing::common::detector::math_utils;
|
using zxing::common::detector::MathUtils;
|
||||||
|
|
||||||
namespace zxing {
|
namespace zxing {
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ void ResultPoint::orderBestPatterns(std::vector<Ref<ResultPoint> > &patterns) {
|
||||||
}
|
}
|
||||||
|
|
||||||
float ResultPoint::distance(Ref<ResultPoint> pattern1, Ref<ResultPoint> pattern2) {
|
float ResultPoint::distance(Ref<ResultPoint> pattern1, Ref<ResultPoint> pattern2) {
|
||||||
return math_utils::distance(pattern1->posX_,
|
return MathUtils::distance(pattern1->posX_,
|
||||||
pattern1->posY_,
|
pattern1->posY_,
|
||||||
pattern2->posX_,
|
pattern2->posX_,
|
||||||
pattern2->posY_);
|
pattern2->posY_);
|
||||||
|
|
|
@ -38,8 +38,7 @@ using zxing::ArrayRef;
|
||||||
using zxing::ResultPoint;
|
using zxing::ResultPoint;
|
||||||
using zxing::BitArray;
|
using zxing::BitArray;
|
||||||
using zxing::BitMatrix;
|
using zxing::BitMatrix;
|
||||||
|
using zxing::common::detector::MathUtils;
|
||||||
namespace math_utils = zxing::common::detector::math_utils;
|
|
||||||
|
|
||||||
Detector::Detector(Ref<BitMatrix> image):
|
Detector::Detector(Ref<BitMatrix> image):
|
||||||
image_(image),
|
image_(image),
|
||||||
|
@ -145,21 +144,21 @@ Detector::getMatrixCornerPoints(std::vector<Ref<Point> > bullEyeCornerPoints) {
|
||||||
int dy = bullEyeCornerPoints[0]->getY() - bullEyeCornerPoints[2]->getY();
|
int dy = bullEyeCornerPoints[0]->getY() - bullEyeCornerPoints[2]->getY();
|
||||||
dy += dy > 0 ? 1 : -1;
|
dy += dy > 0 ? 1 : -1;
|
||||||
|
|
||||||
int targetcx = math_utils::round(bullEyeCornerPoints[2]->getX() - ratio * dx);
|
int targetcx = MathUtils::round(bullEyeCornerPoints[2]->getX() - ratio * dx);
|
||||||
int targetcy = math_utils::round(bullEyeCornerPoints[2]->getY() - ratio * dy);
|
int targetcy = MathUtils::round(bullEyeCornerPoints[2]->getY() - ratio * dy);
|
||||||
|
|
||||||
int targetax = math_utils::round(bullEyeCornerPoints[0]->getX() + ratio * dx);
|
int targetax = MathUtils::round(bullEyeCornerPoints[0]->getX() + ratio * dx);
|
||||||
int targetay = math_utils::round(bullEyeCornerPoints[0]->getY() + ratio * dy);
|
int targetay = MathUtils::round(bullEyeCornerPoints[0]->getY() + ratio * dy);
|
||||||
|
|
||||||
dx = bullEyeCornerPoints[1]->getX() - bullEyeCornerPoints[3]->getX();
|
dx = bullEyeCornerPoints[1]->getX() - bullEyeCornerPoints[3]->getX();
|
||||||
dx += dx > 0 ? 1 : -1;
|
dx += dx > 0 ? 1 : -1;
|
||||||
dy = bullEyeCornerPoints[1]->getY() - bullEyeCornerPoints[3]->getY();
|
dy = bullEyeCornerPoints[1]->getY() - bullEyeCornerPoints[3]->getY();
|
||||||
dy += dy > 0 ? 1 : -1;
|
dy += dy > 0 ? 1 : -1;
|
||||||
|
|
||||||
int targetdx = math_utils::round(bullEyeCornerPoints[3]->getX() - ratio * dx);
|
int targetdx = MathUtils::round(bullEyeCornerPoints[3]->getX() - ratio * dx);
|
||||||
int targetdy = math_utils::round(bullEyeCornerPoints[3]->getY() - ratio * dy);
|
int targetdy = MathUtils::round(bullEyeCornerPoints[3]->getY() - ratio * dy);
|
||||||
int targetbx = math_utils::round(bullEyeCornerPoints[1]->getX() + ratio * dx);
|
int targetbx = MathUtils::round(bullEyeCornerPoints[1]->getX() + ratio * dx);
|
||||||
int targetby = math_utils::round(bullEyeCornerPoints[1]->getY() + ratio * dy);
|
int targetby = MathUtils::round(bullEyeCornerPoints[1]->getY() + ratio * dy);
|
||||||
|
|
||||||
if (!isValid(targetax, targetay) ||
|
if (!isValid(targetax, targetay) ||
|
||||||
!isValid(targetbx, targetby) ||
|
!isValid(targetbx, targetby) ||
|
||||||
|
@ -272,18 +271,18 @@ std::vector<Ref<Point> > Detector::getBullEyeCornerPoints(Ref<zxing::aztec::Poin
|
||||||
int dx = pina->getX() - pind->getX();
|
int dx = pina->getX() - pind->getX();
|
||||||
int dy = pina->getY() - pinc->getY();
|
int dy = pina->getY() - pinc->getY();
|
||||||
|
|
||||||
int targetcx = math_utils::round(pinc->getX() - ratio * dx);
|
int targetcx = MathUtils::round(pinc->getX() - ratio * dx);
|
||||||
int targetcy = math_utils::round(pinc->getY() - ratio * dy);
|
int targetcy = MathUtils::round(pinc->getY() - ratio * dy);
|
||||||
int targetax = math_utils::round(pina->getX() + ratio * dx);
|
int targetax = MathUtils::round(pina->getX() + ratio * dx);
|
||||||
int targetay = math_utils::round(pina->getY() + ratio * dy);
|
int targetay = MathUtils::round(pina->getY() + ratio * dy);
|
||||||
|
|
||||||
dx = pinb->getX() - pind->getX();
|
dx = pinb->getX() - pind->getX();
|
||||||
dy = pinb->getY() - pind->getY();
|
dy = pinb->getY() - pind->getY();
|
||||||
|
|
||||||
int targetdx = math_utils::round(pind->getX() - ratio * dx);
|
int targetdx = MathUtils::round(pind->getX() - ratio * dx);
|
||||||
int targetdy = math_utils::round(pind->getY() - ratio * dy);
|
int targetdy = MathUtils::round(pind->getY() - ratio * dy);
|
||||||
int targetbx = math_utils::round(pinb->getX() + ratio * dx);
|
int targetbx = MathUtils::round(pinb->getX() + ratio * dx);
|
||||||
int targetby = math_utils::round(pinb->getY() + ratio * dy);
|
int targetby = MathUtils::round(pinb->getY() + ratio * dy);
|
||||||
|
|
||||||
if (!isValid(targetax, targetay) ||
|
if (!isValid(targetax, targetay) ||
|
||||||
!isValid(targetbx, targetby) ||
|
!isValid(targetbx, targetby) ||
|
||||||
|
@ -325,8 +324,8 @@ Ref<Point> Detector::getMatrixCenter() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int cx = math_utils::round((pointA->getX() + pointD->getX() + pointB->getX() + pointC->getX()) / 4.0f);
|
int cx = MathUtils::round((pointA->getX() + pointD->getX() + pointB->getX() + pointC->getX()) / 4.0f);
|
||||||
int cy = math_utils::round((pointA->getY() + pointD->getY() + pointB->getY() + pointC->getY()) / 4.0f);
|
int cy = MathUtils::round((pointA->getY() + pointD->getY() + pointB->getY() + pointC->getY()) / 4.0f);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
@ -346,8 +345,8 @@ Ref<Point> Detector::getMatrixCenter() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cx = math_utils::round((pointA->getX() + pointD->getX() + pointB->getX() + pointC->getX()) / 4.0f);
|
cx = MathUtils::round((pointA->getX() + pointD->getX() + pointB->getX() + pointC->getX()) / 4.0f);
|
||||||
cy = math_utils::round((pointA->getY() + pointD->getY() + pointB->getY() + pointC->getY()) / 4.0f);
|
cy = MathUtils::round((pointA->getY() + pointD->getY() + pointB->getY() + pointC->getY()) / 4.0f);
|
||||||
|
|
||||||
return Ref<Point>(new Point(cx, cy));
|
return Ref<Point>(new Point(cx, cy));
|
||||||
|
|
||||||
|
@ -436,7 +435,7 @@ Ref<BitArray> Detector::sampleLine(Ref<zxing::aztec::Point> p1, Ref<zxing::aztec
|
||||||
float py = float(p1->getY());
|
float py = float(p1->getY());
|
||||||
|
|
||||||
for (int i = 0; i < size; i++) {
|
for (int i = 0; i < size; i++) {
|
||||||
if (image_->get(math_utils::round(px), math_utils::round(py))) res->set(i);
|
if (image_->get(MathUtils::round(px), MathUtils::round(py))) res->set(i);
|
||||||
px+=dx;
|
px+=dx;
|
||||||
py+=dy;
|
py+=dy;
|
||||||
}
|
}
|
||||||
|
@ -498,7 +497,7 @@ int Detector::getColor(Ref<zxing::aztec::Point> p1, Ref<zxing::aztec::Point> p2)
|
||||||
for (int i = 0; i < d; i++) {
|
for (int i = 0; i < d; i++) {
|
||||||
px += dx;
|
px += dx;
|
||||||
py += dy;
|
py += dy;
|
||||||
if (image_->get(math_utils::round(px), math_utils::round(py)) != colorModel) {
|
if (image_->get(MathUtils::round(px), MathUtils::round(py)) != colorModel) {
|
||||||
error ++;
|
error ++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,10 @@ String::String(const std::string &text) :
|
||||||
text_(text) {
|
text_(text) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String::String(int capacity) {
|
||||||
|
text_.reserve(capacity);
|
||||||
|
}
|
||||||
|
|
||||||
const std::string& String::getText() const {
|
const std::string& String::getText() const {
|
||||||
return text_;
|
return text_;
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@ private:
|
||||||
std::string text_;
|
std::string text_;
|
||||||
public:
|
public:
|
||||||
explicit String(const std::string &text);
|
explicit String(const std::string &text);
|
||||||
|
explicit String(int);
|
||||||
char charAt(int) const;
|
char charAt(int) const;
|
||||||
Ref<String> substring(int) const;
|
Ref<String> substring(int) const;
|
||||||
const std::string& getText() const;
|
const std::string& getText() const;
|
||||||
|
|
43
cpp/core/src/zxing/common/detector/Math.h
Normal file
43
cpp/core/src/zxing/common/detector/Math.h
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
// -*- mode:c++; tab-width:2; indent-tabs-mode:nil; c-basic-offset:2 -*-
|
||||||
|
#ifndef __ZXING_COMMON_DETECTOR_MATH_H__
|
||||||
|
#define __ZXING_COMMON_DETECTOR_MATH_H__
|
||||||
|
/*
|
||||||
|
* Copyright 2012 ZXing authors All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
namespace zxing {
|
||||||
|
namespace common {
|
||||||
|
namespace detector {
|
||||||
|
|
||||||
|
class Math {
|
||||||
|
private:
|
||||||
|
Math();
|
||||||
|
~Math();
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Java standard Math.round
|
||||||
|
static inline int round(float a) {
|
||||||
|
return (int)std::floor(a +0.5f);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -19,28 +19,39 @@
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
namespace zxing { namespace common { namespace detector { namespace math_utils {
|
namespace zxing {
|
||||||
|
namespace common {
|
||||||
|
namespace detector {
|
||||||
|
|
||||||
/**
|
class MathUtils {
|
||||||
|
private:
|
||||||
|
MathUtils();
|
||||||
|
~MathUtils();
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
* Ends up being a bit faster than {@link Math#round(float)}. This merely rounds its
|
* Ends up being a bit faster than {@link Math#round(float)}. This merely rounds its
|
||||||
* argument to the nearest int, where x.5 rounds up to x+1.
|
* argument to the nearest int, where x.5 rounds up to x+1.
|
||||||
*/
|
*/
|
||||||
inline int round(float d) {
|
static inline int round(float d) {
|
||||||
return (int) (d + 0.5f);
|
return (int) (d + 0.5f);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline float distance(float aX, float aY, float bX, float bY) {
|
static inline float distance(float aX, float aY, float bX, float bY) {
|
||||||
float xDiff = aX - bX;
|
float xDiff = aX - bX;
|
||||||
float yDiff = aY - bY;
|
float yDiff = aY - bY;
|
||||||
return sqrt(xDiff * xDiff + yDiff * yDiff);
|
return sqrt(xDiff * xDiff + yDiff * yDiff);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline float distance(int aX, int aY, int bX, int bY) {
|
static inline float distance(int aX, int aY, int bX, int bY) {
|
||||||
int xDiff = aX - bX;
|
int xDiff = aX - bX;
|
||||||
int yDiff = aY - bY;
|
int yDiff = aY - bY;
|
||||||
return sqrt(float(xDiff * xDiff + yDiff * yDiff));
|
return sqrt(float(xDiff * xDiff + yDiff * yDiff));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}}}}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -24,12 +24,11 @@
|
||||||
#include <zxing/common/detector/MathUtils.h>
|
#include <zxing/common/detector/MathUtils.h>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
namespace math_utils = zxing::common::detector::math_utils;
|
|
||||||
|
|
||||||
using std::vector;
|
using std::vector;
|
||||||
using zxing::Ref;
|
using zxing::Ref;
|
||||||
using zxing::ResultPoint;
|
using zxing::ResultPoint;
|
||||||
using zxing::WhiteRectangleDetector;
|
using zxing::WhiteRectangleDetector;
|
||||||
|
using zxing::common::detector::MathUtils;
|
||||||
|
|
||||||
// VC++
|
// VC++
|
||||||
using zxing::BitMatrix;
|
using zxing::BitMatrix;
|
||||||
|
@ -232,13 +231,13 @@ std::vector<Ref<ResultPoint> > WhiteRectangleDetector::detect() {
|
||||||
Ref<ResultPoint>
|
Ref<ResultPoint>
|
||||||
WhiteRectangleDetector::getBlackPointOnSegment(int aX_, int aY_, int bX_, int bY_) {
|
WhiteRectangleDetector::getBlackPointOnSegment(int aX_, int aY_, int bX_, int bY_) {
|
||||||
float aX = float(aX_), aY = float(aY_), bX = float(bX_), bY = float(bY_);
|
float aX = float(aX_), aY = float(aY_), bX = float(bX_), bY = float(bY_);
|
||||||
int dist = math_utils::round(math_utils::distance(aX, aY, bX, bY));
|
int dist = MathUtils::round(MathUtils::distance(aX, aY, bX, bY));
|
||||||
float xStep = (bX - aX) / dist;
|
float xStep = (bX - aX) / dist;
|
||||||
float yStep = (bY - aY) / dist;
|
float yStep = (bY - aY) / dist;
|
||||||
|
|
||||||
for (int i = 0; i < dist; i++) {
|
for (int i = 0; i < dist; i++) {
|
||||||
int x = math_utils::round(aX + i * xStep);
|
int x = MathUtils::round(aX + i * xStep);
|
||||||
int y = math_utils::round(aY + i * yStep);
|
int y = MathUtils::round(aY + i * yStep);
|
||||||
if (image_->get(x, y)) {
|
if (image_->get(x, y)) {
|
||||||
Ref<ResultPoint> point(new ResultPoint(float(x), float(y)));
|
Ref<ResultPoint> point(new ResultPoint(float(x), float(y)));
|
||||||
return point;
|
return point;
|
||||||
|
|
|
@ -28,7 +28,6 @@
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
namespace math_utils = zxing::common::detector::math_utils;
|
|
||||||
|
|
||||||
using zxing::Ref;
|
using zxing::Ref;
|
||||||
using zxing::BitMatrix;
|
using zxing::BitMatrix;
|
||||||
|
@ -38,6 +37,7 @@ using zxing::PerspectiveTransform;
|
||||||
using zxing::NotFoundException;
|
using zxing::NotFoundException;
|
||||||
using zxing::datamatrix::Detector;
|
using zxing::datamatrix::Detector;
|
||||||
using zxing::datamatrix::ResultPointsAndTransitions;
|
using zxing::datamatrix::ResultPointsAndTransitions;
|
||||||
|
using zxing::common::detector::MathUtils;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
typedef std::map<Ref<ResultPoint>, int> PointMap;
|
typedef std::map<Ref<ResultPoint>, int> PointMap;
|
||||||
|
@ -346,7 +346,7 @@ bool Detector::isValid(Ref<ResultPoint> p) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int Detector::distance(Ref<ResultPoint> a, Ref<ResultPoint> b) {
|
int Detector::distance(Ref<ResultPoint> a, Ref<ResultPoint> b) {
|
||||||
return math_utils::round(ResultPoint::distance(a, b));
|
return MathUtils::round(ResultPoint::distance(a, b));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<ResultPointsAndTransitions> Detector::transitionsBetween(Ref<ResultPoint> from,
|
Ref<ResultPointsAndTransitions> Detector::transitionsBetween(Ref<ResultPoint> from,
|
||||||
|
|
|
@ -118,12 +118,12 @@ int PDF417Reader::moduleSize(ArrayRef<int> leftTopBlack, Ref<BitMatrix> image) {
|
||||||
throw NotFoundException("PDF417Reader::moduleSize: not found!");
|
throw NotFoundException("PDF417Reader::moduleSize: not found!");
|
||||||
}
|
}
|
||||||
|
|
||||||
int nModuleSize = (int)(((unsigned)(x - leftTopBlack[0])) >> 3); // We've crossed left first bar, which is 8x
|
int moduleSize = (int)(((unsigned)(x - leftTopBlack[0])) >> 3); // We've crossed left first bar, which is 8x
|
||||||
if (nModuleSize == 0) {
|
if (moduleSize == 0) {
|
||||||
throw NotFoundException("PDF417Reader::moduleSize: is zero!");
|
throw NotFoundException("PDF417Reader::moduleSize: is zero!");
|
||||||
}
|
}
|
||||||
|
|
||||||
return nModuleSize;
|
return moduleSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PDF417Reader::findPatternStart(int x, int y, Ref<BitMatrix> image) {
|
int PDF417Reader::findPatternStart(int x, int y, Ref<BitMatrix> image) {
|
||||||
|
|
|
@ -28,8 +28,6 @@ using zxing::Ref;
|
||||||
using zxing::DecoderResult;
|
using zxing::DecoderResult;
|
||||||
using zxing::String;
|
using zxing::String;
|
||||||
|
|
||||||
// VC++
|
|
||||||
|
|
||||||
const int DecodedBitStreamParser::TEXT_COMPACTION_MODE_LATCH = 900;
|
const int DecodedBitStreamParser::TEXT_COMPACTION_MODE_LATCH = 900;
|
||||||
const int DecodedBitStreamParser::BYTE_COMPACTION_MODE_LATCH = 901;
|
const int DecodedBitStreamParser::BYTE_COMPACTION_MODE_LATCH = 901;
|
||||||
const int DecodedBitStreamParser::NUMERIC_COMPACTION_MODE_LATCH = 902;
|
const int DecodedBitStreamParser::NUMERIC_COMPACTION_MODE_LATCH = 902;
|
||||||
|
@ -60,40 +58,27 @@ const char DecodedBitStreamParser::MIXED_CHARS[] = {
|
||||||
'\r', '\t', ',', ':', '#', '-', '.', '$', '/', '+', '%', '*',
|
'\r', '\t', ',', ':', '#', '-', '.', '$', '/', '+', '%', '*',
|
||||||
'=', '^'};
|
'=', '^'};
|
||||||
|
|
||||||
ArrayRef<BigInteger> DecodedBitStreamParser::AExp900_;
|
ArrayRef<BigInteger> DecodedBitStreamParser::initEXP900() {
|
||||||
|
ArrayRef<BigInteger> EXP900 (16);
|
||||||
/**
|
EXP900[0] = BigInteger(1);
|
||||||
* Table containing values for the exponent of 900.
|
BigInteger nineHundred (900);
|
||||||
* This is used in the numeric compaction decode algorithm.
|
EXP900[1] = nineHundred;
|
||||||
* Hint: will be initialized only once (because of zero check), so it can be
|
for (int i = 2; i < EXP900->size(); i++) {
|
||||||
* called by the constructor.
|
EXP900[i] = EXP900[i - 1] * nineHundred;
|
||||||
*/
|
|
||||||
void DecodedBitStreamParser::InitExp900()
|
|
||||||
{
|
|
||||||
if(&(*AExp900_) == 0) {
|
|
||||||
BigInteger nineHundred(900);
|
|
||||||
AExp900_ = new Array<BigInteger>(EXP900_SIZE);
|
|
||||||
AExp900_[0] = BigInteger(1);
|
|
||||||
for (int i=1;i<AExp900_->size();i++) {
|
|
||||||
AExp900_[i] = AExp900_[i-1] * nineHundred;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return EXP900;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
ArrayRef<BigInteger> DecodedBitStreamParser::EXP900 = initEXP900();
|
||||||
* Constructor will initialize exp900 table the first time.
|
|
||||||
*/
|
DecodedBitStreamParser::DecodedBitStreamParser(){}
|
||||||
DecodedBitStreamParser::DecodedBitStreamParser()
|
|
||||||
{
|
|
||||||
InitExp900();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PDF417 main decoder.
|
* PDF417 main decoder.
|
||||||
**/
|
**/
|
||||||
Ref<DecoderResult> DecodedBitStreamParser::decode(ArrayRef<int> codewords)
|
Ref<DecoderResult> DecodedBitStreamParser::decode(ArrayRef<int> codewords)
|
||||||
{
|
{
|
||||||
Ref<String> result(new String(""));
|
Ref<String> result (new String(100));
|
||||||
// Get compaction mode
|
// Get compaction mode
|
||||||
int codeIndex = 1;
|
int codeIndex = 1;
|
||||||
int code = codewords[codeIndex++];
|
int code = codewords[codeIndex++];
|
||||||
|
@ -125,13 +110,10 @@ Ref<DecoderResult> DecodedBitStreamParser::decode(ArrayRef<int> codewords)
|
||||||
if (codeIndex < codewords->size()) {
|
if (codeIndex < codewords->size()) {
|
||||||
code = codewords[codeIndex++];
|
code = codewords[codeIndex++];
|
||||||
} else {
|
} else {
|
||||||
throw FormatException("PDF417:DecodedBitStreamParser:decode: codeword overflow");
|
throw FormatException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ArrayRef<char> dummybuf(1);
|
return Ref<DecoderResult>(new DecoderResult(ArrayRef<char>(), result));
|
||||||
dummybuf[0]= '\0';
|
|
||||||
|
|
||||||
return Ref<DecoderResult>(new DecoderResult(dummybuf, result));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -144,12 +126,13 @@ Ref<DecoderResult> DecodedBitStreamParser::decode(ArrayRef<int> codewords)
|
||||||
* @param result The decoded data is appended to the result.
|
* @param result The decoded data is appended to the result.
|
||||||
* @return The next index into the codeword array.
|
* @return The next index into the codeword array.
|
||||||
*/
|
*/
|
||||||
int DecodedBitStreamParser::textCompaction(ArrayRef<int> codewords, int codeIndex, Ref<String> result)
|
int DecodedBitStreamParser::textCompaction(ArrayRef<int> codewords,
|
||||||
{
|
int codeIndex,
|
||||||
|
Ref<String> result) {
|
||||||
// 2 character per codeword
|
// 2 character per codeword
|
||||||
ArrayRef<int> textCompactionData = new Array<int>(codewords[0] << 1);
|
ArrayRef<int> textCompactionData (codewords[0] << 1);
|
||||||
// Used to hold the byte compaction value if there is a mode shift
|
// Used to hold the byte compaction value if there is a mode shift
|
||||||
ArrayRef<int> byteCompactionData = new Array<int>(codewords[0] << 1);
|
ArrayRef<int> byteCompactionData (codewords[0] << 1);
|
||||||
|
|
||||||
int index = 0;
|
int index = 0;
|
||||||
bool end = false;
|
bool end = false;
|
||||||
|
@ -162,8 +145,7 @@ int DecodedBitStreamParser::textCompaction(ArrayRef<int> codewords, int codeInde
|
||||||
} else {
|
} else {
|
||||||
switch (code) {
|
switch (code) {
|
||||||
case TEXT_COMPACTION_MODE_LATCH:
|
case TEXT_COMPACTION_MODE_LATCH:
|
||||||
codeIndex--;
|
textCompactionData[index++] = TEXT_COMPACTION_MODE_LATCH;
|
||||||
end = true;
|
|
||||||
break;
|
break;
|
||||||
case BYTE_COMPACTION_MODE_LATCH:
|
case BYTE_COMPACTION_MODE_LATCH:
|
||||||
codeIndex--;
|
codeIndex--;
|
||||||
|
@ -246,10 +228,7 @@ void DecodedBitStreamParser::decodeTextCompaction(ArrayRef<int> textCompactionDa
|
||||||
subMode = PUNCT_SHIFT;
|
subMode = PUNCT_SHIFT;
|
||||||
} else if (subModeCh == MODE_SHIFT_TO_BYTE_COMPACTION_MODE) {
|
} else if (subModeCh == MODE_SHIFT_TO_BYTE_COMPACTION_MODE) {
|
||||||
result->append((char) byteCompactionData[i]);
|
result->append((char) byteCompactionData[i]);
|
||||||
// 2012-11-27 hfn after fix by srowen in java code:
|
} else if (subModeCh == TEXT_COMPACTION_MODE_LATCH) {
|
||||||
// the pdf417 specs say we have to return to the last latched
|
|
||||||
// sub-mode. But I checked different encoder implementations and
|
|
||||||
// all of them return to alpha sub-mode after Shift-to-Byte
|
|
||||||
subMode = ALPHA;
|
subMode = ALPHA;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -274,10 +253,7 @@ void DecodedBitStreamParser::decodeTextCompaction(ArrayRef<int> textCompactionDa
|
||||||
subMode = PUNCT_SHIFT;
|
subMode = PUNCT_SHIFT;
|
||||||
} else if (subModeCh == MODE_SHIFT_TO_BYTE_COMPACTION_MODE) {
|
} else if (subModeCh == MODE_SHIFT_TO_BYTE_COMPACTION_MODE) {
|
||||||
result->append((char) byteCompactionData[i]);
|
result->append((char) byteCompactionData[i]);
|
||||||
// 2012-11-27 hfn after fix by srowen in java code:
|
} else if (subModeCh == TEXT_COMPACTION_MODE_LATCH) {
|
||||||
// the pdf417 specs say we have to return to the last latched
|
|
||||||
// sub-mode. But I checked different encoder implementations and
|
|
||||||
// all of them return to alpha sub-mode after Shift-to-Byte
|
|
||||||
subMode = ALPHA;
|
subMode = ALPHA;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -302,10 +278,7 @@ void DecodedBitStreamParser::decodeTextCompaction(ArrayRef<int> textCompactionDa
|
||||||
subMode = PUNCT_SHIFT;
|
subMode = PUNCT_SHIFT;
|
||||||
} else if (subModeCh == MODE_SHIFT_TO_BYTE_COMPACTION_MODE) {
|
} else if (subModeCh == MODE_SHIFT_TO_BYTE_COMPACTION_MODE) {
|
||||||
result->append((char) byteCompactionData[i]);
|
result->append((char) byteCompactionData[i]);
|
||||||
// 2012-11-27 hfn after fix by srowen in java code:
|
} else if (subModeCh == TEXT_COMPACTION_MODE_LATCH) {
|
||||||
// the pdf417 specs say we have to return to the last latched
|
|
||||||
// sub-mode. But I checked different encoder implementations and
|
|
||||||
// all of them return to alpha sub-mode after Shift-to-Byte
|
|
||||||
subMode = ALPHA;
|
subMode = ALPHA;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -320,10 +293,7 @@ void DecodedBitStreamParser::decodeTextCompaction(ArrayRef<int> textCompactionDa
|
||||||
subMode = ALPHA;
|
subMode = ALPHA;
|
||||||
} else if (subModeCh == MODE_SHIFT_TO_BYTE_COMPACTION_MODE) {
|
} else if (subModeCh == MODE_SHIFT_TO_BYTE_COMPACTION_MODE) {
|
||||||
result->append((char) byteCompactionData[i]);
|
result->append((char) byteCompactionData[i]);
|
||||||
// 2012-11-27 hfn after fix by srowen in java code:
|
} else if (subModeCh == TEXT_COMPACTION_MODE_LATCH) {
|
||||||
// the pdf417 specs say we have to return to the last latched
|
|
||||||
// sub-mode. But I checked different encoder implementations and
|
|
||||||
// all of them return to alpha sub-mode after Shift-to-Byte
|
|
||||||
subMode = ALPHA;
|
subMode = ALPHA;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -338,7 +308,11 @@ void DecodedBitStreamParser::decodeTextCompaction(ArrayRef<int> textCompactionDa
|
||||||
if (subModeCh == 26) {
|
if (subModeCh == 26) {
|
||||||
ch = ' ';
|
ch = ' ';
|
||||||
} else {
|
} else {
|
||||||
// is this even possible?
|
if (subModeCh == 26) {
|
||||||
|
ch = ' ';
|
||||||
|
} else if (subModeCh == TEXT_COMPACTION_MODE_LATCH) {
|
||||||
|
subMode = ALPHA;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -356,11 +330,6 @@ void DecodedBitStreamParser::decodeTextCompaction(ArrayRef<int> textCompactionDa
|
||||||
// PS before Shift-to-Byte is used as a padding character,
|
// PS before Shift-to-Byte is used as a padding character,
|
||||||
// see 5.4.2.4 of the specification
|
// see 5.4.2.4 of the specification
|
||||||
result->append((char) byteCompactionData[i]);
|
result->append((char) byteCompactionData[i]);
|
||||||
// 2012-11-27 hfn after fix by srowen in java code:
|
|
||||||
// the pdf417 specs say we have to return to the last latched
|
|
||||||
// sub-mode. But I checked different encoder implementations and
|
|
||||||
// all of them return to alpha sub-mode after Shift-to-Byte
|
|
||||||
subMode = ALPHA;
|
|
||||||
} else if (subModeCh == TEXT_COMPACTION_MODE_LATCH) {
|
} else if (subModeCh == TEXT_COMPACTION_MODE_LATCH) {
|
||||||
subMode = ALPHA;
|
subMode = ALPHA;
|
||||||
}
|
}
|
||||||
|
@ -386,8 +355,9 @@ void DecodedBitStreamParser::decodeTextCompaction(ArrayRef<int> textCompactionDa
|
||||||
* @param result The decoded data is appended to the result.
|
* @param result The decoded data is appended to the result.
|
||||||
* @return The next index into the codeword array.
|
* @return The next index into the codeword array.
|
||||||
*/
|
*/
|
||||||
int DecodedBitStreamParser::byteCompaction(int mode, ArrayRef<int> codewords, int codeIndex, Ref<String> result)
|
int DecodedBitStreamParser::byteCompaction(int mode,
|
||||||
{
|
ArrayRef<int> codewords,
|
||||||
|
int codeIndex, Ref<String> result) {
|
||||||
if (mode == BYTE_COMPACTION_MODE_LATCH) {
|
if (mode == BYTE_COMPACTION_MODE_LATCH) {
|
||||||
// Total number of Byte Compaction characters to be encoded
|
// Total number of Byte Compaction characters to be encoded
|
||||||
// is not a multiple of 6
|
// is not a multiple of 6
|
||||||
|
@ -491,8 +461,9 @@ int DecodedBitStreamParser::byteCompaction(int mode, ArrayRef<int> codewords, in
|
||||||
* @param result The decoded data is appended to the result.
|
* @param result The decoded data is appended to the result.
|
||||||
* @return The next index into the codeword array.
|
* @return The next index into the codeword array.
|
||||||
*/
|
*/
|
||||||
int DecodedBitStreamParser::numericCompaction(ArrayRef<int> codewords, int codeIndex, Ref<String> result)
|
int DecodedBitStreamParser::numericCompaction(ArrayRef<int> codewords,
|
||||||
{
|
int codeIndex,
|
||||||
|
Ref<String> result) {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
bool end = false;
|
bool end = false;
|
||||||
|
|
||||||
|
@ -577,10 +548,9 @@ int DecodedBitStreamParser::numericCompaction(ArrayRef<int> codewords, int codeI
|
||||||
*/
|
*/
|
||||||
Ref<String> DecodedBitStreamParser::decodeBase900toBase10(ArrayRef<int> codewords, int count)
|
Ref<String> DecodedBitStreamParser::decodeBase900toBase10(ArrayRef<int> codewords, int count)
|
||||||
{
|
{
|
||||||
InitExp900();
|
|
||||||
BigInteger result = BigInteger(0);
|
BigInteger result = BigInteger(0);
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
result = result + (AExp900_[count - i - 1] * BigInteger(codewords[i]));
|
result = result + (EXP900[count - i - 1] * BigInteger(codewords[i]));
|
||||||
}
|
}
|
||||||
string resultString = bigIntegerToString(result);
|
string resultString = bigIntegerToString(result);
|
||||||
if (resultString[0] != '1') {
|
if (resultString[0] != '1') {
|
||||||
|
|
|
@ -61,8 +61,8 @@ class DecodedBitStreamParser {
|
||||||
static const char PUNCT_CHARS[];
|
static const char PUNCT_CHARS[];
|
||||||
static const char MIXED_CHARS[];
|
static const char MIXED_CHARS[];
|
||||||
|
|
||||||
static ArrayRef<BigInteger> AExp900_;
|
static ArrayRef<BigInteger> EXP900;
|
||||||
static void InitExp900();
|
static ArrayRef<BigInteger> initEXP900();
|
||||||
|
|
||||||
static int textCompaction(ArrayRef<int> codewords, int codeIndex, Ref<String> result);
|
static int textCompaction(ArrayRef<int> codewords, int codeIndex, Ref<String> result);
|
||||||
static void decodeTextCompaction(ArrayRef<int> textCompactionData,
|
static void decodeTextCompaction(ArrayRef<int> textCompactionData,
|
||||||
|
|
|
@ -15,16 +15,18 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <zxing/pdf417/detector/Detector.h>
|
#include <zxing/pdf417/detector/Detector.h>
|
||||||
#include <zxing/pdf417/detector/LinesSampler.h>
|
#include <zxing/pdf417/detector/LinesSampler.h>
|
||||||
#include <zxing/common/GridSampler.h>
|
#include <zxing/common/GridSampler.h>
|
||||||
|
#include <zxing/common/detector/Math.h>
|
||||||
|
#include <zxing/common/detector/MathUtils.h>
|
||||||
|
|
||||||
using std::vector;
|
|
||||||
using std::max;
|
using std::max;
|
||||||
using std::numeric_limits;
|
using std::numeric_limits;
|
||||||
using zxing::pdf417::detector::Detector;
|
using zxing::pdf417::detector::Detector;
|
||||||
|
using zxing::common::detector::Math;
|
||||||
|
using zxing::common::detector::MathUtils;
|
||||||
using zxing::Ref;
|
using zxing::Ref;
|
||||||
using zxing::ArrayRef;
|
using zxing::ArrayRef;
|
||||||
using zxing::DetectorResult;
|
using zxing::DetectorResult;
|
||||||
|
@ -49,51 +51,33 @@ using zxing::Line;
|
||||||
* @author creatale GmbH (christoph.schulz@creatale.de)
|
* @author creatale GmbH (christoph.schulz@creatale.de)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const int Detector::MAX_AVG_VARIANCE = (int) ((1 << 8) * 0.42f);
|
const int Detector::MAX_AVG_VARIANCE= (int) (PATTERN_MATCH_RESULT_SCALE_FACTOR * 0.42f);
|
||||||
const int Detector::MAX_INDIVIDUAL_VARIANCE = (int) ((1 << 8) * 0.8f);
|
const int Detector::MAX_INDIVIDUAL_VARIANCE = (int) (PATTERN_MATCH_RESULT_SCALE_FACTOR * 0.8f);
|
||||||
|
|
||||||
// B S B S B S B S Bar/Space pattern
|
// B S B S B S B S Bar/Space pattern
|
||||||
// 11111111 0 1 0 1 0 1 000
|
// 11111111 0 1 0 1 0 1 000
|
||||||
const int Detector::START_PATTERN[] = {8, 1, 1, 1, 1, 1, 1, 3};
|
const int Detector::START_PATTERN[] = {8, 1, 1, 1, 1, 1, 1, 3};
|
||||||
|
const int Detector::START_PATTERN_LENGTH = sizeof(START_PATTERN) / sizeof(int);
|
||||||
|
|
||||||
// 11111111 0 1 0 1 0 1 000
|
// 11111111 0 1 0 1 0 1 000
|
||||||
const int Detector::START_PATTERN_REVERSE[] = {3, 1, 1, 1, 1, 1, 1, 8};
|
const int Detector::START_PATTERN_REVERSE[] = {3, 1, 1, 1, 1, 1, 1, 8};
|
||||||
|
const int Detector::START_PATTERN_REVERSE_LENGTH = sizeof(START_PATTERN_REVERSE) / sizeof(int);
|
||||||
|
|
||||||
// 1111111 0 1 000 1 0 1 00 1
|
// 1111111 0 1 000 1 0 1 00 1
|
||||||
const int Detector::STOP_PATTERN[] = {7, 1, 1, 3, 1, 1, 1, 2, 1};
|
const int Detector::STOP_PATTERN[] = {7, 1, 1, 3, 1, 1, 1, 2, 1};
|
||||||
|
const int Detector::STOP_PATTERN_LENGTH = sizeof(STOP_PATTERN) / sizeof(int);
|
||||||
|
|
||||||
// B S B S B S B S B Bar/Space pattern
|
// B S B S B S B S B Bar/Space pattern
|
||||||
// 1111111 0 1 000 1 0 1 00 1
|
// 1111111 0 1 000 1 0 1 00 1
|
||||||
const int Detector::STOP_PATTERN_REVERSE[] = {1, 2, 1, 1, 1, 3, 1, 1, 7};
|
const int Detector::STOP_PATTERN_REVERSE[] = {1, 2, 1, 1, 1, 3, 1, 1, 7};
|
||||||
|
const int Detector::STOP_PATTERN_REVERSE_LENGTH = sizeof(STOP_PATTERN_REVERSE) / sizeof(int);
|
||||||
|
|
||||||
const int Detector::SIZEOF_START_PATTERN = sizeof(START_PATTERN) / sizeof(int);
|
Detector::Detector(Ref<BinaryBitmap> image) : image_(image) {}
|
||||||
const int Detector::SIZEOF_START_PATTERN_REVERSE = sizeof(START_PATTERN_REVERSE) / sizeof(int);
|
|
||||||
const int Detector::SIZEOF_STOP_PATTERN = sizeof(STOP_PATTERN) / sizeof(int);
|
|
||||||
const int Detector::SIZEOF_STOP_PATTERN_REVERSE = sizeof(STOP_PATTERN_REVERSE) / sizeof(int);
|
|
||||||
const int Detector::COUNT_VERTICES = 16;
|
|
||||||
|
|
||||||
Detector::Detector(Ref<BinaryBitmap> image)
|
|
||||||
: image_(image) {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Detects a PDF417 Code in an image, simply.</p>
|
|
||||||
*
|
|
||||||
* @return {@link DetectorResult} encapsulating results of detecting a PDF417 Code
|
|
||||||
* @throws NotFoundException if no QR Code can be found
|
|
||||||
*/
|
|
||||||
Ref<DetectorResult> Detector::detect() {
|
Ref<DetectorResult> Detector::detect() {
|
||||||
DecodeHints defaultHints;
|
return detect(DecodeHints());
|
||||||
return detect(defaultHints);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Detects a PDF417 Code in an image. Only checks 0 and 180 degree rotations.</p>
|
|
||||||
*
|
|
||||||
* @param hints optional hints to detector
|
|
||||||
* @return {@link DetectorResult} encapsulating results of detecting a PDF417 Code
|
|
||||||
* @throws NotFoundException if no PDF417 Code can be found
|
|
||||||
*/
|
|
||||||
Ref<DetectorResult> Detector::detect(DecodeHints const& hints) {
|
Ref<DetectorResult> Detector::detect(DecodeHints const& hints) {
|
||||||
(void)hints;
|
(void)hints;
|
||||||
// Fetch the 1 bit matrix once up front.
|
// Fetch the 1 bit matrix once up front.
|
||||||
|
@ -101,19 +85,18 @@ Ref<DetectorResult> Detector::detect(DecodeHints const& hints) {
|
||||||
|
|
||||||
// Try to find the vertices assuming the image is upright.
|
// Try to find the vertices assuming the image is upright.
|
||||||
const int rowStep = 8;
|
const int rowStep = 8;
|
||||||
vector<Ref<ResultPoint> > vertices;
|
ArrayRef< Ref<ResultPoint> > vertices (findVertices(matrix, rowStep));
|
||||||
vertices = findVertices(matrix, rowStep);
|
if (!vertices) {
|
||||||
if (vertices.empty()) {
|
|
||||||
// Maybe the image is rotated 180 degrees?
|
// Maybe the image is rotated 180 degrees?
|
||||||
vertices = findVertices180(matrix, rowStep);
|
vertices = findVertices180(matrix, rowStep);
|
||||||
if (!vertices.empty()) {
|
if (vertices) {
|
||||||
correctVertices(matrix, vertices, true);
|
correctVertices(matrix, vertices, true);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
correctVertices(matrix, vertices, false);
|
correctVertices(matrix, vertices, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vertices.empty()) {
|
if (!vertices) {
|
||||||
throw NotFoundException("No vertices found.");
|
throw NotFoundException("No vertices found.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,15 +116,13 @@ Ref<DetectorResult> Detector::detect(DecodeHints const& hints) {
|
||||||
|
|
||||||
// Deskew and sample lines from image.
|
// Deskew and sample lines from image.
|
||||||
Ref<BitMatrix> linesMatrix = sampleLines(vertices, dimension, yDimension);
|
Ref<BitMatrix> linesMatrix = sampleLines(vertices, dimension, yDimension);
|
||||||
LinesSampler sampler(linesMatrix, dimension);
|
Ref<BitMatrix> linesGrid(LinesSampler(linesMatrix, dimension).sample());
|
||||||
Ref<BitMatrix> linesGrid(sampler.sample());
|
|
||||||
|
|
||||||
//TODO: verify vertices (was vertices[5 4 6 7]).
|
|
||||||
ArrayRef< Ref<ResultPoint> > points(4);
|
ArrayRef< Ref<ResultPoint> > points(4);
|
||||||
points[0] = new ResultPoint(0.0f, (float)linesMatrix->getHeight());
|
points[0] = vertices[5];
|
||||||
points[1] = new ResultPoint(0.0f, 0.0f);
|
points[1] = vertices[4];
|
||||||
points[2] = new ResultPoint((float)linesMatrix->getWidth(), 0.0f);
|
points[2] = vertices[6];
|
||||||
points[3] = new ResultPoint((float)linesMatrix->getWidth(), (float)linesMatrix->getHeight());
|
points[3] = vertices[7];
|
||||||
return Ref<DetectorResult>(new DetectorResult(linesGrid, points));
|
return Ref<DetectorResult>(new DetectorResult(linesGrid, points));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,20 +142,20 @@ Ref<DetectorResult> Detector::detect(DecodeHints const& hints) {
|
||||||
* vertices[6] x, y top right codeword area
|
* vertices[6] x, y top right codeword area
|
||||||
* vertices[7] x, y bottom right codeword area
|
* vertices[7] x, y bottom right codeword area
|
||||||
*/
|
*/
|
||||||
vector<Ref<ResultPoint> > Detector::findVertices(Ref<BitMatrix> matrix, int rowStep)
|
ArrayRef< Ref<ResultPoint> > Detector::findVertices(Ref<BitMatrix> matrix, int rowStep)
|
||||||
{
|
{
|
||||||
const int height = matrix->getHeight();
|
const int height = matrix->getHeight();
|
||||||
const int width = matrix->getWidth();
|
const int width = matrix->getWidth();
|
||||||
|
|
||||||
vector<Ref<ResultPoint> > result(COUNT_VERTICES);
|
ArrayRef< Ref<ResultPoint> > result(16);
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
|
||||||
ArrayRef<int> counters(new Array<int>(SIZEOF_START_PATTERN));
|
ArrayRef<int> counters(new Array<int>(START_PATTERN_LENGTH));
|
||||||
|
|
||||||
// Top Left
|
// Top Left
|
||||||
for (int i = 0; i < height; i += rowStep) {
|
for (int i = 0; i < height; i += rowStep) {
|
||||||
ArrayRef<int> loc = findGuardPattern(matrix, 0, i, width, false, START_PATTERN,
|
ArrayRef<int> loc = findGuardPattern(matrix, 0, i, width, false, START_PATTERN,
|
||||||
SIZEOF_START_PATTERN, counters);
|
START_PATTERN_LENGTH, counters);
|
||||||
if (loc) {
|
if (loc) {
|
||||||
result[0] = new ResultPoint((float)loc[0], (float)i);
|
result[0] = new ResultPoint((float)loc[0], (float)i);
|
||||||
result[4] = new ResultPoint((float)loc[1], (float)i);
|
result[4] = new ResultPoint((float)loc[1], (float)i);
|
||||||
|
@ -185,9 +166,9 @@ vector<Ref<ResultPoint> > Detector::findVertices(Ref<BitMatrix> matrix, int rowS
|
||||||
// Bottom left
|
// Bottom left
|
||||||
if (found) { // Found the Top Left vertex
|
if (found) { // Found the Top Left vertex
|
||||||
found = false;
|
found = false;
|
||||||
for (long i = height - 1; i > 0; i -= rowStep) {
|
for (int i = height - 1; i > 0; i -= rowStep) {
|
||||||
ArrayRef<int> loc = findGuardPattern(matrix, 0, i, width, false, START_PATTERN,
|
ArrayRef<int> loc = findGuardPattern(matrix, 0, i, width, false, START_PATTERN,
|
||||||
SIZEOF_START_PATTERN, counters);
|
START_PATTERN_LENGTH, counters);
|
||||||
if (loc) {
|
if (loc) {
|
||||||
result[1] = new ResultPoint((float)loc[0], (float)i);
|
result[1] = new ResultPoint((float)loc[0], (float)i);
|
||||||
result[5] = new ResultPoint((float)loc[1], (float)i);
|
result[5] = new ResultPoint((float)loc[1], (float)i);
|
||||||
|
@ -197,14 +178,14 @@ vector<Ref<ResultPoint> > Detector::findVertices(Ref<BitMatrix> matrix, int rowS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
counters = new Array<int>(SIZEOF_STOP_PATTERN);
|
counters = new Array<int>(STOP_PATTERN_LENGTH);
|
||||||
|
|
||||||
// Top right
|
// Top right
|
||||||
if (found) { // Found the Bottom Left vertex
|
if (found) { // Found the Bottom Left vertex
|
||||||
found = false;
|
found = false;
|
||||||
for (int i = 0; i < height; i += rowStep) {
|
for (int i = 0; i < height; i += rowStep) {
|
||||||
ArrayRef<int> loc = findGuardPattern(matrix, 0, i, width, false, STOP_PATTERN,
|
ArrayRef<int> loc = findGuardPattern(matrix, 0, i, width, false, STOP_PATTERN,
|
||||||
SIZEOF_STOP_PATTERN, counters);
|
STOP_PATTERN_LENGTH, counters);
|
||||||
if (loc) {
|
if (loc) {
|
||||||
result[2] = new ResultPoint((float)loc[1], (float)i);
|
result[2] = new ResultPoint((float)loc[1], (float)i);
|
||||||
result[6] = new ResultPoint((float)loc[0], (float)i);
|
result[6] = new ResultPoint((float)loc[0], (float)i);
|
||||||
|
@ -216,9 +197,9 @@ vector<Ref<ResultPoint> > Detector::findVertices(Ref<BitMatrix> matrix, int rowS
|
||||||
// Bottom right
|
// Bottom right
|
||||||
if (found) { // Found the Top right vertex
|
if (found) { // Found the Top right vertex
|
||||||
found = false;
|
found = false;
|
||||||
for (long i = height - 1; i > 0; i -= rowStep) {
|
for (int i = height - 1; i > 0; i -= rowStep) {
|
||||||
ArrayRef<int> loc = findGuardPattern(matrix, 0, i, width, false, STOP_PATTERN,
|
ArrayRef<int> loc = findGuardPattern(matrix, 0, i, width, false, STOP_PATTERN,
|
||||||
SIZEOF_STOP_PATTERN, counters);
|
STOP_PATTERN_LENGTH, counters);
|
||||||
if (loc) {
|
if (loc) {
|
||||||
result[3] = new ResultPoint((float)loc[1], (float)i);
|
result[3] = new ResultPoint((float)loc[1], (float)i);
|
||||||
result[7] = new ResultPoint((float)loc[0], (float)i);
|
result[7] = new ResultPoint((float)loc[0], (float)i);
|
||||||
|
@ -228,48 +209,24 @@ vector<Ref<ResultPoint> > Detector::findVertices(Ref<BitMatrix> matrix, int rowS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!found) {
|
return found ? result : ArrayRef< Ref<ResultPoint> >();
|
||||||
// Do not return partial results (instead of returning null).
|
|
||||||
result.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
ArrayRef< Ref<ResultPoint> > Detector::findVertices180(Ref<BitMatrix> matrix, int rowStep) {
|
||||||
* Locate the vertices and the codewords area of a black blob using the Start
|
|
||||||
* and Stop patterns as locators. This assumes that the image is rotated 180
|
|
||||||
* degrees and if it locates the start and stop patterns at it will re-map
|
|
||||||
* the vertices for a 0 degree rotation.
|
|
||||||
* TODO: Change assumption about barcode location.
|
|
||||||
*
|
|
||||||
* @param matrix the scanned barcode image.
|
|
||||||
* @param rowStep the step size for iterating rows (every n-th row).
|
|
||||||
* @return an array containing the vertices:
|
|
||||||
* vertices[0] x, y top left barcode
|
|
||||||
* vertices[1] x, y bottom left barcode
|
|
||||||
* vertices[2] x, y top right barcode
|
|
||||||
* vertices[3] x, y bottom right barcode
|
|
||||||
* vertices[4] x, y top left codeword area
|
|
||||||
* vertices[5] x, y bottom left codeword area
|
|
||||||
* vertices[6] x, y top right codeword area
|
|
||||||
* vertices[7] x, y bottom right codeword area
|
|
||||||
*/
|
|
||||||
vector<Ref<ResultPoint> > Detector::findVertices180(Ref<BitMatrix> matrix, int rowStep)
|
|
||||||
{
|
|
||||||
const int height = matrix->getHeight();
|
const int height = matrix->getHeight();
|
||||||
const int width = matrix->getWidth();
|
const int width = matrix->getWidth();
|
||||||
const int halfWidth = width >> 1;
|
const int halfWidth = width >> 1;
|
||||||
|
|
||||||
vector<Ref<ResultPoint> > result(COUNT_VERTICES);
|
ArrayRef< Ref<ResultPoint> > result(16);
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
|
||||||
ArrayRef<int> counters = new Array<int>(SIZEOF_START_PATTERN_REVERSE);
|
ArrayRef<int> counters = new Array<int>(START_PATTERN_REVERSE_LENGTH);
|
||||||
|
|
||||||
// Top Left
|
// Top Left
|
||||||
for (int i = height - 1; i > 0; i -= rowStep) {
|
for (int i = height - 1; i > 0; i -= rowStep) {
|
||||||
ArrayRef<int> loc = findGuardPattern(matrix, halfWidth, i, halfWidth, true, START_PATTERN_REVERSE,
|
ArrayRef<int> loc =
|
||||||
SIZEOF_START_PATTERN_REVERSE, counters);
|
findGuardPattern(matrix, halfWidth, i, halfWidth, true, START_PATTERN_REVERSE,
|
||||||
|
START_PATTERN_REVERSE_LENGTH, counters);
|
||||||
if (loc) {
|
if (loc) {
|
||||||
result[0] = new ResultPoint((float)loc[1], (float)i);
|
result[0] = new ResultPoint((float)loc[1], (float)i);
|
||||||
result[4] = new ResultPoint((float)loc[0], (float)i);
|
result[4] = new ResultPoint((float)loc[0], (float)i);
|
||||||
|
@ -281,8 +238,9 @@ vector<Ref<ResultPoint> > Detector::findVertices180(Ref<BitMatrix> matrix, int r
|
||||||
if (found) { // Found the Top Left vertex
|
if (found) { // Found the Top Left vertex
|
||||||
found = false;
|
found = false;
|
||||||
for (int i = 0; i < height; i += rowStep) {
|
for (int i = 0; i < height; i += rowStep) {
|
||||||
ArrayRef<int> loc = findGuardPattern(matrix, halfWidth, i, halfWidth, true, START_PATTERN_REVERSE,
|
ArrayRef<int> loc =
|
||||||
SIZEOF_START_PATTERN_REVERSE, counters);
|
findGuardPattern(matrix, halfWidth, i, halfWidth, true, START_PATTERN_REVERSE,
|
||||||
|
START_PATTERN_REVERSE_LENGTH, counters);
|
||||||
if (loc) {
|
if (loc) {
|
||||||
result[1] = new ResultPoint((float)loc[1], (float)i);
|
result[1] = new ResultPoint((float)loc[1], (float)i);
|
||||||
result[5] = new ResultPoint((float)loc[0], (float)i);
|
result[5] = new ResultPoint((float)loc[0], (float)i);
|
||||||
|
@ -292,14 +250,14 @@ vector<Ref<ResultPoint> > Detector::findVertices180(Ref<BitMatrix> matrix, int r
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
counters = new Array<int>(SIZEOF_STOP_PATTERN_REVERSE);
|
counters = new Array<int>(STOP_PATTERN_REVERSE_LENGTH);
|
||||||
|
|
||||||
// Top Right
|
// Top Right
|
||||||
if (found) { // Found the Bottom Left vertex
|
if (found) { // Found the Bottom Left vertex
|
||||||
found = false;
|
found = false;
|
||||||
for (int i = height - 1; i > 0; i -= rowStep) {
|
for (int i = height - 1; i > 0; i -= rowStep) {
|
||||||
ArrayRef<int> loc = findGuardPattern(matrix, 0, i, halfWidth, false, STOP_PATTERN_REVERSE,
|
ArrayRef<int> loc = findGuardPattern(matrix, 0, i, halfWidth, false, STOP_PATTERN_REVERSE,
|
||||||
SIZEOF_STOP_PATTERN_REVERSE, counters);
|
STOP_PATTERN_REVERSE_LENGTH, counters);
|
||||||
if (loc) {
|
if (loc) {
|
||||||
result[2] = new ResultPoint((float)loc[0], (float)i);
|
result[2] = new ResultPoint((float)loc[0], (float)i);
|
||||||
result[6] = new ResultPoint((float)loc[1], (float)i);
|
result[6] = new ResultPoint((float)loc[1], (float)i);
|
||||||
|
@ -313,7 +271,7 @@ vector<Ref<ResultPoint> > Detector::findVertices180(Ref<BitMatrix> matrix, int r
|
||||||
found = false;
|
found = false;
|
||||||
for (int i = 0; i < height; i += rowStep) {
|
for (int i = 0; i < height; i += rowStep) {
|
||||||
ArrayRef<int> loc = findGuardPattern(matrix, 0, i, halfWidth, false, STOP_PATTERN_REVERSE,
|
ArrayRef<int> loc = findGuardPattern(matrix, 0, i, halfWidth, false, STOP_PATTERN_REVERSE,
|
||||||
SIZEOF_STOP_PATTERN_REVERSE, counters);
|
STOP_PATTERN_REVERSE_LENGTH, counters);
|
||||||
if (loc) {
|
if (loc) {
|
||||||
result[3] = new ResultPoint((float)loc[0], (float)i);
|
result[3] = new ResultPoint((float)loc[0], (float)i);
|
||||||
result[7] = new ResultPoint((float)loc[1], (float)i);
|
result[7] = new ResultPoint((float)loc[1], (float)i);
|
||||||
|
@ -323,12 +281,7 @@ vector<Ref<ResultPoint> > Detector::findVertices180(Ref<BitMatrix> matrix, int r
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!found) {
|
return found ? result : ArrayRef< Ref<ResultPoint> >();
|
||||||
// Do not return partial results (instead of returning null).
|
|
||||||
result.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -348,7 +301,7 @@ ArrayRef<int> Detector::findGuardPattern(Ref<BitMatrix> matrix,
|
||||||
bool whiteFirst,
|
bool whiteFirst,
|
||||||
const int pattern[],
|
const int pattern[],
|
||||||
int patternSize,
|
int patternSize,
|
||||||
ArrayRef<int> counters) {
|
ArrayRef<int>& counters) {
|
||||||
counters->values().assign(counters->size(), 0);
|
counters->values().assign(counters->size(), 0);
|
||||||
int patternLength = patternSize;
|
int patternLength = patternSize;
|
||||||
bool isWhite = whiteFirst;
|
bool isWhite = whiteFirst;
|
||||||
|
@ -399,7 +352,8 @@ ArrayRef<int> Detector::findGuardPattern(Ref<BitMatrix> matrix,
|
||||||
* variance between counters and patterns equals the pattern length,
|
* variance between counters and patterns equals the pattern length,
|
||||||
* higher values mean even more variance
|
* higher values mean even more variance
|
||||||
*/
|
*/
|
||||||
int Detector::patternMatchVariance(ArrayRef<int> counters, const int pattern[],
|
int Detector::patternMatchVariance(ArrayRef<int>& counters,
|
||||||
|
const int pattern[],
|
||||||
int maxIndividualVariance)
|
int maxIndividualVariance)
|
||||||
{
|
{
|
||||||
int numCounters = counters->size();
|
int numCounters = counters->size();
|
||||||
|
@ -451,7 +405,7 @@ int Detector::patternMatchVariance(ArrayRef<int> counters, const int pattern[],
|
||||||
* @param upsideDown true if rotated by 180 degree.
|
* @param upsideDown true if rotated by 180 degree.
|
||||||
*/
|
*/
|
||||||
void Detector::correctVertices(Ref<BitMatrix> matrix,
|
void Detector::correctVertices(Ref<BitMatrix> matrix,
|
||||||
vector<Ref<ResultPoint> > &vertices,
|
ArrayRef< Ref<ResultPoint> >& vertices,
|
||||||
bool upsideDown)
|
bool upsideDown)
|
||||||
{
|
{
|
||||||
bool isLowLeft = abs(vertices[4]->getY() - vertices[5]->getY()) < 20.0;
|
bool isLowLeft = abs(vertices[4]->getY() - vertices[5]->getY()) < 20.0;
|
||||||
|
@ -487,7 +441,7 @@ void Detector::correctVertices(Ref<BitMatrix> matrix,
|
||||||
* @param rowStep +1 if corner should be exceeded towards the bottom, -1 towards the top.
|
* @param rowStep +1 if corner should be exceeded towards the bottom, -1 towards the top.
|
||||||
*/
|
*/
|
||||||
void Detector::findWideBarTopBottom(Ref<BitMatrix> matrix,
|
void Detector::findWideBarTopBottom(Ref<BitMatrix> matrix,
|
||||||
vector<Ref<ResultPoint> > &vertices,
|
ArrayRef< Ref<ResultPoint> > &vertices,
|
||||||
int offsetVertice,
|
int offsetVertice,
|
||||||
int startWideBar,
|
int startWideBar,
|
||||||
int lenWideBar,
|
int lenWideBar,
|
||||||
|
@ -502,10 +456,10 @@ void Detector::findWideBarTopBottom(Ref<BitMatrix> matrix,
|
||||||
float barDiff = verticeEnd->getX() - verticeStart->getX();
|
float barDiff = verticeEnd->getX() - verticeStart->getX();
|
||||||
float barStart = verticeStart->getX() + barDiff * (float)startWideBar / (float)lenPattern;
|
float barStart = verticeStart->getX() + barDiff * (float)startWideBar / (float)lenPattern;
|
||||||
float barEnd = verticeStart->getX() + barDiff * (float)endWideBar / (float)lenPattern;
|
float barEnd = verticeStart->getX() + barDiff * (float)endWideBar / (float)lenPattern;
|
||||||
int x = round((barStart + barEnd) / 2.0f);
|
int x = Math::round((barStart + barEnd) / 2.0f);
|
||||||
|
|
||||||
// Start vertically between the preliminary vertices.
|
// Start vertically between the preliminary vertices.
|
||||||
int yStart = round(verticeStart->getY());
|
int yStart = Math::round(verticeStart->getY());
|
||||||
int y = yStart;
|
int y = yStart;
|
||||||
|
|
||||||
// Find offset of thin bar to the right as additional safeguard.
|
// Find offset of thin bar to the right as additional safeguard.
|
||||||
|
@ -557,11 +511,11 @@ void Detector::findWideBarTopBottom(Ref<BitMatrix> matrix,
|
||||||
* @return Returns true when the result is valid and lies inside the matrix. Otherwise throws an
|
* @return Returns true when the result is valid and lies inside the matrix. Otherwise throws an
|
||||||
* exception.
|
* exception.
|
||||||
**/
|
**/
|
||||||
void Detector::findCrossingPoint(vector<Ref<ResultPoint> > &vertices,
|
void Detector::findCrossingPoint(ArrayRef< Ref<ResultPoint> >& vertices,
|
||||||
int idxResult,
|
int idxResult,
|
||||||
int idxLineA1, int idxLineA2,
|
int idxLineA1, int idxLineA2,
|
||||||
int idxLineB1, int idxLineB2,
|
int idxLineB1, int idxLineB2,
|
||||||
Ref<BitMatrix> matrix)
|
Ref<BitMatrix>& matrix)
|
||||||
{
|
{
|
||||||
Point p1(vertices[idxLineA1]->getX(), vertices[idxLineA1]->getY());
|
Point p1(vertices[idxLineA1]->getX(), vertices[idxLineA1]->getY());
|
||||||
Point p2(vertices[idxLineA2]->getX(), vertices[idxLineA2]->getY());
|
Point p2(vertices[idxLineA2]->getX(), vertices[idxLineA2]->getY());
|
||||||
|
@ -574,13 +528,13 @@ void Detector::findCrossingPoint(vector<Ref<ResultPoint> > &vertices,
|
||||||
throw NotFoundException("PDF:Detector: cannot find the crossing of parallel lines!");
|
throw NotFoundException("PDF:Detector: cannot find the crossing of parallel lines!");
|
||||||
}
|
}
|
||||||
|
|
||||||
int x = round(result.x);
|
int x = Math::round(result.x);
|
||||||
int y = round(result.y);
|
int y = Math::round(result.y);
|
||||||
if (x < 0 || x >= (int)matrix->getWidth() || y < 0 || y >= (int)matrix->getHeight()) {
|
if (x < 0 || x >= (int)matrix->getWidth() || y < 0 || y >= (int)matrix->getHeight()) {
|
||||||
throw NotFoundException("PDF:Detector: crossing points out of region!");
|
throw NotFoundException("PDF:Detector: crossing points out of region!");
|
||||||
}
|
}
|
||||||
|
|
||||||
vertices[idxResult] = new ResultPoint(result.x, result.y);
|
vertices[idxResult] = Ref<ResultPoint>(new ResultPoint(result.x, result.y));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -620,8 +574,7 @@ Point Detector::intersection(Line a, Line b) {
|
||||||
* vertices[7] x, y bottom right codeword area
|
* vertices[7] x, y bottom right codeword area
|
||||||
* @return the module size.
|
* @return the module size.
|
||||||
*/
|
*/
|
||||||
float Detector::computeModuleWidth(vector<Ref<ResultPoint> > &vertices)
|
float Detector::computeModuleWidth(ArrayRef< Ref<ResultPoint> >& vertices) {
|
||||||
{
|
|
||||||
float pixels1 = ResultPoint::distance(vertices[0], vertices[4]);
|
float pixels1 = ResultPoint::distance(vertices[0], vertices[4]);
|
||||||
float pixels2 = ResultPoint::distance(vertices[1], vertices[5]);
|
float pixels2 = ResultPoint::distance(vertices[1], vertices[5]);
|
||||||
float moduleWidth1 = (pixels1 + pixels2) / (17 * 2.0f);
|
float moduleWidth1 = (pixels1 + pixels2) / (17 * 2.0f);
|
||||||
|
@ -642,14 +595,15 @@ float Detector::computeModuleWidth(vector<Ref<ResultPoint> > &vertices)
|
||||||
* @param moduleWidth estimated module size
|
* @param moduleWidth estimated module size
|
||||||
* @return the number of modules in a row.
|
* @return the number of modules in a row.
|
||||||
*/
|
*/
|
||||||
int Detector::computeDimension(Ref<ResultPoint> topLeft,
|
int Detector::computeDimension(Ref<ResultPoint> const& topLeft,
|
||||||
Ref<ResultPoint> topRight,
|
Ref<ResultPoint> const& topRight,
|
||||||
Ref<ResultPoint> bottomLeft,
|
Ref<ResultPoint> const& bottomLeft,
|
||||||
Ref<ResultPoint> bottomRight,
|
Ref<ResultPoint> const& bottomRight,
|
||||||
float moduleWidth)
|
float moduleWidth)
|
||||||
{
|
{
|
||||||
int topRowDimension = round(ResultPoint::distance(topLeft, topRight) / moduleWidth);
|
int topRowDimension = MathUtils::round(ResultPoint::distance(topLeft, topRight) / moduleWidth);
|
||||||
int bottomRowDimension = round(ResultPoint::distance(bottomLeft, bottomRight) / moduleWidth);
|
int bottomRowDimension =
|
||||||
|
MathUtils::round(ResultPoint::distance(bottomLeft, bottomRight) / moduleWidth);
|
||||||
return ((((topRowDimension + bottomRowDimension) >> 1) + 8) / 17) * 17;
|
return ((((topRowDimension + bottomRowDimension) >> 1) + 8) / 17) * 17;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -664,14 +618,16 @@ int Detector::computeDimension(Ref<ResultPoint> topLeft,
|
||||||
* @param moduleWidth estimated module size
|
* @param moduleWidth estimated module size
|
||||||
* @return the number of modules in a row.
|
* @return the number of modules in a row.
|
||||||
*/
|
*/
|
||||||
int Detector::computeYDimension(Ref<ResultPoint> topLeft,
|
int Detector::computeYDimension(Ref<ResultPoint> const& topLeft,
|
||||||
Ref<ResultPoint> topRight,
|
Ref<ResultPoint> const& topRight,
|
||||||
Ref<ResultPoint> bottomLeft,
|
Ref<ResultPoint> const& bottomLeft,
|
||||||
Ref<ResultPoint> bottomRight,
|
Ref<ResultPoint> const& bottomRight,
|
||||||
float moduleWidth)
|
float moduleWidth)
|
||||||
{
|
{
|
||||||
int leftColumnDimension = round(ResultPoint::distance(topLeft, bottomLeft) / moduleWidth);
|
int leftColumnDimension =
|
||||||
int rightColumnDimension = round(ResultPoint::distance(topRight, bottomRight) / moduleWidth);
|
MathUtils::round(ResultPoint::distance(topLeft, bottomLeft) / moduleWidth);
|
||||||
|
int rightColumnDimension =
|
||||||
|
MathUtils::round(ResultPoint::distance(topRight, bottomRight) / moduleWidth);
|
||||||
return (leftColumnDimension + rightColumnDimension) >> 1;
|
return (leftColumnDimension + rightColumnDimension) >> 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -683,8 +639,9 @@ int Detector::computeYDimension(Ref<ResultPoint> topLeft,
|
||||||
* @param yDimension y dimension
|
* @param yDimension y dimension
|
||||||
* @return an over-sampled BitMatrix.
|
* @return an over-sampled BitMatrix.
|
||||||
*/
|
*/
|
||||||
Ref<BitMatrix> Detector::sampleLines(const vector<Ref<ResultPoint> >& vertices, int dimensionY, int dimension)
|
Ref<BitMatrix> Detector::sampleLines(ArrayRef< Ref<ResultPoint> > const& vertices,
|
||||||
{
|
int dimensionY,
|
||||||
|
int dimension) {
|
||||||
const int sampleDimensionX = dimension * 8;
|
const int sampleDimensionX = dimension * 8;
|
||||||
const int sampleDimensionY = dimensionY * 4;
|
const int sampleDimensionY = dimensionY * 4;
|
||||||
Ref<PerspectiveTransform> transform(
|
Ref<PerspectiveTransform> transform(
|
||||||
|
@ -704,12 +661,3 @@ Ref<BitMatrix> Detector::sampleLines(const vector<Ref<ResultPoint> >& vertices,
|
||||||
|
|
||||||
return linesMatrix;
|
return linesMatrix;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Ends up being a bit faster than Math.round(). This merely rounds its
|
|
||||||
* argument to the nearest int, where x.5 rounds up.
|
|
||||||
*/
|
|
||||||
int Detector::round(float d)
|
|
||||||
{
|
|
||||||
return (int)(d + 0.5f);
|
|
||||||
}
|
|
||||||
|
|
|
@ -32,22 +32,24 @@ namespace detector {
|
||||||
|
|
||||||
class Detector {
|
class Detector {
|
||||||
private:
|
private:
|
||||||
|
static const int INTEGER_MATH_SHIFT = 8;
|
||||||
|
static const int PATTERN_MATCH_RESULT_SCALE_FACTOR = 1 << INTEGER_MATH_SHIFT;
|
||||||
static const int MAX_AVG_VARIANCE;
|
static const int MAX_AVG_VARIANCE;
|
||||||
static const int MAX_INDIVIDUAL_VARIANCE;
|
static const int MAX_INDIVIDUAL_VARIANCE;
|
||||||
|
|
||||||
static const int START_PATTERN[];
|
static const int START_PATTERN[];
|
||||||
|
static const int START_PATTERN_LENGTH;
|
||||||
static const int START_PATTERN_REVERSE[];
|
static const int START_PATTERN_REVERSE[];
|
||||||
|
static const int START_PATTERN_REVERSE_LENGTH;
|
||||||
static const int STOP_PATTERN[];
|
static const int STOP_PATTERN[];
|
||||||
|
static const int STOP_PATTERN_LENGTH;
|
||||||
static const int STOP_PATTERN_REVERSE[];
|
static const int STOP_PATTERN_REVERSE[];
|
||||||
static const int SIZEOF_START_PATTERN;
|
static const int STOP_PATTERN_REVERSE_LENGTH;
|
||||||
static const int SIZEOF_START_PATTERN_REVERSE;
|
|
||||||
static const int SIZEOF_STOP_PATTERN;
|
|
||||||
static const int SIZEOF_STOP_PATTERN_REVERSE;
|
|
||||||
static const int COUNT_VERTICES;
|
|
||||||
|
|
||||||
Ref<BinaryBitmap> image_;
|
Ref<BinaryBitmap> image_;
|
||||||
|
|
||||||
static std::vector<Ref<ResultPoint> > findVertices(Ref<BitMatrix> matrix, int rowStep);
|
static ArrayRef< Ref<ResultPoint> > findVertices(Ref<BitMatrix> matrix, int rowStep);
|
||||||
static std::vector<Ref<ResultPoint> > findVertices180(Ref<BitMatrix> matrix, int rowStep);
|
static ArrayRef< Ref<ResultPoint> > findVertices180(Ref<BitMatrix> matrix, int rowStep);
|
||||||
|
|
||||||
static ArrayRef<int> findGuardPattern(Ref<BitMatrix> matrix,
|
static ArrayRef<int> findGuardPattern(Ref<BitMatrix> matrix,
|
||||||
int column,
|
int column,
|
||||||
|
@ -56,41 +58,39 @@ private:
|
||||||
bool whiteFirst,
|
bool whiteFirst,
|
||||||
const int pattern[],
|
const int pattern[],
|
||||||
int patternSize,
|
int patternSize,
|
||||||
ArrayRef<int> counters);
|
ArrayRef<int>& counters);
|
||||||
static int patternMatchVariance(ArrayRef<int> counters, const int pattern[],
|
static int patternMatchVariance(ArrayRef<int>& counters, const int pattern[],
|
||||||
int maxIndividualVariance);
|
int maxIndividualVariance);
|
||||||
|
|
||||||
static void correctVertices(Ref<BitMatrix> matrix,
|
static void correctVertices(Ref<BitMatrix> matrix,
|
||||||
std::vector<Ref<ResultPoint> > &vertices,
|
ArrayRef< Ref<ResultPoint> >& vertices,
|
||||||
bool upsideDown);
|
bool upsideDown);
|
||||||
static void findWideBarTopBottom(Ref<BitMatrix> matrix,
|
static void findWideBarTopBottom(Ref<BitMatrix> matrix,
|
||||||
std::vector<Ref<ResultPoint> > &vertices,
|
ArrayRef< Ref<ResultPoint> >& vertices,
|
||||||
int offsetVertice,
|
int offsetVertice,
|
||||||
int startWideBar,
|
int startWideBar,
|
||||||
int lenWideBar,
|
int lenWideBar,
|
||||||
int lenPattern,
|
int lenPattern,
|
||||||
int nIncrement);
|
int nIncrement);
|
||||||
static void findCrossingPoint(std::vector<Ref<ResultPoint> > &vertices,
|
static void findCrossingPoint(ArrayRef< Ref<ResultPoint> >& vertices,
|
||||||
int idxResult,
|
int idxResult,
|
||||||
int idxLineA1,int idxLineA2,
|
int idxLineA1,int idxLineA2,
|
||||||
int idxLineB1,int idxLineB2,
|
int idxLineB1,int idxLineB2,
|
||||||
Ref<BitMatrix> matrix);
|
Ref<BitMatrix>& matrix);
|
||||||
static Point intersection(Line a, Line b);
|
static Point intersection(Line a, Line b);
|
||||||
static float computeModuleWidth(std::vector<Ref<ResultPoint> > &vertices);
|
static float computeModuleWidth(ArrayRef< Ref<ResultPoint> >& vertices);
|
||||||
static int computeDimension(Ref<ResultPoint> topLeft,
|
static int computeDimension(Ref<ResultPoint> const& topLeft,
|
||||||
Ref<ResultPoint> topRight,
|
Ref<ResultPoint> const& topRight,
|
||||||
Ref<ResultPoint> bottomLeft,
|
Ref<ResultPoint> const& bottomLeft,
|
||||||
Ref<ResultPoint> bottomRight,
|
Ref<ResultPoint> const& bottomRight,
|
||||||
float moduleWidth);
|
float moduleWidth);
|
||||||
int computeYDimension(Ref<ResultPoint> topLeft,
|
int computeYDimension(Ref<ResultPoint> const& topLeft,
|
||||||
Ref<ResultPoint> topRight,
|
Ref<ResultPoint> const& topRight,
|
||||||
Ref<ResultPoint> bottomLeft,
|
Ref<ResultPoint> const& bottomLeft,
|
||||||
Ref<ResultPoint> bottomRight,
|
Ref<ResultPoint> const& bottomRight,
|
||||||
float moduleWidth);
|
float moduleWidth);
|
||||||
|
|
||||||
Ref<BitMatrix> sampleLines(const std::vector<Ref<ResultPoint> > &vertices, int dimensionY, int dimension);
|
Ref<BitMatrix> sampleLines(ArrayRef< Ref<ResultPoint> > const& vertices, int dimensionY, int dimension);
|
||||||
|
|
||||||
static int round(float d);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Detector(Ref<BinaryBitmap> image);
|
Detector(Ref<BinaryBitmap> image);
|
||||||
|
|
|
@ -31,7 +31,6 @@
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
namespace math_utils = zxing::common::detector::math_utils;
|
|
||||||
|
|
||||||
using std::ostringstream;
|
using std::ostringstream;
|
||||||
using std::min;
|
using std::min;
|
||||||
|
@ -44,6 +43,7 @@ using zxing::ResultPointCallback;
|
||||||
using zxing::DetectorResult;
|
using zxing::DetectorResult;
|
||||||
using zxing::PerspectiveTransform;
|
using zxing::PerspectiveTransform;
|
||||||
using zxing::qrcode::AlignmentPattern;
|
using zxing::qrcode::AlignmentPattern;
|
||||||
|
using zxing::common::detector::MathUtils;
|
||||||
|
|
||||||
// VC++
|
// VC++
|
||||||
using zxing::DecodeHints;
|
using zxing::DecodeHints;
|
||||||
|
@ -166,9 +166,9 @@ Ref<BitMatrix> Detector::sampleGrid(Ref<BitMatrix> image, int dimension, Ref<Per
|
||||||
int Detector::computeDimension(Ref<ResultPoint> topLeft, Ref<ResultPoint> topRight, Ref<ResultPoint> bottomLeft,
|
int Detector::computeDimension(Ref<ResultPoint> topLeft, Ref<ResultPoint> topRight, Ref<ResultPoint> bottomLeft,
|
||||||
float moduleSize) {
|
float moduleSize) {
|
||||||
int tltrCentersDimension =
|
int tltrCentersDimension =
|
||||||
math_utils::round(ResultPoint::distance(topLeft, topRight) / moduleSize);
|
MathUtils::round(ResultPoint::distance(topLeft, topRight) / moduleSize);
|
||||||
int tlblCentersDimension =
|
int tlblCentersDimension =
|
||||||
math_utils::round(ResultPoint::distance(topLeft, bottomLeft) / moduleSize);
|
MathUtils::round(ResultPoint::distance(topLeft, bottomLeft) / moduleSize);
|
||||||
int dimension = ((tltrCentersDimension + tlblCentersDimension) >> 1) + 7;
|
int dimension = ((tltrCentersDimension + tlblCentersDimension) >> 1) + 7;
|
||||||
switch (dimension & 0x03) { // mod 4
|
switch (dimension & 0x03) { // mod 4
|
||||||
case 0:
|
case 0:
|
||||||
|
@ -269,7 +269,7 @@ float Detector::sizeOfBlackWhiteBlackRun(int fromX, int fromY, int toX, int toY)
|
||||||
// Does current pixel mean we have moved white to black or vice versa?
|
// Does current pixel mean we have moved white to black or vice versa?
|
||||||
if (!((state == 1) ^ image_->get(realX, realY))) {
|
if (!((state == 1) ^ image_->get(realX, realY))) {
|
||||||
if (state == 2) {
|
if (state == 2) {
|
||||||
return math_utils::distance(x, y, fromX, fromY);
|
return MathUtils::distance(x, y, fromX, fromY);
|
||||||
}
|
}
|
||||||
state++;
|
state++;
|
||||||
}
|
}
|
||||||
|
@ -287,7 +287,7 @@ float Detector::sizeOfBlackWhiteBlackRun(int fromX, int fromY, int toX, int toY)
|
||||||
// is "white" so this last point at (toX+xStep,toY) is the right ending. This is really a
|
// 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.
|
// small approximation; (toX+xStep,toY+yStep) might be really correct. Ignore this.
|
||||||
if (state == 2) {
|
if (state == 2) {
|
||||||
return math_utils::distance(toX + xstep, toY, fromX, fromY);
|
return MathUtils::distance(toX + xstep, toY, fromX, fromY);
|
||||||
}
|
}
|
||||||
// else we didn't find even black-white-black; no estimate is really possible
|
// else we didn't find even black-white-black; no estimate is really possible
|
||||||
return nan();
|
return nan();
|
||||||
|
|
Loading…
Reference in a new issue