Index: xfa/src/fxbarcode/pdf417/BC_PDF417ScanningDecoder.cpp |
diff --git a/xfa/src/fxbarcode/pdf417/BC_PDF417ScanningDecoder.cpp b/xfa/src/fxbarcode/pdf417/BC_PDF417ScanningDecoder.cpp |
index 2d2ea8fa8de0a19eb7233abb9854910f69ca4d85..89b2d2865abb501aca9064ca2ad32d9f7c355bdc 100644 |
--- a/xfa/src/fxbarcode/pdf417/BC_PDF417ScanningDecoder.cpp |
+++ b/xfa/src/fxbarcode/pdf417/BC_PDF417ScanningDecoder.cpp |
@@ -1,750 +1,750 @@ |
-// 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 2013 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 "xfa/src/fxbarcode/barcode.h" |
-#include "xfa/src/fxbarcode/BC_DecoderResult.h" |
-#include "xfa/src/fxbarcode/BC_ResultPoint.h" |
-#include "xfa/src/fxbarcode/common/BC_CommonBitMatrix.h" |
-#include "BC_PDF417Codeword.h" |
-#include "BC_PDF417Common.h" |
-#include "BC_PDF417BarcodeValue.h" |
-#include "BC_PDF417BarcodeMetadata.h" |
-#include "BC_PDF417BoundingBox.h" |
-#include "BC_PDF417DetectionResultColumn.h" |
-#include "BC_PDF417DetectionResultRowIndicatorColumn.h" |
-#include "BC_PDF417DetectionResult.h" |
-#include "BC_PDF417DecodedBitStreamParser.h" |
-#include "BC_PDF417CodewordDecoder.h" |
-#include "BC_PDF417DecodedBitStreamParser.h" |
-#include "BC_PDF417ECModulusPoly.h" |
-#include "BC_PDF417ECModulusGF.h" |
-#include "BC_PDF417ECErrorCorrection.h" |
-#include "BC_PDF417DecodedBitStreamParser.h" |
-#include "BC_PDF417ScanningDecoder.h" |
-int32_t CBC_PDF417ScanningDecoder::CODEWORD_SKEW_SIZE = 2; |
-int32_t CBC_PDF417ScanningDecoder::MAX_ERRORS = 3; |
-int32_t CBC_PDF417ScanningDecoder::MAX_EC_CODEWORDS = 512; |
-CBC_PDF417ECErrorCorrection* CBC_PDF417ScanningDecoder::errorCorrection = NULL; |
-CBC_PDF417ScanningDecoder::CBC_PDF417ScanningDecoder() {} |
-CBC_PDF417ScanningDecoder::~CBC_PDF417ScanningDecoder() {} |
-void CBC_PDF417ScanningDecoder::Initialize() { |
- errorCorrection = new CBC_PDF417ECErrorCorrection; |
-} |
-void CBC_PDF417ScanningDecoder::Finalize() { |
- delete errorCorrection; |
-} |
-CBC_CommonDecoderResult* CBC_PDF417ScanningDecoder::decode( |
- CBC_CommonBitMatrix* image, |
- CBC_ResultPoint* imageTopLeft, |
- CBC_ResultPoint* imageBottomLeft, |
- CBC_ResultPoint* imageTopRight, |
- CBC_ResultPoint* imageBottomRight, |
- int32_t minCodewordWidth, |
- int32_t maxCodewordWidth, |
- int32_t& e) { |
- CBC_BoundingBox* boundingBox = new CBC_BoundingBox( |
- image, imageTopLeft, imageBottomLeft, imageTopRight, imageBottomRight, e); |
- BC_EXCEPTION_CHECK_ReturnValue(e, NULL); |
- CBC_DetectionResultRowIndicatorColumn* leftRowIndicatorColumn = NULL; |
- CBC_DetectionResultRowIndicatorColumn* rightRowIndicatorColumn = NULL; |
- CBC_DetectionResult* detectionResult = NULL; |
- for (int32_t i = 0; i < 2; i++) { |
- if (imageTopLeft != NULL) { |
- leftRowIndicatorColumn = |
- getRowIndicatorColumn(image, boundingBox, *imageTopLeft, TRUE, |
- minCodewordWidth, maxCodewordWidth); |
- } |
- if (imageTopRight != NULL) { |
- rightRowIndicatorColumn = |
- getRowIndicatorColumn(image, boundingBox, *imageTopRight, FALSE, |
- minCodewordWidth, maxCodewordWidth); |
- } |
- detectionResult = merge(leftRowIndicatorColumn, rightRowIndicatorColumn, e); |
- if (e != BCExceptionNO) { |
- e = BCExceptiontNotFoundInstance; |
- delete leftRowIndicatorColumn; |
- delete rightRowIndicatorColumn; |
- delete boundingBox; |
- return NULL; |
- } |
- if (i == 0 && (detectionResult->getBoundingBox()->getMinY() < |
- boundingBox->getMinY() || |
- detectionResult->getBoundingBox()->getMaxY() > |
- boundingBox->getMaxY())) { |
- delete boundingBox; |
- boundingBox = detectionResult->getBoundingBox(); |
- } else { |
- detectionResult->setBoundingBox(boundingBox); |
- break; |
- } |
- } |
- int32_t maxBarcodeColumn = detectionResult->getBarcodeColumnCount() + 1; |
- detectionResult->setDetectionResultColumn(0, leftRowIndicatorColumn); |
- detectionResult->setDetectionResultColumn(maxBarcodeColumn, |
- rightRowIndicatorColumn); |
- FX_BOOL leftToRight = leftRowIndicatorColumn != NULL; |
- for (int32_t barcodeColumnCount = 1; barcodeColumnCount <= maxBarcodeColumn; |
- barcodeColumnCount++) { |
- int32_t barcodeColumn = leftToRight ? barcodeColumnCount |
- : maxBarcodeColumn - barcodeColumnCount; |
- if (detectionResult->getDetectionResultColumn(barcodeColumn) != NULL) { |
- continue; |
- } |
- CBC_DetectionResultColumn* detectionResultColumn = NULL; |
- if (barcodeColumn == 0 || barcodeColumn == maxBarcodeColumn) { |
- detectionResultColumn = new CBC_DetectionResultRowIndicatorColumn( |
- boundingBox, barcodeColumn == 0); |
- } else { |
- detectionResultColumn = new CBC_DetectionResultColumn(boundingBox); |
- } |
- detectionResult->setDetectionResultColumn(barcodeColumn, |
- detectionResultColumn); |
- int32_t startColumn = -1; |
- int32_t previousStartColumn = startColumn; |
- for (int32_t imageRow = boundingBox->getMinY(); |
- imageRow <= boundingBox->getMaxY(); imageRow++) { |
- startColumn = |
- getStartColumn(detectionResult, barcodeColumn, imageRow, leftToRight); |
- if (startColumn < 0 || startColumn > boundingBox->getMaxX()) { |
- if (previousStartColumn == -1) { |
- continue; |
- } |
- startColumn = previousStartColumn; |
- } |
- CBC_Codeword* codeword = detectCodeword( |
- image, boundingBox->getMinX(), boundingBox->getMaxX(), leftToRight, |
- startColumn, imageRow, minCodewordWidth, maxCodewordWidth); |
- if (codeword != NULL) { |
- detectionResultColumn->setCodeword(imageRow, codeword); |
- previousStartColumn = startColumn; |
- minCodewordWidth = minCodewordWidth < codeword->getWidth() |
- ? minCodewordWidth |
- : codeword->getWidth(); |
- maxCodewordWidth = maxCodewordWidth > codeword->getWidth() |
- ? maxCodewordWidth |
- : codeword->getWidth(); |
- } |
- } |
- } |
- CBC_CommonDecoderResult* decoderresult = |
- createDecoderResult(detectionResult, e); |
- if (e != BCExceptionNO) { |
- delete detectionResult; |
- return NULL; |
- } |
- return decoderresult; |
-} |
-CFX_ByteString CBC_PDF417ScanningDecoder::toString( |
- CFX_PtrArray* barcodeMatrix) { |
- CFX_ByteString result; |
- for (int32_t row = 0; row < barcodeMatrix->GetSize(); row++) { |
- result += row; |
- int32_t l = 0; |
- for (; l < ((CFX_PtrArray*)barcodeMatrix->GetAt(row))->GetSize(); l++) { |
- CBC_BarcodeValue* barcodeValue = |
- (CBC_BarcodeValue*)((CFX_PtrArray*)barcodeMatrix->GetAt(row)) |
- ->GetAt(l); |
- if (barcodeValue->getValue()->GetSize() == 0) { |
- result += ""; |
- } else { |
- result += barcodeValue->getValue()->GetAt(0); |
- result += |
- barcodeValue->getConfidence(barcodeValue->getValue()->GetAt(0)); |
- } |
- } |
- } |
- return result; |
-} |
-CBC_DetectionResult* CBC_PDF417ScanningDecoder::merge( |
- CBC_DetectionResultRowIndicatorColumn* leftRowIndicatorColumn, |
- CBC_DetectionResultRowIndicatorColumn* rightRowIndicatorColumn, |
- int32_t& e) { |
- if (leftRowIndicatorColumn == NULL && rightRowIndicatorColumn == NULL) { |
- e = BCExceptionIllegalArgument; |
- return NULL; |
- } |
- CBC_BarcodeMetadata* barcodeMetadata = |
- getBarcodeMetadata(leftRowIndicatorColumn, rightRowIndicatorColumn); |
- if (barcodeMetadata == NULL) { |
- e = BCExceptionCannotMetadata; |
- return NULL; |
- } |
- CBC_BoundingBox* leftboundingBox = |
- adjustBoundingBox(leftRowIndicatorColumn, e); |
- if (e != BCExceptionNO) { |
- delete barcodeMetadata; |
- return NULL; |
- } |
- CBC_BoundingBox* rightboundingBox = |
- adjustBoundingBox(rightRowIndicatorColumn, e); |
- if (e != BCExceptionNO) { |
- delete barcodeMetadata; |
- return NULL; |
- } |
- CBC_BoundingBox* boundingBox = |
- CBC_BoundingBox::merge(leftboundingBox, rightboundingBox, e); |
- if (e != BCExceptionNO) { |
- delete barcodeMetadata; |
- return NULL; |
- } |
- CBC_DetectionResult* detectionresult = |
- new CBC_DetectionResult(barcodeMetadata, boundingBox); |
- return detectionresult; |
-} |
-CBC_BoundingBox* CBC_PDF417ScanningDecoder::adjustBoundingBox( |
- CBC_DetectionResultRowIndicatorColumn* rowIndicatorColumn, |
- int32_t& e) { |
- if (rowIndicatorColumn == NULL) { |
- return NULL; |
- } |
- CFX_Int32Array* rowHeights = rowIndicatorColumn->getRowHeights(e); |
- BC_EXCEPTION_CHECK_ReturnValue(e, NULL); |
- int32_t maxRowHeight = getMax(*rowHeights); |
- int32_t missingStartRows = 0; |
- for (int32_t i = 0; i < rowHeights->GetSize(); i++) { |
- int32_t rowHeight = rowHeights->GetAt(i); |
- missingStartRows += maxRowHeight - rowHeight; |
- if (rowHeight > 0) { |
- break; |
- } |
- } |
- CFX_PtrArray* codewords = rowIndicatorColumn->getCodewords(); |
- for (int32_t row = 0; missingStartRows > 0 && codewords->GetAt(row) == NULL; |
- row++) { |
- missingStartRows--; |
- } |
- int32_t missingEndRows = 0; |
- for (int32_t row1 = rowHeights->GetSize() - 1; row1 >= 0; row1--) { |
- missingEndRows += maxRowHeight - rowHeights->GetAt(row1); |
- if (rowHeights->GetAt(row1) > 0) { |
- break; |
- } |
- } |
- for (int32_t row2 = codewords->GetSize() - 1; |
- missingEndRows > 0 && codewords->GetAt(row2) == NULL; row2--) { |
- missingEndRows--; |
- } |
- CBC_BoundingBox* boundingBox = |
- rowIndicatorColumn->getBoundingBox()->addMissingRows( |
- missingStartRows, missingEndRows, rowIndicatorColumn->isLeft(), e); |
- BC_EXCEPTION_CHECK_ReturnValue(e, NULL); |
- return boundingBox; |
-} |
-int32_t CBC_PDF417ScanningDecoder::getMax(CFX_Int32Array& values) { |
- int32_t maxValue = -1; |
- for (int32_t i = 0; i < values.GetSize(); i++) { |
- int32_t value = values.GetAt(i); |
- maxValue = maxValue > value ? maxValue : value; |
- } |
- return maxValue; |
-} |
-CBC_BarcodeMetadata* CBC_PDF417ScanningDecoder::getBarcodeMetadata( |
- CBC_DetectionResultRowIndicatorColumn* leftRowIndicatorColumn, |
- CBC_DetectionResultRowIndicatorColumn* rightRowIndicatorColumn) { |
- CBC_BarcodeMetadata* leftBarcodeMetadata = NULL; |
- CBC_BarcodeMetadata* rightBarcodeMetadata = NULL; |
- if (leftRowIndicatorColumn == NULL || |
- (leftBarcodeMetadata = leftRowIndicatorColumn->getBarcodeMetadata()) == |
- NULL) { |
- return rightRowIndicatorColumn == NULL |
- ? NULL |
- : rightRowIndicatorColumn->getBarcodeMetadata(); |
- } |
- if (rightRowIndicatorColumn == NULL || |
- (rightBarcodeMetadata = rightRowIndicatorColumn->getBarcodeMetadata()) == |
- NULL) { |
- return leftRowIndicatorColumn == NULL |
- ? NULL |
- : leftRowIndicatorColumn->getBarcodeMetadata(); |
- } |
- if (leftBarcodeMetadata->getColumnCount() != |
- rightBarcodeMetadata->getColumnCount() && |
- leftBarcodeMetadata->getErrorCorrectionLevel() != |
- rightBarcodeMetadata->getErrorCorrectionLevel() && |
- leftBarcodeMetadata->getRowCount() != |
- rightBarcodeMetadata->getRowCount()) { |
- delete leftBarcodeMetadata; |
- delete rightBarcodeMetadata; |
- return NULL; |
- } |
- delete rightBarcodeMetadata; |
- return leftBarcodeMetadata; |
-} |
-CBC_DetectionResultRowIndicatorColumn* |
-CBC_PDF417ScanningDecoder::getRowIndicatorColumn(CBC_CommonBitMatrix* image, |
- CBC_BoundingBox* boundingBox, |
- CBC_ResultPoint startPoint, |
- FX_BOOL leftToRight, |
- int32_t minCodewordWidth, |
- int32_t maxCodewordWidth) { |
- CBC_DetectionResultRowIndicatorColumn* rowIndicatorColumn = |
- new CBC_DetectionResultRowIndicatorColumn(boundingBox, leftToRight); |
- for (int32_t i = 0; i < 2; i++) { |
- int32_t increment = i == 0 ? 1 : -1; |
- int32_t startColumn = (int32_t)startPoint.GetX(); |
- for (int32_t imageRow = (int32_t)startPoint.GetY(); |
- imageRow <= boundingBox->getMaxY() && |
- imageRow >= boundingBox->getMinY(); |
- imageRow += increment) { |
- CBC_Codeword* codeword = |
- detectCodeword(image, 0, image->GetWidth(), leftToRight, startColumn, |
- imageRow, minCodewordWidth, maxCodewordWidth); |
- if (codeword != NULL) { |
- rowIndicatorColumn->setCodeword(imageRow, codeword); |
- if (leftToRight) { |
- startColumn = codeword->getStartX(); |
- } else { |
- startColumn = codeword->getEndX(); |
- } |
- } |
- } |
- } |
- return rowIndicatorColumn; |
-} |
-void CBC_PDF417ScanningDecoder::adjustCodewordCount( |
- CBC_DetectionResult* detectionResult, |
- CFX_PtrArray* barcodeMatrix, |
- int32_t& e) { |
- CFX_Int32Array* numberOfCodewords = |
- ((CBC_BarcodeValue*)((CFX_PtrArray*)barcodeMatrix->GetAt(0))->GetAt(1)) |
- ->getValue(); |
- int32_t calculatedNumberOfCodewords = |
- detectionResult->getBarcodeColumnCount() * |
- detectionResult->getBarcodeRowCount() - |
- getNumberOfECCodeWords(detectionResult->getBarcodeECLevel()); |
- if (numberOfCodewords->GetSize() == 0) { |
- if (calculatedNumberOfCodewords < 1 || |
- calculatedNumberOfCodewords > |
- CBC_PDF417Common::MAX_CODEWORDS_IN_BARCODE) { |
- e = BCExceptiontNotFoundInstance; |
- delete numberOfCodewords; |
- BC_EXCEPTION_CHECK_ReturnVoid(e); |
- } |
- ((CBC_BarcodeValue*)((CFX_PtrArray*)barcodeMatrix->GetAt(0))->GetAt(1)) |
- ->setValue(calculatedNumberOfCodewords); |
- } else if (numberOfCodewords->GetAt(0) != calculatedNumberOfCodewords) { |
- ((CBC_BarcodeValue*)((CFX_PtrArray*)barcodeMatrix->GetAt(0))->GetAt(1)) |
- ->setValue(calculatedNumberOfCodewords); |
- } |
- delete numberOfCodewords; |
-} |
-CBC_CommonDecoderResult* CBC_PDF417ScanningDecoder::createDecoderResult( |
- CBC_DetectionResult* detectionResult, |
- int32_t& e) { |
- CFX_PtrArray* barcodeMatrix = createBarcodeMatrix(detectionResult); |
- adjustCodewordCount(detectionResult, barcodeMatrix, e); |
- if (e != BCExceptionNO) { |
- for (int32_t i = 0; i < barcodeMatrix->GetSize(); i++) { |
- CFX_PtrArray* temp = (CFX_PtrArray*)barcodeMatrix->GetAt(i); |
- for (int32_t j = 0; j < temp->GetSize(); j++) { |
- delete (CBC_BarcodeValue*)temp->GetAt(j); |
- } |
- temp->RemoveAll(); |
- delete temp; |
- } |
- barcodeMatrix->RemoveAll(); |
- delete barcodeMatrix; |
- return NULL; |
- } |
- CFX_Int32Array erasures; |
- CFX_Int32Array codewords; |
- codewords.SetSize(detectionResult->getBarcodeRowCount() * |
- detectionResult->getBarcodeColumnCount()); |
- CFX_PtrArray ambiguousIndexValuesList; |
- CFX_Int32Array ambiguousIndexesList; |
- for (int32_t row = 0; row < detectionResult->getBarcodeRowCount(); row++) { |
- for (int32_t l = 0; l < detectionResult->getBarcodeColumnCount(); l++) { |
- CFX_Int32Array* values = |
- ((CBC_BarcodeValue*)((CFX_PtrArray*)barcodeMatrix->GetAt(row)) |
- ->GetAt(l + 1)) |
- ->getValue(); |
- int32_t codewordIndex = |
- row * detectionResult->getBarcodeColumnCount() + l; |
- if (values->GetSize() == 0) { |
- erasures.Add(codewordIndex); |
- } else if (values->GetSize() == 1) { |
- codewords[codewordIndex] = values->GetAt(0); |
- } else { |
- ambiguousIndexesList.Add(codewordIndex); |
- ambiguousIndexValuesList.Add(values); |
- } |
- } |
- } |
- CFX_PtrArray ambiguousIndexValues; |
- ambiguousIndexValues.SetSize(ambiguousIndexValuesList.GetSize()); |
- for (int32_t i = 0; i < ambiguousIndexValues.GetSize(); i++) { |
- ambiguousIndexValues.SetAt(i, ambiguousIndexValuesList.GetAt(i)); |
- } |
- for (int32_t l = 0; l < barcodeMatrix->GetSize(); l++) { |
- CFX_PtrArray* temp = (CFX_PtrArray*)barcodeMatrix->GetAt(l); |
- for (int32_t j = 0; j < temp->GetSize(); j++) { |
- delete (CBC_BarcodeValue*)temp->GetAt(j); |
- } |
- temp->RemoveAll(); |
- delete temp; |
- } |
- barcodeMatrix->RemoveAll(); |
- delete barcodeMatrix; |
- CBC_CommonDecoderResult* decoderResult = |
- createDecoderResultFromAmbiguousValues( |
- detectionResult->getBarcodeECLevel(), codewords, erasures, |
- ambiguousIndexesList, ambiguousIndexValues, e); |
- BC_EXCEPTION_CHECK_ReturnValue(e, NULL); |
- return decoderResult; |
-} |
-CBC_CommonDecoderResult* |
-CBC_PDF417ScanningDecoder::createDecoderResultFromAmbiguousValues( |
- int32_t ecLevel, |
- CFX_Int32Array& codewords, |
- CFX_Int32Array& erasureArray, |
- CFX_Int32Array& ambiguousIndexes, |
- CFX_PtrArray& ambiguousIndexValues, |
- int32_t& e) { |
- CFX_Int32Array ambiguousIndexCount; |
- ambiguousIndexCount.SetSize(ambiguousIndexes.GetSize()); |
- int32_t tries = 100; |
- while (tries-- > 0) { |
- for (int32_t l = 0; l < ambiguousIndexCount.GetSize(); l++) { |
- codewords[ambiguousIndexes[l]] = |
- ((CFX_Int32Array*)ambiguousIndexValues.GetAt(l)) |
- ->GetAt(ambiguousIndexCount[l]); |
- } |
- CBC_CommonDecoderResult* decoderResult = |
- decodeCodewords(codewords, ecLevel, erasureArray, e); |
- if (e != BCExceptionNO) { |
- e = BCExceptionNO; |
- continue; |
- } else { |
- return decoderResult; |
- } |
- if (ambiguousIndexCount.GetSize() == 0) { |
- e = BCExceptionChecksumInstance; |
- return NULL; |
- } |
- for (int32_t i = 0; i < ambiguousIndexCount.GetSize(); i++) { |
- if (ambiguousIndexCount[i] < |
- ((CFX_Int32Array*)(ambiguousIndexValues.GetAt(i)))->GetSize() - 1) { |
- ambiguousIndexCount[i]++; |
- break; |
- } else { |
- ambiguousIndexCount[i] = 0; |
- if (i == ambiguousIndexCount.GetSize() - 1) { |
- e = BCExceptionChecksumInstance; |
- return NULL; |
- } |
- } |
- } |
- } |
- e = BCExceptionChecksumInstance; |
- return NULL; |
-} |
-CFX_PtrArray* CBC_PDF417ScanningDecoder::createBarcodeMatrix( |
- CBC_DetectionResult* detectionResult) { |
- CFX_PtrArray* barcodeMatrix = new CFX_PtrArray; |
- barcodeMatrix->SetSize(detectionResult->getBarcodeRowCount()); |
- CFX_PtrArray* temp = NULL; |
- int32_t colume = 0; |
- for (int32_t row = 0; row < barcodeMatrix->GetSize(); row++) { |
- temp = new CFX_PtrArray; |
- temp->SetSize(detectionResult->getBarcodeColumnCount() + 2); |
- for (colume = 0; colume < detectionResult->getBarcodeColumnCount() + 2; |
- colume++) { |
- temp->SetAt(colume, new CBC_BarcodeValue()); |
- } |
- barcodeMatrix->SetAt(row, temp); |
- } |
- colume = -1; |
- for (int32_t i = 0; |
- i < detectionResult->getDetectionResultColumns().GetSize(); i++) { |
- CBC_DetectionResultColumn* detectionResultColumn = |
- (CBC_DetectionResultColumn*)detectionResult->getDetectionResultColumns() |
- .GetAt(i); |
- colume++; |
- if (detectionResultColumn == NULL) { |
- continue; |
- } |
- CFX_PtrArray* temp = detectionResultColumn->getCodewords(); |
- for (int32_t l = 0; l < temp->GetSize(); l++) { |
- CBC_Codeword* codeword = (CBC_Codeword*)temp->GetAt(l); |
- if (codeword == NULL || codeword->getRowNumber() == -1) { |
- continue; |
- } |
- ((CBC_BarcodeValue*)((CFX_PtrArray*)barcodeMatrix->GetAt( |
- codeword->getRowNumber())) |
- ->GetAt(colume)) |
- ->setValue(codeword->getValue()); |
- } |
- } |
- return barcodeMatrix; |
-} |
-FX_BOOL CBC_PDF417ScanningDecoder::isValidBarcodeColumn( |
- CBC_DetectionResult* detectionResult, |
- int32_t barcodeColumn) { |
- return barcodeColumn >= 0 && |
- barcodeColumn <= detectionResult->getBarcodeColumnCount() + 1; |
-} |
-int32_t CBC_PDF417ScanningDecoder::getStartColumn( |
- CBC_DetectionResult* detectionResult, |
- int32_t barcodeColumn, |
- int32_t imageRow, |
- FX_BOOL leftToRight) { |
- int32_t offset = leftToRight ? 1 : -1; |
- CBC_Codeword* codeword = NULL; |
- if (isValidBarcodeColumn(detectionResult, barcodeColumn - offset)) { |
- codeword = detectionResult->getDetectionResultColumn(barcodeColumn - offset) |
- ->getCodeword(imageRow); |
- } |
- if (codeword != NULL) { |
- return leftToRight ? codeword->getEndX() : codeword->getStartX(); |
- } |
- codeword = detectionResult->getDetectionResultColumn(barcodeColumn) |
- ->getCodewordNearby(imageRow); |
- if (codeword != NULL) { |
- return leftToRight ? codeword->getStartX() : codeword->getEndX(); |
- } |
- if (isValidBarcodeColumn(detectionResult, barcodeColumn - offset)) { |
- codeword = detectionResult->getDetectionResultColumn(barcodeColumn - offset) |
- ->getCodewordNearby(imageRow); |
- } |
- if (codeword != NULL) { |
- return leftToRight ? codeword->getEndX() : codeword->getStartX(); |
- } |
- int32_t skippedColumns = 0; |
- while (isValidBarcodeColumn(detectionResult, barcodeColumn - offset)) { |
- barcodeColumn -= offset; |
- for (int32_t i = 0; |
- i < detectionResult->getDetectionResultColumn(barcodeColumn) |
- ->getCodewords() |
- ->GetSize(); |
- i++) { |
- CBC_Codeword* previousRowCodeword = |
- (CBC_Codeword*)detectionResult->getDetectionResultColumn( |
- barcodeColumn) |
- ->getCodewords() |
- ->GetAt(i); |
- if (previousRowCodeword != NULL) { |
- return (leftToRight ? previousRowCodeword->getEndX() |
- : previousRowCodeword->getStartX()) + |
- offset * skippedColumns * (previousRowCodeword->getEndX() - |
- previousRowCodeword->getStartX()); |
- } |
- } |
- skippedColumns++; |
- } |
- return leftToRight ? detectionResult->getBoundingBox()->getMinX() |
- : detectionResult->getBoundingBox()->getMaxX(); |
-} |
-CBC_Codeword* CBC_PDF417ScanningDecoder::detectCodeword( |
- CBC_CommonBitMatrix* image, |
- int32_t minColumn, |
- int32_t maxColumn, |
- FX_BOOL leftToRight, |
- int32_t startColumn, |
- int32_t imageRow, |
- int32_t minCodewordWidth, |
- int32_t maxCodewordWidth) { |
- startColumn = adjustCodewordStartColumn(image, minColumn, maxColumn, |
- leftToRight, startColumn, imageRow); |
- CFX_Int32Array* moduleBitCount = getModuleBitCount( |
- image, minColumn, maxColumn, leftToRight, startColumn, imageRow); |
- if (moduleBitCount == NULL) { |
- return NULL; |
- } |
- int32_t endColumn; |
- int32_t codewordBitCount = CBC_PDF417Common::getBitCountSum(*moduleBitCount); |
- if (leftToRight) { |
- endColumn = startColumn + codewordBitCount; |
- } else { |
- for (int32_t i = 0; i<moduleBitCount->GetSize()>> 1; i++) { |
- int32_t tmpCount = moduleBitCount->GetAt(i); |
- moduleBitCount->SetAt( |
- i, moduleBitCount->GetAt(moduleBitCount->GetSize() - 1 - i)); |
- moduleBitCount->SetAt(moduleBitCount->GetSize() - 1 - i, tmpCount); |
- } |
- endColumn = startColumn; |
- startColumn = endColumn - codewordBitCount; |
- } |
- int32_t decodedValue = |
- CBC_PDF417CodewordDecoder::getDecodedValue(*moduleBitCount); |
- int32_t codeword = CBC_PDF417Common::getCodeword(decodedValue); |
- delete moduleBitCount; |
- if (codeword == -1) { |
- return NULL; |
- } |
- return new CBC_Codeword(startColumn, endColumn, |
- getCodewordBucketNumber(decodedValue), codeword); |
-} |
-CFX_Int32Array* CBC_PDF417ScanningDecoder::getModuleBitCount( |
- CBC_CommonBitMatrix* image, |
- int32_t minColumn, |
- int32_t maxColumn, |
- FX_BOOL leftToRight, |
- int32_t startColumn, |
- int32_t imageRow) { |
- int32_t imageColumn = startColumn; |
- CFX_Int32Array* moduleBitCount = new CFX_Int32Array; |
- moduleBitCount->SetSize(8); |
- int32_t moduleNumber = 0; |
- int32_t increment = leftToRight ? 1 : -1; |
- FX_BOOL previousPixelValue = leftToRight; |
- while (((leftToRight && imageColumn < maxColumn) || |
- (!leftToRight && imageColumn >= minColumn)) && |
- moduleNumber < moduleBitCount->GetSize()) { |
- if (image->Get(imageColumn, imageRow) == previousPixelValue) { |
- moduleBitCount->SetAt(moduleNumber, |
- moduleBitCount->GetAt(moduleNumber) + 1); |
- imageColumn += increment; |
- } else { |
- moduleNumber++; |
- previousPixelValue = !previousPixelValue; |
- } |
- } |
- if (moduleNumber == moduleBitCount->GetSize() || |
- (((leftToRight && imageColumn == maxColumn) || |
- (!leftToRight && imageColumn == minColumn)) && |
- moduleNumber == moduleBitCount->GetSize() - 1)) { |
- return moduleBitCount; |
- } |
- delete moduleBitCount; |
- return NULL; |
-} |
-int32_t CBC_PDF417ScanningDecoder::getNumberOfECCodeWords( |
- int32_t barcodeECLevel) { |
- return 2 << barcodeECLevel; |
-} |
-int32_t CBC_PDF417ScanningDecoder::adjustCodewordStartColumn( |
- CBC_CommonBitMatrix* image, |
- int32_t minColumn, |
- int32_t maxColumn, |
- FX_BOOL leftToRight, |
- int32_t codewordStartColumn, |
- int32_t imageRow) { |
- int32_t correctedStartColumn = codewordStartColumn; |
- int32_t increment = leftToRight ? -1 : 1; |
- for (int32_t i = 0; i < 2; i++) { |
- while (((leftToRight && correctedStartColumn >= minColumn) || |
- (!leftToRight && correctedStartColumn < maxColumn)) && |
- leftToRight == image->Get(correctedStartColumn, imageRow)) { |
- if (abs(codewordStartColumn - correctedStartColumn) > |
- CODEWORD_SKEW_SIZE) { |
- return codewordStartColumn; |
- } |
- correctedStartColumn += increment; |
- } |
- increment = -increment; |
- leftToRight = !leftToRight; |
- } |
- return correctedStartColumn; |
-} |
-FX_BOOL CBC_PDF417ScanningDecoder::checkCodewordSkew(int32_t codewordSize, |
- int32_t minCodewordWidth, |
- int32_t maxCodewordWidth) { |
- return minCodewordWidth - CODEWORD_SKEW_SIZE <= codewordSize && |
- codewordSize <= maxCodewordWidth + CODEWORD_SKEW_SIZE; |
-} |
-CBC_CommonDecoderResult* CBC_PDF417ScanningDecoder::decodeCodewords( |
- CFX_Int32Array& codewords, |
- int32_t ecLevel, |
- CFX_Int32Array& erasures, |
- int32_t& e) { |
- if (codewords.GetSize() == 0) { |
- e = BCExceptionFormatInstance; |
- return NULL; |
- } |
- int32_t numECCodewords = 1 << (ecLevel + 1); |
- correctErrors(codewords, erasures, numECCodewords, e); |
- BC_EXCEPTION_CHECK_ReturnValue(e, NULL); |
- verifyCodewordCount(codewords, numECCodewords, e); |
- BC_EXCEPTION_CHECK_ReturnValue(e, NULL); |
- CFX_ByteString bytestring; |
- CBC_CommonDecoderResult* decoderResult = CBC_DecodedBitStreamPaser::decode( |
- codewords, bytestring.FormatInteger(ecLevel), e); |
- BC_EXCEPTION_CHECK_ReturnValue(e, NULL); |
- return decoderResult; |
-} |
-int32_t CBC_PDF417ScanningDecoder::correctErrors(CFX_Int32Array& codewords, |
- CFX_Int32Array& erasures, |
- int32_t numECCodewords, |
- int32_t& e) { |
- if ((erasures.GetSize() != 0 && |
- erasures.GetSize() > (numECCodewords / 2 + MAX_ERRORS)) || |
- numECCodewords < 0 || numECCodewords > MAX_EC_CODEWORDS) { |
- e = BCExceptionChecksumInstance; |
- return -1; |
- } |
- int32_t result = CBC_PDF417ECErrorCorrection::decode( |
- codewords, numECCodewords, erasures, e); |
- BC_EXCEPTION_CHECK_ReturnValue(e, -1); |
- return result; |
-} |
-void CBC_PDF417ScanningDecoder::verifyCodewordCount(CFX_Int32Array& codewords, |
- int32_t numECCodewords, |
- int32_t& e) { |
- if (codewords.GetSize() < 4) { |
- e = BCExceptionFormatInstance; |
- return; |
- } |
- int32_t numberOfCodewords = codewords.GetAt(0); |
- if (numberOfCodewords > codewords.GetSize()) { |
- e = BCExceptionFormatInstance; |
- return; |
- } |
- if (numberOfCodewords == 0) { |
- if (numECCodewords < codewords.GetSize()) { |
- codewords[0] = codewords.GetSize() - numECCodewords; |
- } else { |
- e = BCExceptionFormatInstance; |
- return; |
- } |
- } |
-} |
-CFX_Int32Array* CBC_PDF417ScanningDecoder::getBitCountForCodeword( |
- int32_t codeword) { |
- CFX_Int32Array* result = new CFX_Int32Array; |
- result->SetSize(8); |
- int32_t previousValue = 0; |
- int32_t i = result->GetSize() - 1; |
- while (TRUE) { |
- if ((codeword & 0x1) != previousValue) { |
- previousValue = codeword & 0x1; |
- i--; |
- if (i < 0) { |
- break; |
- } |
- } |
- result->SetAt(i, result->GetAt(i) + 1); |
- codeword >>= 1; |
- } |
- return result; |
-} |
-int32_t CBC_PDF417ScanningDecoder::getCodewordBucketNumber(int32_t codeword) { |
- CFX_Int32Array* array = getBitCountForCodeword(codeword); |
- int32_t result = getCodewordBucketNumber(*array); |
- delete array; |
- return result; |
-} |
-int32_t CBC_PDF417ScanningDecoder::getCodewordBucketNumber( |
- CFX_Int32Array& moduleBitCount) { |
- return (moduleBitCount.GetAt(0) - moduleBitCount.GetAt(2) + |
- moduleBitCount.GetAt(4) - moduleBitCount.GetAt(6) + 9) % |
- 9; |
-} |
+// 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 2013 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 "xfa/src/fxbarcode/barcode.h" |
+#include "xfa/src/fxbarcode/BC_DecoderResult.h" |
+#include "xfa/src/fxbarcode/BC_ResultPoint.h" |
+#include "xfa/src/fxbarcode/common/BC_CommonBitMatrix.h" |
+#include "BC_PDF417Codeword.h" |
+#include "BC_PDF417Common.h" |
+#include "BC_PDF417BarcodeValue.h" |
+#include "BC_PDF417BarcodeMetadata.h" |
+#include "BC_PDF417BoundingBox.h" |
+#include "BC_PDF417DetectionResultColumn.h" |
+#include "BC_PDF417DetectionResultRowIndicatorColumn.h" |
+#include "BC_PDF417DetectionResult.h" |
+#include "BC_PDF417DecodedBitStreamParser.h" |
+#include "BC_PDF417CodewordDecoder.h" |
+#include "BC_PDF417DecodedBitStreamParser.h" |
+#include "BC_PDF417ECModulusPoly.h" |
+#include "BC_PDF417ECModulusGF.h" |
+#include "BC_PDF417ECErrorCorrection.h" |
+#include "BC_PDF417DecodedBitStreamParser.h" |
+#include "BC_PDF417ScanningDecoder.h" |
+int32_t CBC_PDF417ScanningDecoder::CODEWORD_SKEW_SIZE = 2; |
+int32_t CBC_PDF417ScanningDecoder::MAX_ERRORS = 3; |
+int32_t CBC_PDF417ScanningDecoder::MAX_EC_CODEWORDS = 512; |
+CBC_PDF417ECErrorCorrection* CBC_PDF417ScanningDecoder::errorCorrection = NULL; |
+CBC_PDF417ScanningDecoder::CBC_PDF417ScanningDecoder() {} |
+CBC_PDF417ScanningDecoder::~CBC_PDF417ScanningDecoder() {} |
+void CBC_PDF417ScanningDecoder::Initialize() { |
+ errorCorrection = new CBC_PDF417ECErrorCorrection; |
+} |
+void CBC_PDF417ScanningDecoder::Finalize() { |
+ delete errorCorrection; |
+} |
+CBC_CommonDecoderResult* CBC_PDF417ScanningDecoder::decode( |
+ CBC_CommonBitMatrix* image, |
+ CBC_ResultPoint* imageTopLeft, |
+ CBC_ResultPoint* imageBottomLeft, |
+ CBC_ResultPoint* imageTopRight, |
+ CBC_ResultPoint* imageBottomRight, |
+ int32_t minCodewordWidth, |
+ int32_t maxCodewordWidth, |
+ int32_t& e) { |
+ CBC_BoundingBox* boundingBox = new CBC_BoundingBox( |
+ image, imageTopLeft, imageBottomLeft, imageTopRight, imageBottomRight, e); |
+ BC_EXCEPTION_CHECK_ReturnValue(e, NULL); |
+ CBC_DetectionResultRowIndicatorColumn* leftRowIndicatorColumn = NULL; |
+ CBC_DetectionResultRowIndicatorColumn* rightRowIndicatorColumn = NULL; |
+ CBC_DetectionResult* detectionResult = NULL; |
+ for (int32_t i = 0; i < 2; i++) { |
+ if (imageTopLeft != NULL) { |
+ leftRowIndicatorColumn = |
+ getRowIndicatorColumn(image, boundingBox, *imageTopLeft, TRUE, |
+ minCodewordWidth, maxCodewordWidth); |
+ } |
+ if (imageTopRight != NULL) { |
+ rightRowIndicatorColumn = |
+ getRowIndicatorColumn(image, boundingBox, *imageTopRight, FALSE, |
+ minCodewordWidth, maxCodewordWidth); |
+ } |
+ detectionResult = merge(leftRowIndicatorColumn, rightRowIndicatorColumn, e); |
+ if (e != BCExceptionNO) { |
+ e = BCExceptiontNotFoundInstance; |
+ delete leftRowIndicatorColumn; |
+ delete rightRowIndicatorColumn; |
+ delete boundingBox; |
+ return NULL; |
+ } |
+ if (i == 0 && (detectionResult->getBoundingBox()->getMinY() < |
+ boundingBox->getMinY() || |
+ detectionResult->getBoundingBox()->getMaxY() > |
+ boundingBox->getMaxY())) { |
+ delete boundingBox; |
+ boundingBox = detectionResult->getBoundingBox(); |
+ } else { |
+ detectionResult->setBoundingBox(boundingBox); |
+ break; |
+ } |
+ } |
+ int32_t maxBarcodeColumn = detectionResult->getBarcodeColumnCount() + 1; |
+ detectionResult->setDetectionResultColumn(0, leftRowIndicatorColumn); |
+ detectionResult->setDetectionResultColumn(maxBarcodeColumn, |
+ rightRowIndicatorColumn); |
+ FX_BOOL leftToRight = leftRowIndicatorColumn != NULL; |
+ for (int32_t barcodeColumnCount = 1; barcodeColumnCount <= maxBarcodeColumn; |
+ barcodeColumnCount++) { |
+ int32_t barcodeColumn = leftToRight ? barcodeColumnCount |
+ : maxBarcodeColumn - barcodeColumnCount; |
+ if (detectionResult->getDetectionResultColumn(barcodeColumn) != NULL) { |
+ continue; |
+ } |
+ CBC_DetectionResultColumn* detectionResultColumn = NULL; |
+ if (barcodeColumn == 0 || barcodeColumn == maxBarcodeColumn) { |
+ detectionResultColumn = new CBC_DetectionResultRowIndicatorColumn( |
+ boundingBox, barcodeColumn == 0); |
+ } else { |
+ detectionResultColumn = new CBC_DetectionResultColumn(boundingBox); |
+ } |
+ detectionResult->setDetectionResultColumn(barcodeColumn, |
+ detectionResultColumn); |
+ int32_t startColumn = -1; |
+ int32_t previousStartColumn = startColumn; |
+ for (int32_t imageRow = boundingBox->getMinY(); |
+ imageRow <= boundingBox->getMaxY(); imageRow++) { |
+ startColumn = |
+ getStartColumn(detectionResult, barcodeColumn, imageRow, leftToRight); |
+ if (startColumn < 0 || startColumn > boundingBox->getMaxX()) { |
+ if (previousStartColumn == -1) { |
+ continue; |
+ } |
+ startColumn = previousStartColumn; |
+ } |
+ CBC_Codeword* codeword = detectCodeword( |
+ image, boundingBox->getMinX(), boundingBox->getMaxX(), leftToRight, |
+ startColumn, imageRow, minCodewordWidth, maxCodewordWidth); |
+ if (codeword != NULL) { |
+ detectionResultColumn->setCodeword(imageRow, codeword); |
+ previousStartColumn = startColumn; |
+ minCodewordWidth = minCodewordWidth < codeword->getWidth() |
+ ? minCodewordWidth |
+ : codeword->getWidth(); |
+ maxCodewordWidth = maxCodewordWidth > codeword->getWidth() |
+ ? maxCodewordWidth |
+ : codeword->getWidth(); |
+ } |
+ } |
+ } |
+ CBC_CommonDecoderResult* decoderresult = |
+ createDecoderResult(detectionResult, e); |
+ if (e != BCExceptionNO) { |
+ delete detectionResult; |
+ return NULL; |
+ } |
+ return decoderresult; |
+} |
+CFX_ByteString CBC_PDF417ScanningDecoder::toString( |
+ CFX_PtrArray* barcodeMatrix) { |
+ CFX_ByteString result; |
+ for (int32_t row = 0; row < barcodeMatrix->GetSize(); row++) { |
+ result += row; |
+ int32_t l = 0; |
+ for (; l < ((CFX_PtrArray*)barcodeMatrix->GetAt(row))->GetSize(); l++) { |
+ CBC_BarcodeValue* barcodeValue = |
+ (CBC_BarcodeValue*)((CFX_PtrArray*)barcodeMatrix->GetAt(row)) |
+ ->GetAt(l); |
+ if (barcodeValue->getValue()->GetSize() == 0) { |
+ result += ""; |
+ } else { |
+ result += barcodeValue->getValue()->GetAt(0); |
+ result += |
+ barcodeValue->getConfidence(barcodeValue->getValue()->GetAt(0)); |
+ } |
+ } |
+ } |
+ return result; |
+} |
+CBC_DetectionResult* CBC_PDF417ScanningDecoder::merge( |
+ CBC_DetectionResultRowIndicatorColumn* leftRowIndicatorColumn, |
+ CBC_DetectionResultRowIndicatorColumn* rightRowIndicatorColumn, |
+ int32_t& e) { |
+ if (leftRowIndicatorColumn == NULL && rightRowIndicatorColumn == NULL) { |
+ e = BCExceptionIllegalArgument; |
+ return NULL; |
+ } |
+ CBC_BarcodeMetadata* barcodeMetadata = |
+ getBarcodeMetadata(leftRowIndicatorColumn, rightRowIndicatorColumn); |
+ if (barcodeMetadata == NULL) { |
+ e = BCExceptionCannotMetadata; |
+ return NULL; |
+ } |
+ CBC_BoundingBox* leftboundingBox = |
+ adjustBoundingBox(leftRowIndicatorColumn, e); |
+ if (e != BCExceptionNO) { |
+ delete barcodeMetadata; |
+ return NULL; |
+ } |
+ CBC_BoundingBox* rightboundingBox = |
+ adjustBoundingBox(rightRowIndicatorColumn, e); |
+ if (e != BCExceptionNO) { |
+ delete barcodeMetadata; |
+ return NULL; |
+ } |
+ CBC_BoundingBox* boundingBox = |
+ CBC_BoundingBox::merge(leftboundingBox, rightboundingBox, e); |
+ if (e != BCExceptionNO) { |
+ delete barcodeMetadata; |
+ return NULL; |
+ } |
+ CBC_DetectionResult* detectionresult = |
+ new CBC_DetectionResult(barcodeMetadata, boundingBox); |
+ return detectionresult; |
+} |
+CBC_BoundingBox* CBC_PDF417ScanningDecoder::adjustBoundingBox( |
+ CBC_DetectionResultRowIndicatorColumn* rowIndicatorColumn, |
+ int32_t& e) { |
+ if (rowIndicatorColumn == NULL) { |
+ return NULL; |
+ } |
+ CFX_Int32Array* rowHeights = rowIndicatorColumn->getRowHeights(e); |
+ BC_EXCEPTION_CHECK_ReturnValue(e, NULL); |
+ int32_t maxRowHeight = getMax(*rowHeights); |
+ int32_t missingStartRows = 0; |
+ for (int32_t i = 0; i < rowHeights->GetSize(); i++) { |
+ int32_t rowHeight = rowHeights->GetAt(i); |
+ missingStartRows += maxRowHeight - rowHeight; |
+ if (rowHeight > 0) { |
+ break; |
+ } |
+ } |
+ CFX_PtrArray* codewords = rowIndicatorColumn->getCodewords(); |
+ for (int32_t row = 0; missingStartRows > 0 && codewords->GetAt(row) == NULL; |
+ row++) { |
+ missingStartRows--; |
+ } |
+ int32_t missingEndRows = 0; |
+ for (int32_t row1 = rowHeights->GetSize() - 1; row1 >= 0; row1--) { |
+ missingEndRows += maxRowHeight - rowHeights->GetAt(row1); |
+ if (rowHeights->GetAt(row1) > 0) { |
+ break; |
+ } |
+ } |
+ for (int32_t row2 = codewords->GetSize() - 1; |
+ missingEndRows > 0 && codewords->GetAt(row2) == NULL; row2--) { |
+ missingEndRows--; |
+ } |
+ CBC_BoundingBox* boundingBox = |
+ rowIndicatorColumn->getBoundingBox()->addMissingRows( |
+ missingStartRows, missingEndRows, rowIndicatorColumn->isLeft(), e); |
+ BC_EXCEPTION_CHECK_ReturnValue(e, NULL); |
+ return boundingBox; |
+} |
+int32_t CBC_PDF417ScanningDecoder::getMax(CFX_Int32Array& values) { |
+ int32_t maxValue = -1; |
+ for (int32_t i = 0; i < values.GetSize(); i++) { |
+ int32_t value = values.GetAt(i); |
+ maxValue = maxValue > value ? maxValue : value; |
+ } |
+ return maxValue; |
+} |
+CBC_BarcodeMetadata* CBC_PDF417ScanningDecoder::getBarcodeMetadata( |
+ CBC_DetectionResultRowIndicatorColumn* leftRowIndicatorColumn, |
+ CBC_DetectionResultRowIndicatorColumn* rightRowIndicatorColumn) { |
+ CBC_BarcodeMetadata* leftBarcodeMetadata = NULL; |
+ CBC_BarcodeMetadata* rightBarcodeMetadata = NULL; |
+ if (leftRowIndicatorColumn == NULL || |
+ (leftBarcodeMetadata = leftRowIndicatorColumn->getBarcodeMetadata()) == |
+ NULL) { |
+ return rightRowIndicatorColumn == NULL |
+ ? NULL |
+ : rightRowIndicatorColumn->getBarcodeMetadata(); |
+ } |
+ if (rightRowIndicatorColumn == NULL || |
+ (rightBarcodeMetadata = rightRowIndicatorColumn->getBarcodeMetadata()) == |
+ NULL) { |
+ return leftRowIndicatorColumn == NULL |
+ ? NULL |
+ : leftRowIndicatorColumn->getBarcodeMetadata(); |
+ } |
+ if (leftBarcodeMetadata->getColumnCount() != |
+ rightBarcodeMetadata->getColumnCount() && |
+ leftBarcodeMetadata->getErrorCorrectionLevel() != |
+ rightBarcodeMetadata->getErrorCorrectionLevel() && |
+ leftBarcodeMetadata->getRowCount() != |
+ rightBarcodeMetadata->getRowCount()) { |
+ delete leftBarcodeMetadata; |
+ delete rightBarcodeMetadata; |
+ return NULL; |
+ } |
+ delete rightBarcodeMetadata; |
+ return leftBarcodeMetadata; |
+} |
+CBC_DetectionResultRowIndicatorColumn* |
+CBC_PDF417ScanningDecoder::getRowIndicatorColumn(CBC_CommonBitMatrix* image, |
+ CBC_BoundingBox* boundingBox, |
+ CBC_ResultPoint startPoint, |
+ FX_BOOL leftToRight, |
+ int32_t minCodewordWidth, |
+ int32_t maxCodewordWidth) { |
+ CBC_DetectionResultRowIndicatorColumn* rowIndicatorColumn = |
+ new CBC_DetectionResultRowIndicatorColumn(boundingBox, leftToRight); |
+ for (int32_t i = 0; i < 2; i++) { |
+ int32_t increment = i == 0 ? 1 : -1; |
+ int32_t startColumn = (int32_t)startPoint.GetX(); |
+ for (int32_t imageRow = (int32_t)startPoint.GetY(); |
+ imageRow <= boundingBox->getMaxY() && |
+ imageRow >= boundingBox->getMinY(); |
+ imageRow += increment) { |
+ CBC_Codeword* codeword = |
+ detectCodeword(image, 0, image->GetWidth(), leftToRight, startColumn, |
+ imageRow, minCodewordWidth, maxCodewordWidth); |
+ if (codeword != NULL) { |
+ rowIndicatorColumn->setCodeword(imageRow, codeword); |
+ if (leftToRight) { |
+ startColumn = codeword->getStartX(); |
+ } else { |
+ startColumn = codeword->getEndX(); |
+ } |
+ } |
+ } |
+ } |
+ return rowIndicatorColumn; |
+} |
+void CBC_PDF417ScanningDecoder::adjustCodewordCount( |
+ CBC_DetectionResult* detectionResult, |
+ CFX_PtrArray* barcodeMatrix, |
+ int32_t& e) { |
+ CFX_Int32Array* numberOfCodewords = |
+ ((CBC_BarcodeValue*)((CFX_PtrArray*)barcodeMatrix->GetAt(0))->GetAt(1)) |
+ ->getValue(); |
+ int32_t calculatedNumberOfCodewords = |
+ detectionResult->getBarcodeColumnCount() * |
+ detectionResult->getBarcodeRowCount() - |
+ getNumberOfECCodeWords(detectionResult->getBarcodeECLevel()); |
+ if (numberOfCodewords->GetSize() == 0) { |
+ if (calculatedNumberOfCodewords < 1 || |
+ calculatedNumberOfCodewords > |
+ CBC_PDF417Common::MAX_CODEWORDS_IN_BARCODE) { |
+ e = BCExceptiontNotFoundInstance; |
+ delete numberOfCodewords; |
+ BC_EXCEPTION_CHECK_ReturnVoid(e); |
+ } |
+ ((CBC_BarcodeValue*)((CFX_PtrArray*)barcodeMatrix->GetAt(0))->GetAt(1)) |
+ ->setValue(calculatedNumberOfCodewords); |
+ } else if (numberOfCodewords->GetAt(0) != calculatedNumberOfCodewords) { |
+ ((CBC_BarcodeValue*)((CFX_PtrArray*)barcodeMatrix->GetAt(0))->GetAt(1)) |
+ ->setValue(calculatedNumberOfCodewords); |
+ } |
+ delete numberOfCodewords; |
+} |
+CBC_CommonDecoderResult* CBC_PDF417ScanningDecoder::createDecoderResult( |
+ CBC_DetectionResult* detectionResult, |
+ int32_t& e) { |
+ CFX_PtrArray* barcodeMatrix = createBarcodeMatrix(detectionResult); |
+ adjustCodewordCount(detectionResult, barcodeMatrix, e); |
+ if (e != BCExceptionNO) { |
+ for (int32_t i = 0; i < barcodeMatrix->GetSize(); i++) { |
+ CFX_PtrArray* temp = (CFX_PtrArray*)barcodeMatrix->GetAt(i); |
+ for (int32_t j = 0; j < temp->GetSize(); j++) { |
+ delete (CBC_BarcodeValue*)temp->GetAt(j); |
+ } |
+ temp->RemoveAll(); |
+ delete temp; |
+ } |
+ barcodeMatrix->RemoveAll(); |
+ delete barcodeMatrix; |
+ return NULL; |
+ } |
+ CFX_Int32Array erasures; |
+ CFX_Int32Array codewords; |
+ codewords.SetSize(detectionResult->getBarcodeRowCount() * |
+ detectionResult->getBarcodeColumnCount()); |
+ CFX_PtrArray ambiguousIndexValuesList; |
+ CFX_Int32Array ambiguousIndexesList; |
+ for (int32_t row = 0; row < detectionResult->getBarcodeRowCount(); row++) { |
+ for (int32_t l = 0; l < detectionResult->getBarcodeColumnCount(); l++) { |
+ CFX_Int32Array* values = |
+ ((CBC_BarcodeValue*)((CFX_PtrArray*)barcodeMatrix->GetAt(row)) |
+ ->GetAt(l + 1)) |
+ ->getValue(); |
+ int32_t codewordIndex = |
+ row * detectionResult->getBarcodeColumnCount() + l; |
+ if (values->GetSize() == 0) { |
+ erasures.Add(codewordIndex); |
+ } else if (values->GetSize() == 1) { |
+ codewords[codewordIndex] = values->GetAt(0); |
+ } else { |
+ ambiguousIndexesList.Add(codewordIndex); |
+ ambiguousIndexValuesList.Add(values); |
+ } |
+ } |
+ } |
+ CFX_PtrArray ambiguousIndexValues; |
+ ambiguousIndexValues.SetSize(ambiguousIndexValuesList.GetSize()); |
+ for (int32_t i = 0; i < ambiguousIndexValues.GetSize(); i++) { |
+ ambiguousIndexValues.SetAt(i, ambiguousIndexValuesList.GetAt(i)); |
+ } |
+ for (int32_t l = 0; l < barcodeMatrix->GetSize(); l++) { |
+ CFX_PtrArray* temp = (CFX_PtrArray*)barcodeMatrix->GetAt(l); |
+ for (int32_t j = 0; j < temp->GetSize(); j++) { |
+ delete (CBC_BarcodeValue*)temp->GetAt(j); |
+ } |
+ temp->RemoveAll(); |
+ delete temp; |
+ } |
+ barcodeMatrix->RemoveAll(); |
+ delete barcodeMatrix; |
+ CBC_CommonDecoderResult* decoderResult = |
+ createDecoderResultFromAmbiguousValues( |
+ detectionResult->getBarcodeECLevel(), codewords, erasures, |
+ ambiguousIndexesList, ambiguousIndexValues, e); |
+ BC_EXCEPTION_CHECK_ReturnValue(e, NULL); |
+ return decoderResult; |
+} |
+CBC_CommonDecoderResult* |
+CBC_PDF417ScanningDecoder::createDecoderResultFromAmbiguousValues( |
+ int32_t ecLevel, |
+ CFX_Int32Array& codewords, |
+ CFX_Int32Array& erasureArray, |
+ CFX_Int32Array& ambiguousIndexes, |
+ CFX_PtrArray& ambiguousIndexValues, |
+ int32_t& e) { |
+ CFX_Int32Array ambiguousIndexCount; |
+ ambiguousIndexCount.SetSize(ambiguousIndexes.GetSize()); |
+ int32_t tries = 100; |
+ while (tries-- > 0) { |
+ for (int32_t l = 0; l < ambiguousIndexCount.GetSize(); l++) { |
+ codewords[ambiguousIndexes[l]] = |
+ ((CFX_Int32Array*)ambiguousIndexValues.GetAt(l)) |
+ ->GetAt(ambiguousIndexCount[l]); |
+ } |
+ CBC_CommonDecoderResult* decoderResult = |
+ decodeCodewords(codewords, ecLevel, erasureArray, e); |
+ if (e != BCExceptionNO) { |
+ e = BCExceptionNO; |
+ continue; |
+ } else { |
+ return decoderResult; |
+ } |
+ if (ambiguousIndexCount.GetSize() == 0) { |
+ e = BCExceptionChecksumInstance; |
+ return NULL; |
+ } |
+ for (int32_t i = 0; i < ambiguousIndexCount.GetSize(); i++) { |
+ if (ambiguousIndexCount[i] < |
+ ((CFX_Int32Array*)(ambiguousIndexValues.GetAt(i)))->GetSize() - 1) { |
+ ambiguousIndexCount[i]++; |
+ break; |
+ } else { |
+ ambiguousIndexCount[i] = 0; |
+ if (i == ambiguousIndexCount.GetSize() - 1) { |
+ e = BCExceptionChecksumInstance; |
+ return NULL; |
+ } |
+ } |
+ } |
+ } |
+ e = BCExceptionChecksumInstance; |
+ return NULL; |
+} |
+CFX_PtrArray* CBC_PDF417ScanningDecoder::createBarcodeMatrix( |
+ CBC_DetectionResult* detectionResult) { |
+ CFX_PtrArray* barcodeMatrix = new CFX_PtrArray; |
+ barcodeMatrix->SetSize(detectionResult->getBarcodeRowCount()); |
+ CFX_PtrArray* temp = NULL; |
+ int32_t colume = 0; |
+ for (int32_t row = 0; row < barcodeMatrix->GetSize(); row++) { |
+ temp = new CFX_PtrArray; |
+ temp->SetSize(detectionResult->getBarcodeColumnCount() + 2); |
+ for (colume = 0; colume < detectionResult->getBarcodeColumnCount() + 2; |
+ colume++) { |
+ temp->SetAt(colume, new CBC_BarcodeValue()); |
+ } |
+ barcodeMatrix->SetAt(row, temp); |
+ } |
+ colume = -1; |
+ for (int32_t i = 0; |
+ i < detectionResult->getDetectionResultColumns().GetSize(); i++) { |
+ CBC_DetectionResultColumn* detectionResultColumn = |
+ (CBC_DetectionResultColumn*)detectionResult->getDetectionResultColumns() |
+ .GetAt(i); |
+ colume++; |
+ if (detectionResultColumn == NULL) { |
+ continue; |
+ } |
+ CFX_PtrArray* temp = detectionResultColumn->getCodewords(); |
+ for (int32_t l = 0; l < temp->GetSize(); l++) { |
+ CBC_Codeword* codeword = (CBC_Codeword*)temp->GetAt(l); |
+ if (codeword == NULL || codeword->getRowNumber() == -1) { |
+ continue; |
+ } |
+ ((CBC_BarcodeValue*)((CFX_PtrArray*)barcodeMatrix->GetAt( |
+ codeword->getRowNumber())) |
+ ->GetAt(colume)) |
+ ->setValue(codeword->getValue()); |
+ } |
+ } |
+ return barcodeMatrix; |
+} |
+FX_BOOL CBC_PDF417ScanningDecoder::isValidBarcodeColumn( |
+ CBC_DetectionResult* detectionResult, |
+ int32_t barcodeColumn) { |
+ return barcodeColumn >= 0 && |
+ barcodeColumn <= detectionResult->getBarcodeColumnCount() + 1; |
+} |
+int32_t CBC_PDF417ScanningDecoder::getStartColumn( |
+ CBC_DetectionResult* detectionResult, |
+ int32_t barcodeColumn, |
+ int32_t imageRow, |
+ FX_BOOL leftToRight) { |
+ int32_t offset = leftToRight ? 1 : -1; |
+ CBC_Codeword* codeword = NULL; |
+ if (isValidBarcodeColumn(detectionResult, barcodeColumn - offset)) { |
+ codeword = detectionResult->getDetectionResultColumn(barcodeColumn - offset) |
+ ->getCodeword(imageRow); |
+ } |
+ if (codeword != NULL) { |
+ return leftToRight ? codeword->getEndX() : codeword->getStartX(); |
+ } |
+ codeword = detectionResult->getDetectionResultColumn(barcodeColumn) |
+ ->getCodewordNearby(imageRow); |
+ if (codeword != NULL) { |
+ return leftToRight ? codeword->getStartX() : codeword->getEndX(); |
+ } |
+ if (isValidBarcodeColumn(detectionResult, barcodeColumn - offset)) { |
+ codeword = detectionResult->getDetectionResultColumn(barcodeColumn - offset) |
+ ->getCodewordNearby(imageRow); |
+ } |
+ if (codeword != NULL) { |
+ return leftToRight ? codeword->getEndX() : codeword->getStartX(); |
+ } |
+ int32_t skippedColumns = 0; |
+ while (isValidBarcodeColumn(detectionResult, barcodeColumn - offset)) { |
+ barcodeColumn -= offset; |
+ for (int32_t i = 0; |
+ i < detectionResult->getDetectionResultColumn(barcodeColumn) |
+ ->getCodewords() |
+ ->GetSize(); |
+ i++) { |
+ CBC_Codeword* previousRowCodeword = |
+ (CBC_Codeword*)detectionResult->getDetectionResultColumn( |
+ barcodeColumn) |
+ ->getCodewords() |
+ ->GetAt(i); |
+ if (previousRowCodeword != NULL) { |
+ return (leftToRight ? previousRowCodeword->getEndX() |
+ : previousRowCodeword->getStartX()) + |
+ offset * skippedColumns * (previousRowCodeword->getEndX() - |
+ previousRowCodeword->getStartX()); |
+ } |
+ } |
+ skippedColumns++; |
+ } |
+ return leftToRight ? detectionResult->getBoundingBox()->getMinX() |
+ : detectionResult->getBoundingBox()->getMaxX(); |
+} |
+CBC_Codeword* CBC_PDF417ScanningDecoder::detectCodeword( |
+ CBC_CommonBitMatrix* image, |
+ int32_t minColumn, |
+ int32_t maxColumn, |
+ FX_BOOL leftToRight, |
+ int32_t startColumn, |
+ int32_t imageRow, |
+ int32_t minCodewordWidth, |
+ int32_t maxCodewordWidth) { |
+ startColumn = adjustCodewordStartColumn(image, minColumn, maxColumn, |
+ leftToRight, startColumn, imageRow); |
+ CFX_Int32Array* moduleBitCount = getModuleBitCount( |
+ image, minColumn, maxColumn, leftToRight, startColumn, imageRow); |
+ if (moduleBitCount == NULL) { |
+ return NULL; |
+ } |
+ int32_t endColumn; |
+ int32_t codewordBitCount = CBC_PDF417Common::getBitCountSum(*moduleBitCount); |
+ if (leftToRight) { |
+ endColumn = startColumn + codewordBitCount; |
+ } else { |
+ for (int32_t i = 0; i<moduleBitCount->GetSize()>> 1; i++) { |
+ int32_t tmpCount = moduleBitCount->GetAt(i); |
+ moduleBitCount->SetAt( |
+ i, moduleBitCount->GetAt(moduleBitCount->GetSize() - 1 - i)); |
+ moduleBitCount->SetAt(moduleBitCount->GetSize() - 1 - i, tmpCount); |
+ } |
+ endColumn = startColumn; |
+ startColumn = endColumn - codewordBitCount; |
+ } |
+ int32_t decodedValue = |
+ CBC_PDF417CodewordDecoder::getDecodedValue(*moduleBitCount); |
+ int32_t codeword = CBC_PDF417Common::getCodeword(decodedValue); |
+ delete moduleBitCount; |
+ if (codeword == -1) { |
+ return NULL; |
+ } |
+ return new CBC_Codeword(startColumn, endColumn, |
+ getCodewordBucketNumber(decodedValue), codeword); |
+} |
+CFX_Int32Array* CBC_PDF417ScanningDecoder::getModuleBitCount( |
+ CBC_CommonBitMatrix* image, |
+ int32_t minColumn, |
+ int32_t maxColumn, |
+ FX_BOOL leftToRight, |
+ int32_t startColumn, |
+ int32_t imageRow) { |
+ int32_t imageColumn = startColumn; |
+ CFX_Int32Array* moduleBitCount = new CFX_Int32Array; |
+ moduleBitCount->SetSize(8); |
+ int32_t moduleNumber = 0; |
+ int32_t increment = leftToRight ? 1 : -1; |
+ FX_BOOL previousPixelValue = leftToRight; |
+ while (((leftToRight && imageColumn < maxColumn) || |
+ (!leftToRight && imageColumn >= minColumn)) && |
+ moduleNumber < moduleBitCount->GetSize()) { |
+ if (image->Get(imageColumn, imageRow) == previousPixelValue) { |
+ moduleBitCount->SetAt(moduleNumber, |
+ moduleBitCount->GetAt(moduleNumber) + 1); |
+ imageColumn += increment; |
+ } else { |
+ moduleNumber++; |
+ previousPixelValue = !previousPixelValue; |
+ } |
+ } |
+ if (moduleNumber == moduleBitCount->GetSize() || |
+ (((leftToRight && imageColumn == maxColumn) || |
+ (!leftToRight && imageColumn == minColumn)) && |
+ moduleNumber == moduleBitCount->GetSize() - 1)) { |
+ return moduleBitCount; |
+ } |
+ delete moduleBitCount; |
+ return NULL; |
+} |
+int32_t CBC_PDF417ScanningDecoder::getNumberOfECCodeWords( |
+ int32_t barcodeECLevel) { |
+ return 2 << barcodeECLevel; |
+} |
+int32_t CBC_PDF417ScanningDecoder::adjustCodewordStartColumn( |
+ CBC_CommonBitMatrix* image, |
+ int32_t minColumn, |
+ int32_t maxColumn, |
+ FX_BOOL leftToRight, |
+ int32_t codewordStartColumn, |
+ int32_t imageRow) { |
+ int32_t correctedStartColumn = codewordStartColumn; |
+ int32_t increment = leftToRight ? -1 : 1; |
+ for (int32_t i = 0; i < 2; i++) { |
+ while (((leftToRight && correctedStartColumn >= minColumn) || |
+ (!leftToRight && correctedStartColumn < maxColumn)) && |
+ leftToRight == image->Get(correctedStartColumn, imageRow)) { |
+ if (abs(codewordStartColumn - correctedStartColumn) > |
+ CODEWORD_SKEW_SIZE) { |
+ return codewordStartColumn; |
+ } |
+ correctedStartColumn += increment; |
+ } |
+ increment = -increment; |
+ leftToRight = !leftToRight; |
+ } |
+ return correctedStartColumn; |
+} |
+FX_BOOL CBC_PDF417ScanningDecoder::checkCodewordSkew(int32_t codewordSize, |
+ int32_t minCodewordWidth, |
+ int32_t maxCodewordWidth) { |
+ return minCodewordWidth - CODEWORD_SKEW_SIZE <= codewordSize && |
+ codewordSize <= maxCodewordWidth + CODEWORD_SKEW_SIZE; |
+} |
+CBC_CommonDecoderResult* CBC_PDF417ScanningDecoder::decodeCodewords( |
+ CFX_Int32Array& codewords, |
+ int32_t ecLevel, |
+ CFX_Int32Array& erasures, |
+ int32_t& e) { |
+ if (codewords.GetSize() == 0) { |
+ e = BCExceptionFormatInstance; |
+ return NULL; |
+ } |
+ int32_t numECCodewords = 1 << (ecLevel + 1); |
+ correctErrors(codewords, erasures, numECCodewords, e); |
+ BC_EXCEPTION_CHECK_ReturnValue(e, NULL); |
+ verifyCodewordCount(codewords, numECCodewords, e); |
+ BC_EXCEPTION_CHECK_ReturnValue(e, NULL); |
+ CFX_ByteString bytestring; |
+ CBC_CommonDecoderResult* decoderResult = CBC_DecodedBitStreamPaser::decode( |
+ codewords, bytestring.FormatInteger(ecLevel), e); |
+ BC_EXCEPTION_CHECK_ReturnValue(e, NULL); |
+ return decoderResult; |
+} |
+int32_t CBC_PDF417ScanningDecoder::correctErrors(CFX_Int32Array& codewords, |
+ CFX_Int32Array& erasures, |
+ int32_t numECCodewords, |
+ int32_t& e) { |
+ if ((erasures.GetSize() != 0 && |
+ erasures.GetSize() > (numECCodewords / 2 + MAX_ERRORS)) || |
+ numECCodewords < 0 || numECCodewords > MAX_EC_CODEWORDS) { |
+ e = BCExceptionChecksumInstance; |
+ return -1; |
+ } |
+ int32_t result = CBC_PDF417ECErrorCorrection::decode( |
+ codewords, numECCodewords, erasures, e); |
+ BC_EXCEPTION_CHECK_ReturnValue(e, -1); |
+ return result; |
+} |
+void CBC_PDF417ScanningDecoder::verifyCodewordCount(CFX_Int32Array& codewords, |
+ int32_t numECCodewords, |
+ int32_t& e) { |
+ if (codewords.GetSize() < 4) { |
+ e = BCExceptionFormatInstance; |
+ return; |
+ } |
+ int32_t numberOfCodewords = codewords.GetAt(0); |
+ if (numberOfCodewords > codewords.GetSize()) { |
+ e = BCExceptionFormatInstance; |
+ return; |
+ } |
+ if (numberOfCodewords == 0) { |
+ if (numECCodewords < codewords.GetSize()) { |
+ codewords[0] = codewords.GetSize() - numECCodewords; |
+ } else { |
+ e = BCExceptionFormatInstance; |
+ return; |
+ } |
+ } |
+} |
+CFX_Int32Array* CBC_PDF417ScanningDecoder::getBitCountForCodeword( |
+ int32_t codeword) { |
+ CFX_Int32Array* result = new CFX_Int32Array; |
+ result->SetSize(8); |
+ int32_t previousValue = 0; |
+ int32_t i = result->GetSize() - 1; |
+ while (TRUE) { |
+ if ((codeword & 0x1) != previousValue) { |
+ previousValue = codeword & 0x1; |
+ i--; |
+ if (i < 0) { |
+ break; |
+ } |
+ } |
+ result->SetAt(i, result->GetAt(i) + 1); |
+ codeword >>= 1; |
+ } |
+ return result; |
+} |
+int32_t CBC_PDF417ScanningDecoder::getCodewordBucketNumber(int32_t codeword) { |
+ CFX_Int32Array* array = getBitCountForCodeword(codeword); |
+ int32_t result = getCodewordBucketNumber(*array); |
+ delete array; |
+ return result; |
+} |
+int32_t CBC_PDF417ScanningDecoder::getCodewordBucketNumber( |
+ CFX_Int32Array& moduleBitCount) { |
+ return (moduleBitCount.GetAt(0) - moduleBitCount.GetAt(2) + |
+ moduleBitCount.GetAt(4) - moduleBitCount.GetAt(6) + 9) % |
+ 9; |
+} |