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 |