Index: xfa/src/fxbarcode/datamatrix/BC_DataMatrixDetector.cpp |
diff --git a/xfa/src/fxbarcode/datamatrix/BC_DataMatrixDetector.cpp b/xfa/src/fxbarcode/datamatrix/BC_DataMatrixDetector.cpp |
index 27c29afe77c75db81915f47851618405792d651e..9a769b05fec9939ee1dc84c73c454a44d5b5f06c 100644 |
--- a/xfa/src/fxbarcode/datamatrix/BC_DataMatrixDetector.cpp |
+++ b/xfa/src/fxbarcode/datamatrix/BC_DataMatrixDetector.cpp |
@@ -1,406 +1,406 @@ |
-// Copyright 2014 PDFium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com |
-// Original code is licensed as follows: |
-/* |
- * Copyright 2008 ZXing authors |
- * |
- * 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 <algorithm> |
- |
-#include "xfa/src/fxbarcode/barcode.h" |
-#include "xfa/src/fxbarcode/BC_ResultPoint.h" |
-#include "xfa/src/fxbarcode/common/BC_WhiteRectangleDetector.h" |
-#include "xfa/src/fxbarcode/common/BC_CommonBitMatrix.h" |
-#include "xfa/src/fxbarcode/qrcode/BC_QRFinderPatternFinder.h" |
-#include "xfa/src/fxbarcode/qrcode/BC_QRDetectorResult.h" |
-#include "xfa/src/fxbarcode/qrcode/BC_QRGridSampler.h" |
-#include "BC_DataMatrixDetector.h" |
-const int32_t CBC_DataMatrixDetector::INTEGERS[5] = {0, 1, 2, 3, 4}; |
-CBC_DataMatrixDetector::CBC_DataMatrixDetector(CBC_CommonBitMatrix* image) |
- : m_image(image), m_rectangleDetector(NULL) {} |
-void CBC_DataMatrixDetector::Init(int32_t& e) { |
- m_rectangleDetector = new CBC_WhiteRectangleDetector(m_image); |
- m_rectangleDetector->Init(e); |
- BC_EXCEPTION_CHECK_ReturnVoid(e); |
-} |
-CBC_DataMatrixDetector::~CBC_DataMatrixDetector() { |
- if (m_rectangleDetector != NULL) { |
- delete m_rectangleDetector; |
- } |
- m_rectangleDetector = NULL; |
-} |
-inline FX_BOOL ResultPointsAndTransitionsComparator(void* a, void* b) { |
- return ((CBC_ResultPointsAndTransitions*)b)->GetTransitions() > |
- ((CBC_ResultPointsAndTransitions*)a)->GetTransitions(); |
-} |
-CBC_QRDetectorResult* CBC_DataMatrixDetector::Detect(int32_t& e) { |
- CFX_PtrArray* cornerPoints = m_rectangleDetector->Detect(e); |
- BC_EXCEPTION_CHECK_ReturnValue(e, NULL); |
- CBC_ResultPoint* pointA = (CBC_ResultPoint*)(*cornerPoints)[0]; |
- CBC_ResultPoint* pointB = (CBC_ResultPoint*)(*cornerPoints)[1]; |
- CBC_ResultPoint* pointC = (CBC_ResultPoint*)(*cornerPoints)[2]; |
- CBC_ResultPoint* pointD = (CBC_ResultPoint*)(*cornerPoints)[3]; |
- delete cornerPoints; |
- cornerPoints = NULL; |
- CFX_PtrArray transitions; |
- transitions.Add(TransitionsBetween(pointA, pointB)); |
- transitions.Add(TransitionsBetween(pointA, pointC)); |
- transitions.Add(TransitionsBetween(pointB, pointD)); |
- transitions.Add(TransitionsBetween(pointC, pointD)); |
- BC_FX_PtrArray_Sort(transitions, &ResultPointsAndTransitionsComparator); |
- delete ((CBC_ResultPointsAndTransitions*)transitions[2]); |
- delete ((CBC_ResultPointsAndTransitions*)transitions[3]); |
- CBC_ResultPointsAndTransitions* lSideOne = |
- (CBC_ResultPointsAndTransitions*)transitions[0]; |
- CBC_ResultPointsAndTransitions* lSideTwo = |
- (CBC_ResultPointsAndTransitions*)transitions[1]; |
- CFX_MapPtrTemplate<CBC_ResultPoint*, int32_t> pointCount; |
- Increment(pointCount, lSideOne->GetFrom()); |
- Increment(pointCount, lSideOne->GetTo()); |
- Increment(pointCount, lSideTwo->GetFrom()); |
- Increment(pointCount, lSideTwo->GetTo()); |
- delete ((CBC_ResultPointsAndTransitions*)transitions[1]); |
- delete ((CBC_ResultPointsAndTransitions*)transitions[0]); |
- transitions.RemoveAll(); |
- CBC_ResultPoint* maybeTopLeft = NULL; |
- CBC_ResultPoint* bottomLeft = NULL; |
- CBC_ResultPoint* maybeBottomRight = NULL; |
- FX_POSITION itBegin = pointCount.GetStartPosition(); |
- while (itBegin != NULL) { |
- CBC_ResultPoint* key = 0; |
- int32_t value = 0; |
- pointCount.GetNextAssoc(itBegin, key, value); |
- if (value == 2) { |
- bottomLeft = key; |
- } else { |
- if (maybeBottomRight == NULL) { |
- maybeBottomRight = key; |
- } else { |
- maybeTopLeft = key; |
- } |
- } |
- } |
- if (maybeTopLeft == NULL || bottomLeft == NULL || maybeBottomRight == NULL) { |
- delete pointA; |
- delete pointB; |
- delete pointC; |
- delete pointD; |
- e = BCExceptionNotFound; |
- return NULL; |
- } |
- CFX_PtrArray corners; |
- corners.SetSize(3); |
- corners[0] = maybeTopLeft; |
- corners[1] = bottomLeft; |
- corners[2] = maybeBottomRight; |
- OrderBestPatterns(&corners); |
- CBC_ResultPoint* bottomRight = (CBC_ResultPoint*)corners[0]; |
- bottomLeft = (CBC_ResultPoint*)corners[1]; |
- CBC_ResultPoint* topLeft = (CBC_ResultPoint*)corners[2]; |
- CBC_ResultPoint* topRight = NULL; |
- int32_t value; |
- if (!pointCount.Lookup(pointA, value)) { |
- topRight = pointA; |
- } else if (!pointCount.Lookup(pointB, value)) { |
- topRight = pointB; |
- } else if (!pointCount.Lookup(pointC, value)) { |
- topRight = pointC; |
- } else { |
- topRight = pointD; |
- } |
- int32_t dimensionTop = CBC_AutoPtr<CBC_ResultPointsAndTransitions>( |
- TransitionsBetween(topLeft, topRight)) |
- ->GetTransitions(); |
- int32_t dimensionRight = CBC_AutoPtr<CBC_ResultPointsAndTransitions>( |
- TransitionsBetween(bottomRight, topRight)) |
- ->GetTransitions(); |
- if ((dimensionTop & 0x01) == 1) { |
- dimensionTop++; |
- } |
- dimensionTop += 2; |
- if ((dimensionRight & 0x01) == 1) { |
- dimensionRight++; |
- } |
- dimensionRight += 2; |
- CBC_AutoPtr<CBC_CommonBitMatrix> bits(NULL); |
- CBC_AutoPtr<CBC_ResultPoint> correctedTopRight(NULL); |
- if (4 * dimensionTop >= 7 * dimensionRight || |
- 4 * dimensionRight >= 7 * dimensionTop) { |
- correctedTopRight = CBC_AutoPtr<CBC_ResultPoint>( |
- CorrectTopRightRectangular(bottomLeft, bottomRight, topLeft, topRight, |
- dimensionTop, dimensionRight)); |
- if (correctedTopRight.get() == NULL) { |
- correctedTopRight = CBC_AutoPtr<CBC_ResultPoint>(topRight); |
- } else { |
- delete topRight; |
- topRight = NULL; |
- } |
- dimensionTop = CBC_AutoPtr<CBC_ResultPointsAndTransitions>( |
- TransitionsBetween(topLeft, correctedTopRight.get())) |
- ->GetTransitions(); |
- dimensionRight = |
- CBC_AutoPtr<CBC_ResultPointsAndTransitions>( |
- TransitionsBetween(bottomRight, correctedTopRight.get())) |
- ->GetTransitions(); |
- if ((dimensionTop & 0x01) == 1) { |
- dimensionTop++; |
- } |
- if ((dimensionRight & 0x01) == 1) { |
- dimensionRight++; |
- } |
- bits = CBC_AutoPtr<CBC_CommonBitMatrix>( |
- SampleGrid(m_image, topLeft, bottomLeft, bottomRight, |
- correctedTopRight.get(), dimensionTop, dimensionRight, e)); |
- BC_EXCEPTION_CHECK_ReturnValue(e, NULL); |
- } else { |
- int32_t dimension = std::min(dimensionRight, dimensionTop); |
- correctedTopRight = CBC_AutoPtr<CBC_ResultPoint>( |
- CorrectTopRight(bottomLeft, bottomRight, topLeft, topRight, dimension)); |
- if (correctedTopRight.get() == NULL) { |
- correctedTopRight = CBC_AutoPtr<CBC_ResultPoint>(topRight); |
- } else { |
- delete topRight; |
- topRight = NULL; |
- } |
- int32_t dimensionCorrected = |
- std::max(CBC_AutoPtr<CBC_ResultPointsAndTransitions>( |
- TransitionsBetween(topLeft, correctedTopRight.get())) |
- ->GetTransitions(), |
- CBC_AutoPtr<CBC_ResultPointsAndTransitions>( |
- TransitionsBetween(bottomRight, correctedTopRight.get())) |
- ->GetTransitions()); |
- dimensionCorrected++; |
- if ((dimensionCorrected & 0x01) == 1) { |
- dimensionCorrected++; |
- } |
- bits = CBC_AutoPtr<CBC_CommonBitMatrix>(SampleGrid( |
- m_image, topLeft, bottomLeft, bottomRight, correctedTopRight.get(), |
- dimensionCorrected, dimensionCorrected, e)); |
- BC_EXCEPTION_CHECK_ReturnValue(e, NULL); |
- } |
- CFX_PtrArray* result = new CFX_PtrArray; |
- result->SetSize(4); |
- result->Add(topLeft); |
- result->Add(bottomLeft); |
- result->Add(bottomRight); |
- result->Add(correctedTopRight.release()); |
- return new CBC_QRDetectorResult(bits.release(), result); |
-} |
-CBC_ResultPoint* CBC_DataMatrixDetector::CorrectTopRightRectangular( |
- CBC_ResultPoint* bottomLeft, |
- CBC_ResultPoint* bottomRight, |
- CBC_ResultPoint* topLeft, |
- CBC_ResultPoint* topRight, |
- int32_t dimensionTop, |
- int32_t dimensionRight) { |
- FX_FLOAT corr = Distance(bottomLeft, bottomRight) / (FX_FLOAT)dimensionTop; |
- int32_t norm = Distance(topLeft, topRight); |
- FX_FLOAT cos = (topRight->GetX() - topLeft->GetX()) / norm; |
- FX_FLOAT sin = (topRight->GetY() - topLeft->GetY()) / norm; |
- CBC_AutoPtr<CBC_ResultPoint> c1(new CBC_ResultPoint( |
- topRight->GetX() + corr * cos, topRight->GetY() + corr * sin)); |
- corr = Distance(bottomLeft, topLeft) / (FX_FLOAT)dimensionRight; |
- norm = Distance(bottomRight, topRight); |
- cos = (topRight->GetX() - bottomRight->GetX()) / norm; |
- sin = (topRight->GetY() - bottomRight->GetY()) / norm; |
- CBC_AutoPtr<CBC_ResultPoint> c2(new CBC_ResultPoint( |
- topRight->GetX() + corr * cos, topRight->GetY() + corr * sin)); |
- if (!IsValid(c1.get())) { |
- if (IsValid(c2.get())) { |
- return c2.release(); |
- } |
- return NULL; |
- } else if (!IsValid(c2.get())) { |
- return c1.release(); |
- } |
- int32_t l1 = FXSYS_abs(dimensionTop - |
- CBC_AutoPtr<CBC_ResultPointsAndTransitions>( |
- TransitionsBetween(topLeft, c1.get())) |
- ->GetTransitions()) + |
- FXSYS_abs(dimensionRight - |
- CBC_AutoPtr<CBC_ResultPointsAndTransitions>( |
- TransitionsBetween(bottomRight, c1.get())) |
- ->GetTransitions()); |
- int32_t l2 = FXSYS_abs(dimensionTop - |
- CBC_AutoPtr<CBC_ResultPointsAndTransitions>( |
- TransitionsBetween(topLeft, c2.get())) |
- ->GetTransitions()) + |
- FXSYS_abs(dimensionRight - |
- CBC_AutoPtr<CBC_ResultPointsAndTransitions>( |
- TransitionsBetween(bottomRight, c2.get())) |
- ->GetTransitions()); |
- if (l1 <= l2) { |
- return c1.release(); |
- } |
- return c2.release(); |
-} |
-CBC_ResultPoint* CBC_DataMatrixDetector::CorrectTopRight( |
- CBC_ResultPoint* bottomLeft, |
- CBC_ResultPoint* bottomRight, |
- CBC_ResultPoint* topLeft, |
- CBC_ResultPoint* topRight, |
- int32_t dimension) { |
- FX_FLOAT corr = Distance(bottomLeft, bottomRight) / (FX_FLOAT)dimension; |
- int32_t norm = Distance(topLeft, topRight); |
- FX_FLOAT cos = (topRight->GetX() - topLeft->GetX()) / norm; |
- FX_FLOAT sin = (topRight->GetY() - topLeft->GetY()) / norm; |
- CBC_AutoPtr<CBC_ResultPoint> c1(new CBC_ResultPoint( |
- topRight->GetX() + corr * cos, topRight->GetY() + corr * sin)); |
- corr = Distance(bottomLeft, bottomRight) / (FX_FLOAT)dimension; |
- norm = Distance(bottomRight, topRight); |
- cos = (topRight->GetX() - bottomRight->GetX()) / norm; |
- sin = (topRight->GetY() - bottomRight->GetY()) / norm; |
- CBC_AutoPtr<CBC_ResultPoint> c2(new CBC_ResultPoint( |
- topRight->GetX() + corr * cos, topRight->GetY() + corr * sin)); |
- if (!IsValid(c1.get())) { |
- if (IsValid(c2.get())) { |
- return c2.release(); |
- } |
- return NULL; |
- } else if (!IsValid(c2.get())) { |
- return c1.release(); |
- } |
- int32_t l1 = FXSYS_abs(CBC_AutoPtr<CBC_ResultPointsAndTransitions>( |
- TransitionsBetween(topLeft, c1.get())) |
- ->GetTransitions() - |
- CBC_AutoPtr<CBC_ResultPointsAndTransitions>( |
- TransitionsBetween(bottomRight, c1.get())) |
- ->GetTransitions()); |
- int32_t l2 = FXSYS_abs(CBC_AutoPtr<CBC_ResultPointsAndTransitions>( |
- TransitionsBetween(topLeft, c2.get())) |
- ->GetTransitions() - |
- CBC_AutoPtr<CBC_ResultPointsAndTransitions>( |
- TransitionsBetween(bottomRight, c2.get())) |
- ->GetTransitions()); |
- return l1 <= l2 ? c1.release() : c2.release(); |
-} |
-FX_BOOL CBC_DataMatrixDetector::IsValid(CBC_ResultPoint* p) { |
- return p->GetX() >= 0 && p->GetX() < m_image->GetWidth() && p->GetY() > 0 && |
- p->GetY() < m_image->GetHeight(); |
-} |
-int32_t CBC_DataMatrixDetector::Round(FX_FLOAT d) { |
- return (int32_t)(d + 0.5f); |
-} |
-int32_t CBC_DataMatrixDetector::Distance(CBC_ResultPoint* a, |
- CBC_ResultPoint* b) { |
- return Round( |
- (FX_FLOAT)sqrt((a->GetX() - b->GetX()) * (a->GetX() - b->GetX()) + |
- (a->GetY() - b->GetY()) * (a->GetY() - b->GetY()))); |
-} |
-void CBC_DataMatrixDetector::Increment( |
- CFX_MapPtrTemplate<CBC_ResultPoint*, int32_t>& table, |
- CBC_ResultPoint* key) { |
- int32_t value; |
- if (table.Lookup(key, value)) { |
- table.SetAt(key, INTEGERS[value + 1]); |
- } else { |
- table.SetAt(key, INTEGERS[1]); |
- } |
-} |
-CBC_CommonBitMatrix* CBC_DataMatrixDetector::SampleGrid( |
- CBC_CommonBitMatrix* image, |
- CBC_ResultPoint* topLeft, |
- CBC_ResultPoint* bottomLeft, |
- CBC_ResultPoint* bottomRight, |
- CBC_ResultPoint* topRight, |
- int32_t dimensionX, |
- int32_t dimensionY, |
- int32_t& e) { |
- CBC_QRGridSampler& sampler = CBC_QRGridSampler::GetInstance(); |
- CBC_CommonBitMatrix* cbm = sampler.SampleGrid( |
- image, dimensionX, dimensionY, 0.5f, 0.5f, dimensionX - 0.5f, 0.5f, |
- dimensionX - 0.5f, dimensionY - 0.5f, 0.5f, dimensionY - 0.5f, |
- topLeft->GetX(), topLeft->GetY(), topRight->GetX(), topRight->GetY(), |
- bottomRight->GetX(), bottomRight->GetY(), bottomLeft->GetX(), |
- bottomLeft->GetY(), e); |
- BC_EXCEPTION_CHECK_ReturnValue(e, NULL); |
- return cbm; |
-} |
-CBC_ResultPointsAndTransitions* CBC_DataMatrixDetector::TransitionsBetween( |
- CBC_ResultPoint* from, |
- CBC_ResultPoint* to) { |
- int32_t fromX = (int32_t)from->GetX(); |
- int32_t fromY = (int32_t)from->GetY(); |
- int32_t toX = (int32_t)to->GetX(); |
- int32_t toY = (int32_t)to->GetY(); |
- FX_BOOL steep = FXSYS_abs(toY - fromY) > FXSYS_abs(toX - fromX); |
- if (steep) { |
- int32_t temp = fromX; |
- fromX = fromY; |
- fromY = temp; |
- temp = toX; |
- toX = toY; |
- toY = temp; |
- } |
- int32_t dx = FXSYS_abs(toX - fromX); |
- int32_t dy = FXSYS_abs(toY - fromY); |
- int32_t error = -dx >> 1; |
- int32_t ystep = fromY < toY ? 1 : -1; |
- int32_t xstep = fromX < toX ? 1 : -1; |
- int32_t transitions = 0; |
- FX_BOOL inBlack = m_image->Get(steep ? fromY : fromX, steep ? fromX : fromY); |
- for (int32_t x = fromX, y = fromY; x != toX; x += xstep) { |
- FX_BOOL isBlack = m_image->Get(steep ? y : x, steep ? x : y); |
- if (isBlack != inBlack) { |
- transitions++; |
- inBlack = isBlack; |
- } |
- error += dy; |
- if (error > 0) { |
- if (y == toY) { |
- break; |
- } |
- y += ystep; |
- error -= dx; |
- } |
- } |
- return new CBC_ResultPointsAndTransitions(from, to, transitions); |
-} |
-void CBC_DataMatrixDetector::OrderBestPatterns(CFX_PtrArray* patterns) { |
- FX_FLOAT abDistance = (FX_FLOAT)Distance((CBC_ResultPoint*)(*patterns)[0], |
- (CBC_ResultPoint*)(*patterns)[1]); |
- FX_FLOAT bcDistance = (FX_FLOAT)Distance((CBC_ResultPoint*)(*patterns)[1], |
- (CBC_ResultPoint*)(*patterns)[2]); |
- FX_FLOAT acDistance = (FX_FLOAT)Distance((CBC_ResultPoint*)(*patterns)[0], |
- (CBC_ResultPoint*)(*patterns)[2]); |
- CBC_ResultPoint *topLeft, *topRight, *bottomLeft; |
- if (bcDistance >= abDistance && bcDistance >= acDistance) { |
- topLeft = (CBC_ResultPoint*)(*patterns)[0]; |
- topRight = (CBC_ResultPoint*)(*patterns)[1]; |
- bottomLeft = (CBC_ResultPoint*)(*patterns)[2]; |
- } else if (acDistance >= bcDistance && acDistance >= abDistance) { |
- topLeft = (CBC_ResultPoint*)(*patterns)[1]; |
- topRight = (CBC_ResultPoint*)(*patterns)[0]; |
- bottomLeft = (CBC_ResultPoint*)(*patterns)[2]; |
- } else { |
- topLeft = (CBC_ResultPoint*)(*patterns)[2]; |
- topRight = (CBC_ResultPoint*)(*patterns)[0]; |
- bottomLeft = (CBC_ResultPoint*)(*patterns)[1]; |
- } |
- if ((bottomLeft->GetY() - topLeft->GetY()) * |
- (topRight->GetX() - topLeft->GetX()) < |
- (bottomLeft->GetX() - topLeft->GetX()) * |
- (topRight->GetY() - topLeft->GetY())) { |
- CBC_ResultPoint* temp = topRight; |
- topRight = bottomLeft; |
- bottomLeft = temp; |
- } |
- (*patterns)[0] = bottomLeft; |
- (*patterns)[1] = topLeft; |
- (*patterns)[2] = topRight; |
-} |
+// Copyright 2014 PDFium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com |
+// Original code is licensed as follows: |
+/* |
+ * Copyright 2008 ZXing authors |
+ * |
+ * 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 <algorithm> |
+ |
+#include "xfa/src/fxbarcode/barcode.h" |
+#include "xfa/src/fxbarcode/BC_ResultPoint.h" |
+#include "xfa/src/fxbarcode/common/BC_WhiteRectangleDetector.h" |
+#include "xfa/src/fxbarcode/common/BC_CommonBitMatrix.h" |
+#include "xfa/src/fxbarcode/qrcode/BC_QRFinderPatternFinder.h" |
+#include "xfa/src/fxbarcode/qrcode/BC_QRDetectorResult.h" |
+#include "xfa/src/fxbarcode/qrcode/BC_QRGridSampler.h" |
+#include "BC_DataMatrixDetector.h" |
+const int32_t CBC_DataMatrixDetector::INTEGERS[5] = {0, 1, 2, 3, 4}; |
+CBC_DataMatrixDetector::CBC_DataMatrixDetector(CBC_CommonBitMatrix* image) |
+ : m_image(image), m_rectangleDetector(NULL) {} |
+void CBC_DataMatrixDetector::Init(int32_t& e) { |
+ m_rectangleDetector = new CBC_WhiteRectangleDetector(m_image); |
+ m_rectangleDetector->Init(e); |
+ BC_EXCEPTION_CHECK_ReturnVoid(e); |
+} |
+CBC_DataMatrixDetector::~CBC_DataMatrixDetector() { |
+ if (m_rectangleDetector != NULL) { |
+ delete m_rectangleDetector; |
+ } |
+ m_rectangleDetector = NULL; |
+} |
+inline FX_BOOL ResultPointsAndTransitionsComparator(void* a, void* b) { |
+ return ((CBC_ResultPointsAndTransitions*)b)->GetTransitions() > |
+ ((CBC_ResultPointsAndTransitions*)a)->GetTransitions(); |
+} |
+CBC_QRDetectorResult* CBC_DataMatrixDetector::Detect(int32_t& e) { |
+ CFX_PtrArray* cornerPoints = m_rectangleDetector->Detect(e); |
+ BC_EXCEPTION_CHECK_ReturnValue(e, NULL); |
+ CBC_ResultPoint* pointA = (CBC_ResultPoint*)(*cornerPoints)[0]; |
+ CBC_ResultPoint* pointB = (CBC_ResultPoint*)(*cornerPoints)[1]; |
+ CBC_ResultPoint* pointC = (CBC_ResultPoint*)(*cornerPoints)[2]; |
+ CBC_ResultPoint* pointD = (CBC_ResultPoint*)(*cornerPoints)[3]; |
+ delete cornerPoints; |
+ cornerPoints = NULL; |
+ CFX_PtrArray transitions; |
+ transitions.Add(TransitionsBetween(pointA, pointB)); |
+ transitions.Add(TransitionsBetween(pointA, pointC)); |
+ transitions.Add(TransitionsBetween(pointB, pointD)); |
+ transitions.Add(TransitionsBetween(pointC, pointD)); |
+ BC_FX_PtrArray_Sort(transitions, &ResultPointsAndTransitionsComparator); |
+ delete ((CBC_ResultPointsAndTransitions*)transitions[2]); |
+ delete ((CBC_ResultPointsAndTransitions*)transitions[3]); |
+ CBC_ResultPointsAndTransitions* lSideOne = |
+ (CBC_ResultPointsAndTransitions*)transitions[0]; |
+ CBC_ResultPointsAndTransitions* lSideTwo = |
+ (CBC_ResultPointsAndTransitions*)transitions[1]; |
+ CFX_MapPtrTemplate<CBC_ResultPoint*, int32_t> pointCount; |
+ Increment(pointCount, lSideOne->GetFrom()); |
+ Increment(pointCount, lSideOne->GetTo()); |
+ Increment(pointCount, lSideTwo->GetFrom()); |
+ Increment(pointCount, lSideTwo->GetTo()); |
+ delete ((CBC_ResultPointsAndTransitions*)transitions[1]); |
+ delete ((CBC_ResultPointsAndTransitions*)transitions[0]); |
+ transitions.RemoveAll(); |
+ CBC_ResultPoint* maybeTopLeft = NULL; |
+ CBC_ResultPoint* bottomLeft = NULL; |
+ CBC_ResultPoint* maybeBottomRight = NULL; |
+ FX_POSITION itBegin = pointCount.GetStartPosition(); |
+ while (itBegin != NULL) { |
+ CBC_ResultPoint* key = 0; |
+ int32_t value = 0; |
+ pointCount.GetNextAssoc(itBegin, key, value); |
+ if (value == 2) { |
+ bottomLeft = key; |
+ } else { |
+ if (maybeBottomRight == NULL) { |
+ maybeBottomRight = key; |
+ } else { |
+ maybeTopLeft = key; |
+ } |
+ } |
+ } |
+ if (maybeTopLeft == NULL || bottomLeft == NULL || maybeBottomRight == NULL) { |
+ delete pointA; |
+ delete pointB; |
+ delete pointC; |
+ delete pointD; |
+ e = BCExceptionNotFound; |
+ return NULL; |
+ } |
+ CFX_PtrArray corners; |
+ corners.SetSize(3); |
+ corners[0] = maybeTopLeft; |
+ corners[1] = bottomLeft; |
+ corners[2] = maybeBottomRight; |
+ OrderBestPatterns(&corners); |
+ CBC_ResultPoint* bottomRight = (CBC_ResultPoint*)corners[0]; |
+ bottomLeft = (CBC_ResultPoint*)corners[1]; |
+ CBC_ResultPoint* topLeft = (CBC_ResultPoint*)corners[2]; |
+ CBC_ResultPoint* topRight = NULL; |
+ int32_t value; |
+ if (!pointCount.Lookup(pointA, value)) { |
+ topRight = pointA; |
+ } else if (!pointCount.Lookup(pointB, value)) { |
+ topRight = pointB; |
+ } else if (!pointCount.Lookup(pointC, value)) { |
+ topRight = pointC; |
+ } else { |
+ topRight = pointD; |
+ } |
+ int32_t dimensionTop = CBC_AutoPtr<CBC_ResultPointsAndTransitions>( |
+ TransitionsBetween(topLeft, topRight)) |
+ ->GetTransitions(); |
+ int32_t dimensionRight = CBC_AutoPtr<CBC_ResultPointsAndTransitions>( |
+ TransitionsBetween(bottomRight, topRight)) |
+ ->GetTransitions(); |
+ if ((dimensionTop & 0x01) == 1) { |
+ dimensionTop++; |
+ } |
+ dimensionTop += 2; |
+ if ((dimensionRight & 0x01) == 1) { |
+ dimensionRight++; |
+ } |
+ dimensionRight += 2; |
+ CBC_AutoPtr<CBC_CommonBitMatrix> bits(NULL); |
+ CBC_AutoPtr<CBC_ResultPoint> correctedTopRight(NULL); |
+ if (4 * dimensionTop >= 7 * dimensionRight || |
+ 4 * dimensionRight >= 7 * dimensionTop) { |
+ correctedTopRight = CBC_AutoPtr<CBC_ResultPoint>( |
+ CorrectTopRightRectangular(bottomLeft, bottomRight, topLeft, topRight, |
+ dimensionTop, dimensionRight)); |
+ if (correctedTopRight.get() == NULL) { |
+ correctedTopRight = CBC_AutoPtr<CBC_ResultPoint>(topRight); |
+ } else { |
+ delete topRight; |
+ topRight = NULL; |
+ } |
+ dimensionTop = CBC_AutoPtr<CBC_ResultPointsAndTransitions>( |
+ TransitionsBetween(topLeft, correctedTopRight.get())) |
+ ->GetTransitions(); |
+ dimensionRight = |
+ CBC_AutoPtr<CBC_ResultPointsAndTransitions>( |
+ TransitionsBetween(bottomRight, correctedTopRight.get())) |
+ ->GetTransitions(); |
+ if ((dimensionTop & 0x01) == 1) { |
+ dimensionTop++; |
+ } |
+ if ((dimensionRight & 0x01) == 1) { |
+ dimensionRight++; |
+ } |
+ bits = CBC_AutoPtr<CBC_CommonBitMatrix>( |
+ SampleGrid(m_image, topLeft, bottomLeft, bottomRight, |
+ correctedTopRight.get(), dimensionTop, dimensionRight, e)); |
+ BC_EXCEPTION_CHECK_ReturnValue(e, NULL); |
+ } else { |
+ int32_t dimension = std::min(dimensionRight, dimensionTop); |
+ correctedTopRight = CBC_AutoPtr<CBC_ResultPoint>( |
+ CorrectTopRight(bottomLeft, bottomRight, topLeft, topRight, dimension)); |
+ if (correctedTopRight.get() == NULL) { |
+ correctedTopRight = CBC_AutoPtr<CBC_ResultPoint>(topRight); |
+ } else { |
+ delete topRight; |
+ topRight = NULL; |
+ } |
+ int32_t dimensionCorrected = |
+ std::max(CBC_AutoPtr<CBC_ResultPointsAndTransitions>( |
+ TransitionsBetween(topLeft, correctedTopRight.get())) |
+ ->GetTransitions(), |
+ CBC_AutoPtr<CBC_ResultPointsAndTransitions>( |
+ TransitionsBetween(bottomRight, correctedTopRight.get())) |
+ ->GetTransitions()); |
+ dimensionCorrected++; |
+ if ((dimensionCorrected & 0x01) == 1) { |
+ dimensionCorrected++; |
+ } |
+ bits = CBC_AutoPtr<CBC_CommonBitMatrix>(SampleGrid( |
+ m_image, topLeft, bottomLeft, bottomRight, correctedTopRight.get(), |
+ dimensionCorrected, dimensionCorrected, e)); |
+ BC_EXCEPTION_CHECK_ReturnValue(e, NULL); |
+ } |
+ CFX_PtrArray* result = new CFX_PtrArray; |
+ result->SetSize(4); |
+ result->Add(topLeft); |
+ result->Add(bottomLeft); |
+ result->Add(bottomRight); |
+ result->Add(correctedTopRight.release()); |
+ return new CBC_QRDetectorResult(bits.release(), result); |
+} |
+CBC_ResultPoint* CBC_DataMatrixDetector::CorrectTopRightRectangular( |
+ CBC_ResultPoint* bottomLeft, |
+ CBC_ResultPoint* bottomRight, |
+ CBC_ResultPoint* topLeft, |
+ CBC_ResultPoint* topRight, |
+ int32_t dimensionTop, |
+ int32_t dimensionRight) { |
+ FX_FLOAT corr = Distance(bottomLeft, bottomRight) / (FX_FLOAT)dimensionTop; |
+ int32_t norm = Distance(topLeft, topRight); |
+ FX_FLOAT cos = (topRight->GetX() - topLeft->GetX()) / norm; |
+ FX_FLOAT sin = (topRight->GetY() - topLeft->GetY()) / norm; |
+ CBC_AutoPtr<CBC_ResultPoint> c1(new CBC_ResultPoint( |
+ topRight->GetX() + corr * cos, topRight->GetY() + corr * sin)); |
+ corr = Distance(bottomLeft, topLeft) / (FX_FLOAT)dimensionRight; |
+ norm = Distance(bottomRight, topRight); |
+ cos = (topRight->GetX() - bottomRight->GetX()) / norm; |
+ sin = (topRight->GetY() - bottomRight->GetY()) / norm; |
+ CBC_AutoPtr<CBC_ResultPoint> c2(new CBC_ResultPoint( |
+ topRight->GetX() + corr * cos, topRight->GetY() + corr * sin)); |
+ if (!IsValid(c1.get())) { |
+ if (IsValid(c2.get())) { |
+ return c2.release(); |
+ } |
+ return NULL; |
+ } else if (!IsValid(c2.get())) { |
+ return c1.release(); |
+ } |
+ int32_t l1 = FXSYS_abs(dimensionTop - |
+ CBC_AutoPtr<CBC_ResultPointsAndTransitions>( |
+ TransitionsBetween(topLeft, c1.get())) |
+ ->GetTransitions()) + |
+ FXSYS_abs(dimensionRight - |
+ CBC_AutoPtr<CBC_ResultPointsAndTransitions>( |
+ TransitionsBetween(bottomRight, c1.get())) |
+ ->GetTransitions()); |
+ int32_t l2 = FXSYS_abs(dimensionTop - |
+ CBC_AutoPtr<CBC_ResultPointsAndTransitions>( |
+ TransitionsBetween(topLeft, c2.get())) |
+ ->GetTransitions()) + |
+ FXSYS_abs(dimensionRight - |
+ CBC_AutoPtr<CBC_ResultPointsAndTransitions>( |
+ TransitionsBetween(bottomRight, c2.get())) |
+ ->GetTransitions()); |
+ if (l1 <= l2) { |
+ return c1.release(); |
+ } |
+ return c2.release(); |
+} |
+CBC_ResultPoint* CBC_DataMatrixDetector::CorrectTopRight( |
+ CBC_ResultPoint* bottomLeft, |
+ CBC_ResultPoint* bottomRight, |
+ CBC_ResultPoint* topLeft, |
+ CBC_ResultPoint* topRight, |
+ int32_t dimension) { |
+ FX_FLOAT corr = Distance(bottomLeft, bottomRight) / (FX_FLOAT)dimension; |
+ int32_t norm = Distance(topLeft, topRight); |
+ FX_FLOAT cos = (topRight->GetX() - topLeft->GetX()) / norm; |
+ FX_FLOAT sin = (topRight->GetY() - topLeft->GetY()) / norm; |
+ CBC_AutoPtr<CBC_ResultPoint> c1(new CBC_ResultPoint( |
+ topRight->GetX() + corr * cos, topRight->GetY() + corr * sin)); |
+ corr = Distance(bottomLeft, bottomRight) / (FX_FLOAT)dimension; |
+ norm = Distance(bottomRight, topRight); |
+ cos = (topRight->GetX() - bottomRight->GetX()) / norm; |
+ sin = (topRight->GetY() - bottomRight->GetY()) / norm; |
+ CBC_AutoPtr<CBC_ResultPoint> c2(new CBC_ResultPoint( |
+ topRight->GetX() + corr * cos, topRight->GetY() + corr * sin)); |
+ if (!IsValid(c1.get())) { |
+ if (IsValid(c2.get())) { |
+ return c2.release(); |
+ } |
+ return NULL; |
+ } else if (!IsValid(c2.get())) { |
+ return c1.release(); |
+ } |
+ int32_t l1 = FXSYS_abs(CBC_AutoPtr<CBC_ResultPointsAndTransitions>( |
+ TransitionsBetween(topLeft, c1.get())) |
+ ->GetTransitions() - |
+ CBC_AutoPtr<CBC_ResultPointsAndTransitions>( |
+ TransitionsBetween(bottomRight, c1.get())) |
+ ->GetTransitions()); |
+ int32_t l2 = FXSYS_abs(CBC_AutoPtr<CBC_ResultPointsAndTransitions>( |
+ TransitionsBetween(topLeft, c2.get())) |
+ ->GetTransitions() - |
+ CBC_AutoPtr<CBC_ResultPointsAndTransitions>( |
+ TransitionsBetween(bottomRight, c2.get())) |
+ ->GetTransitions()); |
+ return l1 <= l2 ? c1.release() : c2.release(); |
+} |
+FX_BOOL CBC_DataMatrixDetector::IsValid(CBC_ResultPoint* p) { |
+ return p->GetX() >= 0 && p->GetX() < m_image->GetWidth() && p->GetY() > 0 && |
+ p->GetY() < m_image->GetHeight(); |
+} |
+int32_t CBC_DataMatrixDetector::Round(FX_FLOAT d) { |
+ return (int32_t)(d + 0.5f); |
+} |
+int32_t CBC_DataMatrixDetector::Distance(CBC_ResultPoint* a, |
+ CBC_ResultPoint* b) { |
+ return Round( |
+ (FX_FLOAT)sqrt((a->GetX() - b->GetX()) * (a->GetX() - b->GetX()) + |
+ (a->GetY() - b->GetY()) * (a->GetY() - b->GetY()))); |
+} |
+void CBC_DataMatrixDetector::Increment( |
+ CFX_MapPtrTemplate<CBC_ResultPoint*, int32_t>& table, |
+ CBC_ResultPoint* key) { |
+ int32_t value; |
+ if (table.Lookup(key, value)) { |
+ table.SetAt(key, INTEGERS[value + 1]); |
+ } else { |
+ table.SetAt(key, INTEGERS[1]); |
+ } |
+} |
+CBC_CommonBitMatrix* CBC_DataMatrixDetector::SampleGrid( |
+ CBC_CommonBitMatrix* image, |
+ CBC_ResultPoint* topLeft, |
+ CBC_ResultPoint* bottomLeft, |
+ CBC_ResultPoint* bottomRight, |
+ CBC_ResultPoint* topRight, |
+ int32_t dimensionX, |
+ int32_t dimensionY, |
+ int32_t& e) { |
+ CBC_QRGridSampler& sampler = CBC_QRGridSampler::GetInstance(); |
+ CBC_CommonBitMatrix* cbm = sampler.SampleGrid( |
+ image, dimensionX, dimensionY, 0.5f, 0.5f, dimensionX - 0.5f, 0.5f, |
+ dimensionX - 0.5f, dimensionY - 0.5f, 0.5f, dimensionY - 0.5f, |
+ topLeft->GetX(), topLeft->GetY(), topRight->GetX(), topRight->GetY(), |
+ bottomRight->GetX(), bottomRight->GetY(), bottomLeft->GetX(), |
+ bottomLeft->GetY(), e); |
+ BC_EXCEPTION_CHECK_ReturnValue(e, NULL); |
+ return cbm; |
+} |
+CBC_ResultPointsAndTransitions* CBC_DataMatrixDetector::TransitionsBetween( |
+ CBC_ResultPoint* from, |
+ CBC_ResultPoint* to) { |
+ int32_t fromX = (int32_t)from->GetX(); |
+ int32_t fromY = (int32_t)from->GetY(); |
+ int32_t toX = (int32_t)to->GetX(); |
+ int32_t toY = (int32_t)to->GetY(); |
+ FX_BOOL steep = FXSYS_abs(toY - fromY) > FXSYS_abs(toX - fromX); |
+ if (steep) { |
+ int32_t temp = fromX; |
+ fromX = fromY; |
+ fromY = temp; |
+ temp = toX; |
+ toX = toY; |
+ toY = temp; |
+ } |
+ int32_t dx = FXSYS_abs(toX - fromX); |
+ int32_t dy = FXSYS_abs(toY - fromY); |
+ int32_t error = -dx >> 1; |
+ int32_t ystep = fromY < toY ? 1 : -1; |
+ int32_t xstep = fromX < toX ? 1 : -1; |
+ int32_t transitions = 0; |
+ FX_BOOL inBlack = m_image->Get(steep ? fromY : fromX, steep ? fromX : fromY); |
+ for (int32_t x = fromX, y = fromY; x != toX; x += xstep) { |
+ FX_BOOL isBlack = m_image->Get(steep ? y : x, steep ? x : y); |
+ if (isBlack != inBlack) { |
+ transitions++; |
+ inBlack = isBlack; |
+ } |
+ error += dy; |
+ if (error > 0) { |
+ if (y == toY) { |
+ break; |
+ } |
+ y += ystep; |
+ error -= dx; |
+ } |
+ } |
+ return new CBC_ResultPointsAndTransitions(from, to, transitions); |
+} |
+void CBC_DataMatrixDetector::OrderBestPatterns(CFX_PtrArray* patterns) { |
+ FX_FLOAT abDistance = (FX_FLOAT)Distance((CBC_ResultPoint*)(*patterns)[0], |
+ (CBC_ResultPoint*)(*patterns)[1]); |
+ FX_FLOAT bcDistance = (FX_FLOAT)Distance((CBC_ResultPoint*)(*patterns)[1], |
+ (CBC_ResultPoint*)(*patterns)[2]); |
+ FX_FLOAT acDistance = (FX_FLOAT)Distance((CBC_ResultPoint*)(*patterns)[0], |
+ (CBC_ResultPoint*)(*patterns)[2]); |
+ CBC_ResultPoint *topLeft, *topRight, *bottomLeft; |
+ if (bcDistance >= abDistance && bcDistance >= acDistance) { |
+ topLeft = (CBC_ResultPoint*)(*patterns)[0]; |
+ topRight = (CBC_ResultPoint*)(*patterns)[1]; |
+ bottomLeft = (CBC_ResultPoint*)(*patterns)[2]; |
+ } else if (acDistance >= bcDistance && acDistance >= abDistance) { |
+ topLeft = (CBC_ResultPoint*)(*patterns)[1]; |
+ topRight = (CBC_ResultPoint*)(*patterns)[0]; |
+ bottomLeft = (CBC_ResultPoint*)(*patterns)[2]; |
+ } else { |
+ topLeft = (CBC_ResultPoint*)(*patterns)[2]; |
+ topRight = (CBC_ResultPoint*)(*patterns)[0]; |
+ bottomLeft = (CBC_ResultPoint*)(*patterns)[1]; |
+ } |
+ if ((bottomLeft->GetY() - topLeft->GetY()) * |
+ (topRight->GetX() - topLeft->GetX()) < |
+ (bottomLeft->GetX() - topLeft->GetX()) * |
+ (topRight->GetY() - topLeft->GetY())) { |
+ CBC_ResultPoint* temp = topRight; |
+ topRight = bottomLeft; |
+ bottomLeft = temp; |
+ } |
+ (*patterns)[0] = bottomLeft; |
+ (*patterns)[1] = topLeft; |
+ (*patterns)[2] = topRight; |
+} |