| OLD | NEW |
| (Empty) |
| 1 // Copyright 2014 PDFium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | |
| 6 // Original code is licensed as follows: | |
| 7 /* | |
| 8 * Copyright 2013 ZXing authors | |
| 9 * | |
| 10 * Licensed under the Apache License, Version 2.0 (the "License"); | |
| 11 * you may not use this file except in compliance with the License. | |
| 12 * You may obtain a copy of the License at | |
| 13 * | |
| 14 * http://www.apache.org/licenses/LICENSE-2.0 | |
| 15 * | |
| 16 * Unless required by applicable law or agreed to in writing, software | |
| 17 * distributed under the License is distributed on an "AS IS" BASIS, | |
| 18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 19 * See the License for the specific language governing permissions and | |
| 20 * limitations under the License. | |
| 21 */ | |
| 22 | |
| 23 #include "xfa/src/fxbarcode/BC_DecoderResult.h" | |
| 24 #include "xfa/src/fxbarcode/BC_ResultPoint.h" | |
| 25 #include "xfa/src/fxbarcode/common/BC_CommonBitMatrix.h" | |
| 26 #include "xfa/src/fxbarcode/pdf417/BC_PDF417BarcodeMetadata.h" | |
| 27 #include "xfa/src/fxbarcode/pdf417/BC_PDF417BarcodeValue.h" | |
| 28 #include "xfa/src/fxbarcode/pdf417/BC_PDF417BoundingBox.h" | |
| 29 #include "xfa/src/fxbarcode/pdf417/BC_PDF417Codeword.h" | |
| 30 #include "xfa/src/fxbarcode/pdf417/BC_PDF417CodewordDecoder.h" | |
| 31 #include "xfa/src/fxbarcode/pdf417/BC_PDF417Common.h" | |
| 32 #include "xfa/src/fxbarcode/pdf417/BC_PDF417DecodedBitStreamParser.h" | |
| 33 #include "xfa/src/fxbarcode/pdf417/BC_PDF417DecodedBitStreamParser.h" | |
| 34 #include "xfa/src/fxbarcode/pdf417/BC_PDF417DecodedBitStreamParser.h" | |
| 35 #include "xfa/src/fxbarcode/pdf417/BC_PDF417DetectionResult.h" | |
| 36 #include "xfa/src/fxbarcode/pdf417/BC_PDF417DetectionResultColumn.h" | |
| 37 #include "xfa/src/fxbarcode/pdf417/BC_PDF417DetectionResultRowIndicatorColumn.h" | |
| 38 #include "xfa/src/fxbarcode/pdf417/BC_PDF417ECErrorCorrection.h" | |
| 39 #include "xfa/src/fxbarcode/pdf417/BC_PDF417ECModulusGF.h" | |
| 40 #include "xfa/src/fxbarcode/pdf417/BC_PDF417ECModulusPoly.h" | |
| 41 #include "xfa/src/fxbarcode/pdf417/BC_PDF417ScanningDecoder.h" | |
| 42 #include "xfa/src/fxbarcode/utils.h" | |
| 43 | |
| 44 int32_t CBC_PDF417ScanningDecoder::CODEWORD_SKEW_SIZE = 2; | |
| 45 int32_t CBC_PDF417ScanningDecoder::MAX_ERRORS = 3; | |
| 46 int32_t CBC_PDF417ScanningDecoder::MAX_EC_CODEWORDS = 512; | |
| 47 CBC_PDF417ECErrorCorrection* CBC_PDF417ScanningDecoder::errorCorrection = NULL; | |
| 48 | |
| 49 CBC_PDF417ScanningDecoder::CBC_PDF417ScanningDecoder() {} | |
| 50 CBC_PDF417ScanningDecoder::~CBC_PDF417ScanningDecoder() {} | |
| 51 void CBC_PDF417ScanningDecoder::Initialize() { | |
| 52 errorCorrection = new CBC_PDF417ECErrorCorrection; | |
| 53 } | |
| 54 void CBC_PDF417ScanningDecoder::Finalize() { | |
| 55 delete errorCorrection; | |
| 56 } | |
| 57 CBC_CommonDecoderResult* CBC_PDF417ScanningDecoder::decode( | |
| 58 CBC_CommonBitMatrix* image, | |
| 59 CBC_ResultPoint* imageTopLeft, | |
| 60 CBC_ResultPoint* imageBottomLeft, | |
| 61 CBC_ResultPoint* imageTopRight, | |
| 62 CBC_ResultPoint* imageBottomRight, | |
| 63 int32_t minCodewordWidth, | |
| 64 int32_t maxCodewordWidth, | |
| 65 int32_t& e) { | |
| 66 CBC_BoundingBox* boundingBox = new CBC_BoundingBox( | |
| 67 image, imageTopLeft, imageBottomLeft, imageTopRight, imageBottomRight, e); | |
| 68 BC_EXCEPTION_CHECK_ReturnValue(e, NULL); | |
| 69 CBC_DetectionResultRowIndicatorColumn* leftRowIndicatorColumn = NULL; | |
| 70 CBC_DetectionResultRowIndicatorColumn* rightRowIndicatorColumn = NULL; | |
| 71 CBC_DetectionResult* detectionResult = NULL; | |
| 72 for (int32_t i = 0; i < 2; i++) { | |
| 73 if (imageTopLeft) { | |
| 74 leftRowIndicatorColumn = | |
| 75 getRowIndicatorColumn(image, boundingBox, *imageTopLeft, TRUE, | |
| 76 minCodewordWidth, maxCodewordWidth); | |
| 77 } | |
| 78 if (imageTopRight) { | |
| 79 rightRowIndicatorColumn = | |
| 80 getRowIndicatorColumn(image, boundingBox, *imageTopRight, FALSE, | |
| 81 minCodewordWidth, maxCodewordWidth); | |
| 82 } | |
| 83 detectionResult = merge(leftRowIndicatorColumn, rightRowIndicatorColumn, e); | |
| 84 if (e != BCExceptionNO) { | |
| 85 e = BCExceptiontNotFoundInstance; | |
| 86 delete leftRowIndicatorColumn; | |
| 87 delete rightRowIndicatorColumn; | |
| 88 delete boundingBox; | |
| 89 return NULL; | |
| 90 } | |
| 91 if (i == 0 && (detectionResult->getBoundingBox()->getMinY() < | |
| 92 boundingBox->getMinY() || | |
| 93 detectionResult->getBoundingBox()->getMaxY() > | |
| 94 boundingBox->getMaxY())) { | |
| 95 delete boundingBox; | |
| 96 boundingBox = detectionResult->getBoundingBox(); | |
| 97 } else { | |
| 98 detectionResult->setBoundingBox(boundingBox); | |
| 99 break; | |
| 100 } | |
| 101 } | |
| 102 int32_t maxBarcodeColumn = detectionResult->getBarcodeColumnCount() + 1; | |
| 103 detectionResult->setDetectionResultColumn(0, leftRowIndicatorColumn); | |
| 104 detectionResult->setDetectionResultColumn(maxBarcodeColumn, | |
| 105 rightRowIndicatorColumn); | |
| 106 FX_BOOL leftToRight = leftRowIndicatorColumn != NULL; | |
| 107 for (int32_t barcodeColumnCount = 1; barcodeColumnCount <= maxBarcodeColumn; | |
| 108 barcodeColumnCount++) { | |
| 109 int32_t barcodeColumn = leftToRight ? barcodeColumnCount | |
| 110 : maxBarcodeColumn - barcodeColumnCount; | |
| 111 if (detectionResult->getDetectionResultColumn(barcodeColumn)) { | |
| 112 continue; | |
| 113 } | |
| 114 CBC_DetectionResultColumn* detectionResultColumn = NULL; | |
| 115 if (barcodeColumn == 0 || barcodeColumn == maxBarcodeColumn) { | |
| 116 detectionResultColumn = new CBC_DetectionResultRowIndicatorColumn( | |
| 117 boundingBox, barcodeColumn == 0); | |
| 118 } else { | |
| 119 detectionResultColumn = new CBC_DetectionResultColumn(boundingBox); | |
| 120 } | |
| 121 detectionResult->setDetectionResultColumn(barcodeColumn, | |
| 122 detectionResultColumn); | |
| 123 int32_t startColumn = -1; | |
| 124 int32_t previousStartColumn = startColumn; | |
| 125 for (int32_t imageRow = boundingBox->getMinY(); | |
| 126 imageRow <= boundingBox->getMaxY(); imageRow++) { | |
| 127 startColumn = | |
| 128 getStartColumn(detectionResult, barcodeColumn, imageRow, leftToRight); | |
| 129 if (startColumn < 0 || startColumn > boundingBox->getMaxX()) { | |
| 130 if (previousStartColumn == -1) { | |
| 131 continue; | |
| 132 } | |
| 133 startColumn = previousStartColumn; | |
| 134 } | |
| 135 CBC_Codeword* codeword = detectCodeword( | |
| 136 image, boundingBox->getMinX(), boundingBox->getMaxX(), leftToRight, | |
| 137 startColumn, imageRow, minCodewordWidth, maxCodewordWidth); | |
| 138 if (codeword) { | |
| 139 detectionResultColumn->setCodeword(imageRow, codeword); | |
| 140 previousStartColumn = startColumn; | |
| 141 minCodewordWidth = minCodewordWidth < codeword->getWidth() | |
| 142 ? minCodewordWidth | |
| 143 : codeword->getWidth(); | |
| 144 maxCodewordWidth = maxCodewordWidth > codeword->getWidth() | |
| 145 ? maxCodewordWidth | |
| 146 : codeword->getWidth(); | |
| 147 } | |
| 148 } | |
| 149 } | |
| 150 CBC_CommonDecoderResult* decoderresult = | |
| 151 createDecoderResult(detectionResult, e); | |
| 152 if (e != BCExceptionNO) { | |
| 153 delete detectionResult; | |
| 154 return NULL; | |
| 155 } | |
| 156 return decoderresult; | |
| 157 } | |
| 158 CFX_ByteString CBC_PDF417ScanningDecoder::toString( | |
| 159 CFX_PtrArray* barcodeMatrix) { | |
| 160 CFX_ByteString result; | |
| 161 for (int32_t row = 0; row < barcodeMatrix->GetSize(); row++) { | |
| 162 result += row; | |
| 163 int32_t l = 0; | |
| 164 for (; l < ((CFX_PtrArray*)barcodeMatrix->GetAt(row))->GetSize(); l++) { | |
| 165 CBC_BarcodeValue* barcodeValue = | |
| 166 (CBC_BarcodeValue*)((CFX_PtrArray*)barcodeMatrix->GetAt(row)) | |
| 167 ->GetAt(l); | |
| 168 if (barcodeValue->getValue()->GetSize() == 0) { | |
| 169 result += ""; | |
| 170 } else { | |
| 171 result += barcodeValue->getValue()->GetAt(0); | |
| 172 result += | |
| 173 barcodeValue->getConfidence(barcodeValue->getValue()->GetAt(0)); | |
| 174 } | |
| 175 } | |
| 176 } | |
| 177 return result; | |
| 178 } | |
| 179 CBC_DetectionResult* CBC_PDF417ScanningDecoder::merge( | |
| 180 CBC_DetectionResultRowIndicatorColumn* leftRowIndicatorColumn, | |
| 181 CBC_DetectionResultRowIndicatorColumn* rightRowIndicatorColumn, | |
| 182 int32_t& e) { | |
| 183 if (leftRowIndicatorColumn == NULL && rightRowIndicatorColumn == NULL) { | |
| 184 e = BCExceptionIllegalArgument; | |
| 185 return NULL; | |
| 186 } | |
| 187 CBC_BarcodeMetadata* barcodeMetadata = | |
| 188 getBarcodeMetadata(leftRowIndicatorColumn, rightRowIndicatorColumn); | |
| 189 if (barcodeMetadata == NULL) { | |
| 190 e = BCExceptionCannotMetadata; | |
| 191 return NULL; | |
| 192 } | |
| 193 CBC_BoundingBox* leftboundingBox = | |
| 194 adjustBoundingBox(leftRowIndicatorColumn, e); | |
| 195 if (e != BCExceptionNO) { | |
| 196 delete barcodeMetadata; | |
| 197 return NULL; | |
| 198 } | |
| 199 CBC_BoundingBox* rightboundingBox = | |
| 200 adjustBoundingBox(rightRowIndicatorColumn, e); | |
| 201 if (e != BCExceptionNO) { | |
| 202 delete barcodeMetadata; | |
| 203 return NULL; | |
| 204 } | |
| 205 CBC_BoundingBox* boundingBox = | |
| 206 CBC_BoundingBox::merge(leftboundingBox, rightboundingBox, e); | |
| 207 if (e != BCExceptionNO) { | |
| 208 delete barcodeMetadata; | |
| 209 return NULL; | |
| 210 } | |
| 211 CBC_DetectionResult* detectionresult = | |
| 212 new CBC_DetectionResult(barcodeMetadata, boundingBox); | |
| 213 return detectionresult; | |
| 214 } | |
| 215 CBC_BoundingBox* CBC_PDF417ScanningDecoder::adjustBoundingBox( | |
| 216 CBC_DetectionResultRowIndicatorColumn* rowIndicatorColumn, | |
| 217 int32_t& e) { | |
| 218 if (rowIndicatorColumn == NULL) { | |
| 219 return NULL; | |
| 220 } | |
| 221 CFX_Int32Array* rowHeights = rowIndicatorColumn->getRowHeights(e); | |
| 222 BC_EXCEPTION_CHECK_ReturnValue(e, NULL); | |
| 223 int32_t maxRowHeight = getMax(*rowHeights); | |
| 224 int32_t missingStartRows = 0; | |
| 225 for (int32_t i = 0; i < rowHeights->GetSize(); i++) { | |
| 226 int32_t rowHeight = rowHeights->GetAt(i); | |
| 227 missingStartRows += maxRowHeight - rowHeight; | |
| 228 if (rowHeight > 0) { | |
| 229 break; | |
| 230 } | |
| 231 } | |
| 232 CFX_PtrArray* codewords = rowIndicatorColumn->getCodewords(); | |
| 233 for (int32_t row = 0; missingStartRows > 0 && codewords->GetAt(row) == NULL; | |
| 234 row++) { | |
| 235 missingStartRows--; | |
| 236 } | |
| 237 int32_t missingEndRows = 0; | |
| 238 for (int32_t row1 = rowHeights->GetSize() - 1; row1 >= 0; row1--) { | |
| 239 missingEndRows += maxRowHeight - rowHeights->GetAt(row1); | |
| 240 if (rowHeights->GetAt(row1) > 0) { | |
| 241 break; | |
| 242 } | |
| 243 } | |
| 244 for (int32_t row2 = codewords->GetSize() - 1; | |
| 245 missingEndRows > 0 && codewords->GetAt(row2) == NULL; row2--) { | |
| 246 missingEndRows--; | |
| 247 } | |
| 248 CBC_BoundingBox* boundingBox = | |
| 249 rowIndicatorColumn->getBoundingBox()->addMissingRows( | |
| 250 missingStartRows, missingEndRows, rowIndicatorColumn->isLeft(), e); | |
| 251 BC_EXCEPTION_CHECK_ReturnValue(e, NULL); | |
| 252 return boundingBox; | |
| 253 } | |
| 254 int32_t CBC_PDF417ScanningDecoder::getMax(CFX_Int32Array& values) { | |
| 255 int32_t maxValue = -1; | |
| 256 for (int32_t i = 0; i < values.GetSize(); i++) { | |
| 257 int32_t value = values.GetAt(i); | |
| 258 maxValue = maxValue > value ? maxValue : value; | |
| 259 } | |
| 260 return maxValue; | |
| 261 } | |
| 262 CBC_BarcodeMetadata* CBC_PDF417ScanningDecoder::getBarcodeMetadata( | |
| 263 CBC_DetectionResultRowIndicatorColumn* leftRowIndicatorColumn, | |
| 264 CBC_DetectionResultRowIndicatorColumn* rightRowIndicatorColumn) { | |
| 265 CBC_BarcodeMetadata* leftBarcodeMetadata = NULL; | |
| 266 CBC_BarcodeMetadata* rightBarcodeMetadata = NULL; | |
| 267 if (leftRowIndicatorColumn == NULL || | |
| 268 (leftBarcodeMetadata = leftRowIndicatorColumn->getBarcodeMetadata()) == | |
| 269 NULL) { | |
| 270 return rightRowIndicatorColumn == NULL | |
| 271 ? NULL | |
| 272 : rightRowIndicatorColumn->getBarcodeMetadata(); | |
| 273 } | |
| 274 if (rightRowIndicatorColumn == NULL || | |
| 275 (rightBarcodeMetadata = rightRowIndicatorColumn->getBarcodeMetadata()) == | |
| 276 NULL) { | |
| 277 return leftRowIndicatorColumn == NULL | |
| 278 ? NULL | |
| 279 : leftRowIndicatorColumn->getBarcodeMetadata(); | |
| 280 } | |
| 281 if (leftBarcodeMetadata->getColumnCount() != | |
| 282 rightBarcodeMetadata->getColumnCount() && | |
| 283 leftBarcodeMetadata->getErrorCorrectionLevel() != | |
| 284 rightBarcodeMetadata->getErrorCorrectionLevel() && | |
| 285 leftBarcodeMetadata->getRowCount() != | |
| 286 rightBarcodeMetadata->getRowCount()) { | |
| 287 delete leftBarcodeMetadata; | |
| 288 delete rightBarcodeMetadata; | |
| 289 return NULL; | |
| 290 } | |
| 291 delete rightBarcodeMetadata; | |
| 292 return leftBarcodeMetadata; | |
| 293 } | |
| 294 CBC_DetectionResultRowIndicatorColumn* | |
| 295 CBC_PDF417ScanningDecoder::getRowIndicatorColumn(CBC_CommonBitMatrix* image, | |
| 296 CBC_BoundingBox* boundingBox, | |
| 297 CBC_ResultPoint startPoint, | |
| 298 FX_BOOL leftToRight, | |
| 299 int32_t minCodewordWidth, | |
| 300 int32_t maxCodewordWidth) { | |
| 301 CBC_DetectionResultRowIndicatorColumn* rowIndicatorColumn = | |
| 302 new CBC_DetectionResultRowIndicatorColumn(boundingBox, leftToRight); | |
| 303 for (int32_t i = 0; i < 2; i++) { | |
| 304 int32_t increment = i == 0 ? 1 : -1; | |
| 305 int32_t startColumn = (int32_t)startPoint.GetX(); | |
| 306 for (int32_t imageRow = (int32_t)startPoint.GetY(); | |
| 307 imageRow <= boundingBox->getMaxY() && | |
| 308 imageRow >= boundingBox->getMinY(); | |
| 309 imageRow += increment) { | |
| 310 CBC_Codeword* codeword = | |
| 311 detectCodeword(image, 0, image->GetWidth(), leftToRight, startColumn, | |
| 312 imageRow, minCodewordWidth, maxCodewordWidth); | |
| 313 if (codeword) { | |
| 314 rowIndicatorColumn->setCodeword(imageRow, codeword); | |
| 315 if (leftToRight) { | |
| 316 startColumn = codeword->getStartX(); | |
| 317 } else { | |
| 318 startColumn = codeword->getEndX(); | |
| 319 } | |
| 320 } | |
| 321 } | |
| 322 } | |
| 323 return rowIndicatorColumn; | |
| 324 } | |
| 325 void CBC_PDF417ScanningDecoder::adjustCodewordCount( | |
| 326 CBC_DetectionResult* detectionResult, | |
| 327 CFX_PtrArray* barcodeMatrix, | |
| 328 int32_t& e) { | |
| 329 CFX_Int32Array* numberOfCodewords = | |
| 330 ((CBC_BarcodeValue*)((CFX_PtrArray*)barcodeMatrix->GetAt(0))->GetAt(1)) | |
| 331 ->getValue(); | |
| 332 int32_t calculatedNumberOfCodewords = | |
| 333 detectionResult->getBarcodeColumnCount() * | |
| 334 detectionResult->getBarcodeRowCount() - | |
| 335 getNumberOfECCodeWords(detectionResult->getBarcodeECLevel()); | |
| 336 if (numberOfCodewords->GetSize() == 0) { | |
| 337 if (calculatedNumberOfCodewords < 1 || | |
| 338 calculatedNumberOfCodewords > | |
| 339 CBC_PDF417Common::MAX_CODEWORDS_IN_BARCODE) { | |
| 340 e = BCExceptiontNotFoundInstance; | |
| 341 delete numberOfCodewords; | |
| 342 BC_EXCEPTION_CHECK_ReturnVoid(e); | |
| 343 } | |
| 344 ((CBC_BarcodeValue*)((CFX_PtrArray*)barcodeMatrix->GetAt(0))->GetAt(1)) | |
| 345 ->setValue(calculatedNumberOfCodewords); | |
| 346 } else if (numberOfCodewords->GetAt(0) != calculatedNumberOfCodewords) { | |
| 347 ((CBC_BarcodeValue*)((CFX_PtrArray*)barcodeMatrix->GetAt(0))->GetAt(1)) | |
| 348 ->setValue(calculatedNumberOfCodewords); | |
| 349 } | |
| 350 delete numberOfCodewords; | |
| 351 } | |
| 352 CBC_CommonDecoderResult* CBC_PDF417ScanningDecoder::createDecoderResult( | |
| 353 CBC_DetectionResult* detectionResult, | |
| 354 int32_t& e) { | |
| 355 CFX_PtrArray* barcodeMatrix = createBarcodeMatrix(detectionResult); | |
| 356 adjustCodewordCount(detectionResult, barcodeMatrix, e); | |
| 357 if (e != BCExceptionNO) { | |
| 358 for (int32_t i = 0; i < barcodeMatrix->GetSize(); i++) { | |
| 359 CFX_PtrArray* temp = (CFX_PtrArray*)barcodeMatrix->GetAt(i); | |
| 360 for (int32_t j = 0; j < temp->GetSize(); j++) { | |
| 361 delete (CBC_BarcodeValue*)temp->GetAt(j); | |
| 362 } | |
| 363 temp->RemoveAll(); | |
| 364 delete temp; | |
| 365 } | |
| 366 barcodeMatrix->RemoveAll(); | |
| 367 delete barcodeMatrix; | |
| 368 return NULL; | |
| 369 } | |
| 370 CFX_Int32Array erasures; | |
| 371 CFX_Int32Array codewords; | |
| 372 codewords.SetSize(detectionResult->getBarcodeRowCount() * | |
| 373 detectionResult->getBarcodeColumnCount()); | |
| 374 CFX_PtrArray ambiguousIndexValuesList; | |
| 375 CFX_Int32Array ambiguousIndexesList; | |
| 376 for (int32_t row = 0; row < detectionResult->getBarcodeRowCount(); row++) { | |
| 377 for (int32_t l = 0; l < detectionResult->getBarcodeColumnCount(); l++) { | |
| 378 CFX_Int32Array* values = | |
| 379 ((CBC_BarcodeValue*)((CFX_PtrArray*)barcodeMatrix->GetAt(row)) | |
| 380 ->GetAt(l + 1)) | |
| 381 ->getValue(); | |
| 382 int32_t codewordIndex = | |
| 383 row * detectionResult->getBarcodeColumnCount() + l; | |
| 384 if (values->GetSize() == 0) { | |
| 385 erasures.Add(codewordIndex); | |
| 386 } else if (values->GetSize() == 1) { | |
| 387 codewords[codewordIndex] = values->GetAt(0); | |
| 388 } else { | |
| 389 ambiguousIndexesList.Add(codewordIndex); | |
| 390 ambiguousIndexValuesList.Add(values); | |
| 391 } | |
| 392 } | |
| 393 } | |
| 394 CFX_PtrArray ambiguousIndexValues; | |
| 395 ambiguousIndexValues.SetSize(ambiguousIndexValuesList.GetSize()); | |
| 396 for (int32_t i = 0; i < ambiguousIndexValues.GetSize(); i++) { | |
| 397 ambiguousIndexValues.SetAt(i, ambiguousIndexValuesList.GetAt(i)); | |
| 398 } | |
| 399 for (int32_t l = 0; l < barcodeMatrix->GetSize(); l++) { | |
| 400 CFX_PtrArray* temp = (CFX_PtrArray*)barcodeMatrix->GetAt(l); | |
| 401 for (int32_t j = 0; j < temp->GetSize(); j++) { | |
| 402 delete (CBC_BarcodeValue*)temp->GetAt(j); | |
| 403 } | |
| 404 temp->RemoveAll(); | |
| 405 delete temp; | |
| 406 } | |
| 407 barcodeMatrix->RemoveAll(); | |
| 408 delete barcodeMatrix; | |
| 409 CBC_CommonDecoderResult* decoderResult = | |
| 410 createDecoderResultFromAmbiguousValues( | |
| 411 detectionResult->getBarcodeECLevel(), codewords, erasures, | |
| 412 ambiguousIndexesList, ambiguousIndexValues, e); | |
| 413 BC_EXCEPTION_CHECK_ReturnValue(e, NULL); | |
| 414 return decoderResult; | |
| 415 } | |
| 416 CBC_CommonDecoderResult* | |
| 417 CBC_PDF417ScanningDecoder::createDecoderResultFromAmbiguousValues( | |
| 418 int32_t ecLevel, | |
| 419 CFX_Int32Array& codewords, | |
| 420 CFX_Int32Array& erasureArray, | |
| 421 CFX_Int32Array& ambiguousIndexes, | |
| 422 CFX_PtrArray& ambiguousIndexValues, | |
| 423 int32_t& e) { | |
| 424 CFX_Int32Array ambiguousIndexCount; | |
| 425 ambiguousIndexCount.SetSize(ambiguousIndexes.GetSize()); | |
| 426 int32_t tries = 100; | |
| 427 while (tries-- > 0) { | |
| 428 for (int32_t l = 0; l < ambiguousIndexCount.GetSize(); l++) { | |
| 429 codewords[ambiguousIndexes[l]] = | |
| 430 ((CFX_Int32Array*)ambiguousIndexValues.GetAt(l)) | |
| 431 ->GetAt(ambiguousIndexCount[l]); | |
| 432 } | |
| 433 CBC_CommonDecoderResult* decoderResult = | |
| 434 decodeCodewords(codewords, ecLevel, erasureArray, e); | |
| 435 if (e != BCExceptionNO) { | |
| 436 e = BCExceptionNO; | |
| 437 continue; | |
| 438 } else { | |
| 439 return decoderResult; | |
| 440 } | |
| 441 if (ambiguousIndexCount.GetSize() == 0) { | |
| 442 e = BCExceptionChecksumInstance; | |
| 443 return NULL; | |
| 444 } | |
| 445 for (int32_t i = 0; i < ambiguousIndexCount.GetSize(); i++) { | |
| 446 if (ambiguousIndexCount[i] < | |
| 447 ((CFX_Int32Array*)(ambiguousIndexValues.GetAt(i)))->GetSize() - 1) { | |
| 448 ambiguousIndexCount[i]++; | |
| 449 break; | |
| 450 } else { | |
| 451 ambiguousIndexCount[i] = 0; | |
| 452 if (i == ambiguousIndexCount.GetSize() - 1) { | |
| 453 e = BCExceptionChecksumInstance; | |
| 454 return NULL; | |
| 455 } | |
| 456 } | |
| 457 } | |
| 458 } | |
| 459 e = BCExceptionChecksumInstance; | |
| 460 return NULL; | |
| 461 } | |
| 462 CFX_PtrArray* CBC_PDF417ScanningDecoder::createBarcodeMatrix( | |
| 463 CBC_DetectionResult* detectionResult) { | |
| 464 CFX_PtrArray* barcodeMatrix = new CFX_PtrArray; | |
| 465 barcodeMatrix->SetSize(detectionResult->getBarcodeRowCount()); | |
| 466 CFX_PtrArray* temp = NULL; | |
| 467 int32_t colume = 0; | |
| 468 for (int32_t row = 0; row < barcodeMatrix->GetSize(); row++) { | |
| 469 temp = new CFX_PtrArray; | |
| 470 temp->SetSize(detectionResult->getBarcodeColumnCount() + 2); | |
| 471 for (colume = 0; colume < detectionResult->getBarcodeColumnCount() + 2; | |
| 472 colume++) { | |
| 473 temp->SetAt(colume, new CBC_BarcodeValue()); | |
| 474 } | |
| 475 barcodeMatrix->SetAt(row, temp); | |
| 476 } | |
| 477 colume = -1; | |
| 478 for (int32_t i = 0; | |
| 479 i < detectionResult->getDetectionResultColumns().GetSize(); i++) { | |
| 480 CBC_DetectionResultColumn* detectionResultColumn = | |
| 481 (CBC_DetectionResultColumn*)detectionResult->getDetectionResultColumns() | |
| 482 .GetAt(i); | |
| 483 colume++; | |
| 484 if (detectionResultColumn == NULL) { | |
| 485 continue; | |
| 486 } | |
| 487 CFX_PtrArray* temp = detectionResultColumn->getCodewords(); | |
| 488 for (int32_t l = 0; l < temp->GetSize(); l++) { | |
| 489 CBC_Codeword* codeword = (CBC_Codeword*)temp->GetAt(l); | |
| 490 if (codeword == NULL || codeword->getRowNumber() == -1) { | |
| 491 continue; | |
| 492 } | |
| 493 ((CBC_BarcodeValue*)((CFX_PtrArray*)barcodeMatrix->GetAt( | |
| 494 codeword->getRowNumber())) | |
| 495 ->GetAt(colume)) | |
| 496 ->setValue(codeword->getValue()); | |
| 497 } | |
| 498 } | |
| 499 return barcodeMatrix; | |
| 500 } | |
| 501 FX_BOOL CBC_PDF417ScanningDecoder::isValidBarcodeColumn( | |
| 502 CBC_DetectionResult* detectionResult, | |
| 503 int32_t barcodeColumn) { | |
| 504 return barcodeColumn >= 0 && | |
| 505 barcodeColumn <= detectionResult->getBarcodeColumnCount() + 1; | |
| 506 } | |
| 507 int32_t CBC_PDF417ScanningDecoder::getStartColumn( | |
| 508 CBC_DetectionResult* detectionResult, | |
| 509 int32_t barcodeColumn, | |
| 510 int32_t imageRow, | |
| 511 FX_BOOL leftToRight) { | |
| 512 int32_t offset = leftToRight ? 1 : -1; | |
| 513 CBC_Codeword* codeword = NULL; | |
| 514 if (isValidBarcodeColumn(detectionResult, barcodeColumn - offset)) { | |
| 515 codeword = detectionResult->getDetectionResultColumn(barcodeColumn - offset) | |
| 516 ->getCodeword(imageRow); | |
| 517 } | |
| 518 if (codeword) { | |
| 519 return leftToRight ? codeword->getEndX() : codeword->getStartX(); | |
| 520 } | |
| 521 codeword = detectionResult->getDetectionResultColumn(barcodeColumn) | |
| 522 ->getCodewordNearby(imageRow); | |
| 523 if (codeword) { | |
| 524 return leftToRight ? codeword->getStartX() : codeword->getEndX(); | |
| 525 } | |
| 526 if (isValidBarcodeColumn(detectionResult, barcodeColumn - offset)) { | |
| 527 codeword = detectionResult->getDetectionResultColumn(barcodeColumn - offset) | |
| 528 ->getCodewordNearby(imageRow); | |
| 529 } | |
| 530 if (codeword) { | |
| 531 return leftToRight ? codeword->getEndX() : codeword->getStartX(); | |
| 532 } | |
| 533 int32_t skippedColumns = 0; | |
| 534 while (isValidBarcodeColumn(detectionResult, barcodeColumn - offset)) { | |
| 535 barcodeColumn -= offset; | |
| 536 for (int32_t i = 0; | |
| 537 i < detectionResult->getDetectionResultColumn(barcodeColumn) | |
| 538 ->getCodewords() | |
| 539 ->GetSize(); | |
| 540 i++) { | |
| 541 CBC_Codeword* previousRowCodeword = | |
| 542 (CBC_Codeword*)detectionResult->getDetectionResultColumn( | |
| 543 barcodeColumn) | |
| 544 ->getCodewords() | |
| 545 ->GetAt(i); | |
| 546 if (previousRowCodeword) { | |
| 547 return (leftToRight ? previousRowCodeword->getEndX() | |
| 548 : previousRowCodeword->getStartX()) + | |
| 549 offset * skippedColumns * (previousRowCodeword->getEndX() - | |
| 550 previousRowCodeword->getStartX()); | |
| 551 } | |
| 552 } | |
| 553 skippedColumns++; | |
| 554 } | |
| 555 return leftToRight ? detectionResult->getBoundingBox()->getMinX() | |
| 556 : detectionResult->getBoundingBox()->getMaxX(); | |
| 557 } | |
| 558 CBC_Codeword* CBC_PDF417ScanningDecoder::detectCodeword( | |
| 559 CBC_CommonBitMatrix* image, | |
| 560 int32_t minColumn, | |
| 561 int32_t maxColumn, | |
| 562 FX_BOOL leftToRight, | |
| 563 int32_t startColumn, | |
| 564 int32_t imageRow, | |
| 565 int32_t minCodewordWidth, | |
| 566 int32_t maxCodewordWidth) { | |
| 567 startColumn = adjustCodewordStartColumn(image, minColumn, maxColumn, | |
| 568 leftToRight, startColumn, imageRow); | |
| 569 CFX_Int32Array* moduleBitCount = getModuleBitCount( | |
| 570 image, minColumn, maxColumn, leftToRight, startColumn, imageRow); | |
| 571 if (moduleBitCount == NULL) { | |
| 572 return NULL; | |
| 573 } | |
| 574 int32_t endColumn; | |
| 575 int32_t codewordBitCount = CBC_PDF417Common::getBitCountSum(*moduleBitCount); | |
| 576 if (leftToRight) { | |
| 577 endColumn = startColumn + codewordBitCount; | |
| 578 } else { | |
| 579 for (int32_t i = 0; i<moduleBitCount->GetSize()>> 1; i++) { | |
| 580 int32_t tmpCount = moduleBitCount->GetAt(i); | |
| 581 moduleBitCount->SetAt( | |
| 582 i, moduleBitCount->GetAt(moduleBitCount->GetSize() - 1 - i)); | |
| 583 moduleBitCount->SetAt(moduleBitCount->GetSize() - 1 - i, tmpCount); | |
| 584 } | |
| 585 endColumn = startColumn; | |
| 586 startColumn = endColumn - codewordBitCount; | |
| 587 } | |
| 588 int32_t decodedValue = | |
| 589 CBC_PDF417CodewordDecoder::getDecodedValue(*moduleBitCount); | |
| 590 int32_t codeword = CBC_PDF417Common::getCodeword(decodedValue); | |
| 591 delete moduleBitCount; | |
| 592 if (codeword == -1) { | |
| 593 return NULL; | |
| 594 } | |
| 595 return new CBC_Codeword(startColumn, endColumn, | |
| 596 getCodewordBucketNumber(decodedValue), codeword); | |
| 597 } | |
| 598 CFX_Int32Array* CBC_PDF417ScanningDecoder::getModuleBitCount( | |
| 599 CBC_CommonBitMatrix* image, | |
| 600 int32_t minColumn, | |
| 601 int32_t maxColumn, | |
| 602 FX_BOOL leftToRight, | |
| 603 int32_t startColumn, | |
| 604 int32_t imageRow) { | |
| 605 int32_t imageColumn = startColumn; | |
| 606 CFX_Int32Array* moduleBitCount = new CFX_Int32Array; | |
| 607 moduleBitCount->SetSize(8); | |
| 608 int32_t moduleNumber = 0; | |
| 609 int32_t increment = leftToRight ? 1 : -1; | |
| 610 FX_BOOL previousPixelValue = leftToRight; | |
| 611 while (((leftToRight && imageColumn < maxColumn) || | |
| 612 (!leftToRight && imageColumn >= minColumn)) && | |
| 613 moduleNumber < moduleBitCount->GetSize()) { | |
| 614 if (image->Get(imageColumn, imageRow) == previousPixelValue) { | |
| 615 moduleBitCount->SetAt(moduleNumber, | |
| 616 moduleBitCount->GetAt(moduleNumber) + 1); | |
| 617 imageColumn += increment; | |
| 618 } else { | |
| 619 moduleNumber++; | |
| 620 previousPixelValue = !previousPixelValue; | |
| 621 } | |
| 622 } | |
| 623 if (moduleNumber == moduleBitCount->GetSize() || | |
| 624 (((leftToRight && imageColumn == maxColumn) || | |
| 625 (!leftToRight && imageColumn == minColumn)) && | |
| 626 moduleNumber == moduleBitCount->GetSize() - 1)) { | |
| 627 return moduleBitCount; | |
| 628 } | |
| 629 delete moduleBitCount; | |
| 630 return NULL; | |
| 631 } | |
| 632 int32_t CBC_PDF417ScanningDecoder::getNumberOfECCodeWords( | |
| 633 int32_t barcodeECLevel) { | |
| 634 return 2 << barcodeECLevel; | |
| 635 } | |
| 636 int32_t CBC_PDF417ScanningDecoder::adjustCodewordStartColumn( | |
| 637 CBC_CommonBitMatrix* image, | |
| 638 int32_t minColumn, | |
| 639 int32_t maxColumn, | |
| 640 FX_BOOL leftToRight, | |
| 641 int32_t codewordStartColumn, | |
| 642 int32_t imageRow) { | |
| 643 int32_t correctedStartColumn = codewordStartColumn; | |
| 644 int32_t increment = leftToRight ? -1 : 1; | |
| 645 for (int32_t i = 0; i < 2; i++) { | |
| 646 while (((leftToRight && correctedStartColumn >= minColumn) || | |
| 647 (!leftToRight && correctedStartColumn < maxColumn)) && | |
| 648 leftToRight == image->Get(correctedStartColumn, imageRow)) { | |
| 649 if (abs(codewordStartColumn - correctedStartColumn) > | |
| 650 CODEWORD_SKEW_SIZE) { | |
| 651 return codewordStartColumn; | |
| 652 } | |
| 653 correctedStartColumn += increment; | |
| 654 } | |
| 655 increment = -increment; | |
| 656 leftToRight = !leftToRight; | |
| 657 } | |
| 658 return correctedStartColumn; | |
| 659 } | |
| 660 FX_BOOL CBC_PDF417ScanningDecoder::checkCodewordSkew(int32_t codewordSize, | |
| 661 int32_t minCodewordWidth, | |
| 662 int32_t maxCodewordWidth) { | |
| 663 return minCodewordWidth - CODEWORD_SKEW_SIZE <= codewordSize && | |
| 664 codewordSize <= maxCodewordWidth + CODEWORD_SKEW_SIZE; | |
| 665 } | |
| 666 CBC_CommonDecoderResult* CBC_PDF417ScanningDecoder::decodeCodewords( | |
| 667 CFX_Int32Array& codewords, | |
| 668 int32_t ecLevel, | |
| 669 CFX_Int32Array& erasures, | |
| 670 int32_t& e) { | |
| 671 if (codewords.GetSize() == 0) { | |
| 672 e = BCExceptionFormatInstance; | |
| 673 return NULL; | |
| 674 } | |
| 675 int32_t numECCodewords = 1 << (ecLevel + 1); | |
| 676 correctErrors(codewords, erasures, numECCodewords, e); | |
| 677 BC_EXCEPTION_CHECK_ReturnValue(e, NULL); | |
| 678 verifyCodewordCount(codewords, numECCodewords, e); | |
| 679 BC_EXCEPTION_CHECK_ReturnValue(e, NULL); | |
| 680 CFX_ByteString bytestring; | |
| 681 CBC_CommonDecoderResult* decoderResult = CBC_DecodedBitStreamPaser::decode( | |
| 682 codewords, bytestring.FormatInteger(ecLevel), e); | |
| 683 BC_EXCEPTION_CHECK_ReturnValue(e, NULL); | |
| 684 return decoderResult; | |
| 685 } | |
| 686 int32_t CBC_PDF417ScanningDecoder::correctErrors(CFX_Int32Array& codewords, | |
| 687 CFX_Int32Array& erasures, | |
| 688 int32_t numECCodewords, | |
| 689 int32_t& e) { | |
| 690 if ((erasures.GetSize() != 0 && | |
| 691 erasures.GetSize() > (numECCodewords / 2 + MAX_ERRORS)) || | |
| 692 numECCodewords < 0 || numECCodewords > MAX_EC_CODEWORDS) { | |
| 693 e = BCExceptionChecksumInstance; | |
| 694 return -1; | |
| 695 } | |
| 696 int32_t result = CBC_PDF417ECErrorCorrection::decode( | |
| 697 codewords, numECCodewords, erasures, e); | |
| 698 BC_EXCEPTION_CHECK_ReturnValue(e, -1); | |
| 699 return result; | |
| 700 } | |
| 701 void CBC_PDF417ScanningDecoder::verifyCodewordCount(CFX_Int32Array& codewords, | |
| 702 int32_t numECCodewords, | |
| 703 int32_t& e) { | |
| 704 if (codewords.GetSize() < 4) { | |
| 705 e = BCExceptionFormatInstance; | |
| 706 return; | |
| 707 } | |
| 708 int32_t numberOfCodewords = codewords.GetAt(0); | |
| 709 if (numberOfCodewords > codewords.GetSize()) { | |
| 710 e = BCExceptionFormatInstance; | |
| 711 return; | |
| 712 } | |
| 713 if (numberOfCodewords == 0) { | |
| 714 if (numECCodewords < codewords.GetSize()) { | |
| 715 codewords[0] = codewords.GetSize() - numECCodewords; | |
| 716 } else { | |
| 717 e = BCExceptionFormatInstance; | |
| 718 return; | |
| 719 } | |
| 720 } | |
| 721 } | |
| 722 CFX_Int32Array* CBC_PDF417ScanningDecoder::getBitCountForCodeword( | |
| 723 int32_t codeword) { | |
| 724 CFX_Int32Array* result = new CFX_Int32Array; | |
| 725 result->SetSize(8); | |
| 726 int32_t previousValue = 0; | |
| 727 int32_t i = result->GetSize() - 1; | |
| 728 while (TRUE) { | |
| 729 if ((codeword & 0x1) != previousValue) { | |
| 730 previousValue = codeword & 0x1; | |
| 731 i--; | |
| 732 if (i < 0) { | |
| 733 break; | |
| 734 } | |
| 735 } | |
| 736 result->SetAt(i, result->GetAt(i) + 1); | |
| 737 codeword >>= 1; | |
| 738 } | |
| 739 return result; | |
| 740 } | |
| 741 int32_t CBC_PDF417ScanningDecoder::getCodewordBucketNumber(int32_t codeword) { | |
| 742 CFX_Int32Array* array = getBitCountForCodeword(codeword); | |
| 743 int32_t result = getCodewordBucketNumber(*array); | |
| 744 delete array; | |
| 745 return result; | |
| 746 } | |
| 747 int32_t CBC_PDF417ScanningDecoder::getCodewordBucketNumber( | |
| 748 CFX_Int32Array& moduleBitCount) { | |
| 749 return (moduleBitCount.GetAt(0) - moduleBitCount.GetAt(2) + | |
| 750 moduleBitCount.GetAt(4) - moduleBitCount.GetAt(6) + 9) % | |
| 751 9; | |
| 752 } | |
| OLD | NEW |