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