• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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