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 "barcode.h" | |
24 #include "include/BC_DecoderResult.h" | |
25 #include "include/BC_ResultPoint.h" | |
26 #include "include/BC_PDF417Codeword.h" | |
27 #include "include/BC_CommonBitMatrix.h" | |
28 #include "include/BC_PDF417Common.h" | |
29 #include "include/BC_PDF417BarcodeValue.h" | |
30 #include "include/BC_PDF417BarcodeMetadata.h" | |
31 #include "include/BC_PDF417BoundingBox.h" | |
32 #include "include/BC_PDF417DetectionResultColumn.h" | |
33 #include "include/BC_PDF417DetectionResultRowIndicatorColumn.h" | |
34 #include "include/BC_PDF417DetectionResult.h" | |
35 #include "include/BC_PDF417DecodedBitStreamParser.h" | |
36 #include "include/BC_PDF417CodewordDecoder.h" | |
37 #include "include/BC_PDF417DecodedBitStreamParser.h" | |
38 #include "include/BC_PDF417ECModulusPoly.h" | |
39 #include "include/BC_PDF417ECModulusGF.h" | |
40 #include "include/BC_PDF417ECErrorCorrection.h" | |
41 #include "include/BC_PDF417DecodedBitStreamParser.h" | |
42 #include "include/BC_PDF417ScanningDecoder.h" | |
43 FX_INT32 CBC_PDF417ScanningDecoder::CODEWORD_SKEW_SIZE = 2; | |
44 FX_INT32 CBC_PDF417ScanningDecoder::MAX_ERRORS = 3; | |
45 FX_INT32 CBC_PDF417ScanningDecoder::MAX_EC_CODEWORDS = 512; | |
46 CBC_PDF417ECErrorCorrection* CBC_PDF417ScanningDecoder::errorCorrection = NULL; | |
47 CBC_PDF417ScanningDecoder::CBC_PDF417ScanningDecoder() | |
48 { | |
49 } | |
50 CBC_PDF417ScanningDecoder::~CBC_PDF417ScanningDecoder() | |
51 { | |
52 } | |
53 void CBC_PDF417ScanningDecoder::Initialize() | |
54 { | |
55 errorCorrection = FX_NEW CBC_PDF417ECErrorCorrection; | |
56 } | |
57 void CBC_PDF417ScanningDecoder::Finalize() | |
58 { | |
59 delete errorCorrection; | |
60 } | |
61 CBC_CommonDecoderResult* CBC_PDF417ScanningDecoder::decode(CBC_CommonBitMatrix*
image, CBC_ResultPoint* imageTopLeft, CBC_ResultPoint* imageBottomLeft, CBC_Resu
ltPoint* imageTopRight, | |
62 CBC_ResultPoint* imageBottomRight, FX_INT32 minCodewordWidth, FX_INT32 m
axCodewordWidth, FX_INT32 &e) | |
63 { | |
64 CBC_BoundingBox* boundingBox = FX_NEW CBC_BoundingBox(image, imageTopLeft, i
mageBottomLeft, imageTopRight, imageBottomRight, e); | |
65 BC_EXCEPTION_CHECK_ReturnValue(e, NULL); | |
66 CBC_DetectionResultRowIndicatorColumn* leftRowIndicatorColumn = NULL; | |
67 CBC_DetectionResultRowIndicatorColumn* rightRowIndicatorColumn = NULL; | |
68 CBC_DetectionResult* detectionResult = NULL; | |
69 for (FX_INT32 i = 0; i < 2; i++) { | |
70 if (imageTopLeft != NULL) { | |
71 leftRowIndicatorColumn = getRowIndicatorColumn(image, boundingBox, *
imageTopLeft, TRUE, minCodewordWidth, maxCodewordWidth); | |
72 } | |
73 if (imageTopRight != NULL) { | |
74 rightRowIndicatorColumn = getRowIndicatorColumn(image, boundingBox,
*imageTopRight, FALSE, minCodewordWidth, maxCodewordWidth); | |
75 } | |
76 detectionResult = merge(leftRowIndicatorColumn, rightRowIndicatorColumn,
e); | |
77 if (e != BCExceptionNO) { | |
78 e = BCExceptiontNotFoundInstance; | |
79 delete leftRowIndicatorColumn; | |
80 delete rightRowIndicatorColumn; | |
81 delete boundingBox; | |
82 return NULL; | |
83 } | |
84 if (i == 0 && (detectionResult->getBoundingBox()->getMinY() < boundingBo
x->getMinY() || detectionResult->getBoundingBox()->getMaxY() > boundingBox->getM
axY())) { | |
85 delete boundingBox; | |
86 boundingBox = detectionResult->getBoundingBox(); | |
87 } else { | |
88 detectionResult->setBoundingBox(boundingBox); | |
89 break; | |
90 } | |
91 } | |
92 FX_INT32 maxBarcodeColumn = detectionResult->getBarcodeColumnCount() + 1; | |
93 detectionResult->setDetectionResultColumn(0, leftRowIndicatorColumn); | |
94 detectionResult->setDetectionResultColumn(maxBarcodeColumn, rightRowIndicato
rColumn); | |
95 FX_BOOL leftToRight = leftRowIndicatorColumn != NULL; | |
96 for (FX_INT32 barcodeColumnCount = 1; barcodeColumnCount <= maxBarcodeColumn
; barcodeColumnCount++) { | |
97 FX_INT32 barcodeColumn = leftToRight ? barcodeColumnCount : maxBarcodeCo
lumn - barcodeColumnCount; | |
98 if (detectionResult->getDetectionResultColumn(barcodeColumn) != NULL) { | |
99 continue; | |
100 } | |
101 CBC_DetectionResultColumn* detectionResultColumn = NULL; | |
102 if (barcodeColumn == 0 || barcodeColumn == maxBarcodeColumn) { | |
103 detectionResultColumn = FX_NEW CBC_DetectionResultRowIndicatorColumn
(boundingBox, barcodeColumn == 0); | |
104 } else { | |
105 detectionResultColumn = FX_NEW CBC_DetectionResultColumn(boundingBox
); | |
106 } | |
107 detectionResult->setDetectionResultColumn(barcodeColumn, detectionResult
Column); | |
108 FX_INT32 startColumn = -1; | |
109 FX_INT32 previousStartColumn = startColumn; | |
110 for (FX_INT32 imageRow = boundingBox->getMinY(); imageRow <= boundingBox
->getMaxY(); imageRow++) { | |
111 startColumn = getStartColumn(detectionResult, barcodeColumn, imageRo
w, leftToRight); | |
112 if (startColumn < 0 || startColumn > boundingBox->getMaxX()) { | |
113 if (previousStartColumn == -1) { | |
114 continue; | |
115 } | |
116 startColumn = previousStartColumn; | |
117 } | |
118 CBC_Codeword* codeword = detectCodeword(image, boundingBox->getMinX(
), boundingBox->getMaxX(), leftToRight, startColumn, imageRow, minCodewordWidth,
maxCodewordWidth); | |
119 if (codeword != NULL) { | |
120 detectionResultColumn->setCodeword(imageRow, codeword); | |
121 previousStartColumn = startColumn; | |
122 minCodewordWidth = minCodewordWidth < codeword->getWidth() ? min
CodewordWidth : codeword->getWidth(); | |
123 maxCodewordWidth = maxCodewordWidth > codeword->getWidth() ? max
CodewordWidth : codeword->getWidth(); | |
124 } | |
125 } | |
126 } | |
127 CBC_CommonDecoderResult* decoderresult = createDecoderResult(detectionResult
, e); | |
128 if (e != BCExceptionNO) { | |
129 delete detectionResult; | |
130 return NULL; | |
131 } | |
132 return decoderresult; | |
133 } | |
134 CFX_ByteString CBC_PDF417ScanningDecoder::toString(CFX_PtrArray* barcodeMatrix) | |
135 { | |
136 CFX_ByteString result; | |
137 for (FX_INT32 row = 0; row < barcodeMatrix->GetSize(); row++) { | |
138 result += row; | |
139 FX_INT32 l = 0; | |
140 for (; l < ((CFX_PtrArray*)barcodeMatrix->GetAt(row))->GetSize(); l++) { | |
141 CBC_BarcodeValue* barcodeValue = (CBC_BarcodeValue*)((CFX_PtrArray*)
barcodeMatrix->GetAt(row))->GetAt(l); | |
142 if (barcodeValue->getValue()->GetSize() == 0) { | |
143 result += ""; | |
144 } else { | |
145 result += barcodeValue->getValue()->GetAt(0); | |
146 result += barcodeValue->getConfidence(barcodeValue->getValue()->
GetAt(0)); | |
147 } | |
148 } | |
149 } | |
150 return result; | |
151 } | |
152 CBC_DetectionResult* CBC_PDF417ScanningDecoder::merge(CBC_DetectionResultRowIndi
catorColumn* leftRowIndicatorColumn, CBC_DetectionResultRowIndicatorColumn* righ
tRowIndicatorColumn, FX_INT32 &e) | |
153 { | |
154 if (leftRowIndicatorColumn == NULL && rightRowIndicatorColumn == NULL) { | |
155 e = BCExceptionIllegalArgument; | |
156 return NULL; | |
157 } | |
158 CBC_BarcodeMetadata* barcodeMetadata = getBarcodeMetadata(leftRowIndicatorCo
lumn, rightRowIndicatorColumn); | |
159 if (barcodeMetadata == NULL) { | |
160 e = BCExceptionCannotMetadata; | |
161 return NULL; | |
162 } | |
163 CBC_BoundingBox* leftboundingBox = adjustBoundingBox(leftRowIndicatorColumn,
e); | |
164 if (e != BCExceptionNO) { | |
165 delete barcodeMetadata; | |
166 return NULL; | |
167 } | |
168 CBC_BoundingBox* rightboundingBox = adjustBoundingBox(rightRowIndicatorColum
n, e); | |
169 if (e != BCExceptionNO) { | |
170 delete barcodeMetadata; | |
171 return NULL; | |
172 } | |
173 CBC_BoundingBox* boundingBox = CBC_BoundingBox::merge(leftboundingBox, right
boundingBox, e); | |
174 if (e != BCExceptionNO) { | |
175 delete barcodeMetadata; | |
176 return NULL; | |
177 } | |
178 CBC_DetectionResult* detectionresult = FX_NEW CBC_DetectionResult(barcodeMet
adata, boundingBox); | |
179 return detectionresult; | |
180 } | |
181 CBC_BoundingBox* CBC_PDF417ScanningDecoder::adjustBoundingBox(CBC_DetectionResul
tRowIndicatorColumn* rowIndicatorColumn, FX_INT32 &e) | |
182 { | |
183 if (rowIndicatorColumn == NULL) { | |
184 return NULL; | |
185 } | |
186 CFX_Int32Array* rowHeights = rowIndicatorColumn->getRowHeights(e); | |
187 BC_EXCEPTION_CHECK_ReturnValue(e, NULL); | |
188 FX_INT32 maxRowHeight = getMax(*rowHeights); | |
189 FX_INT32 missingStartRows = 0; | |
190 for (FX_INT32 i = 0; i < rowHeights->GetSize(); i++) { | |
191 FX_INT32 rowHeight = rowHeights->GetAt(i); | |
192 missingStartRows += maxRowHeight - rowHeight; | |
193 if (rowHeight > 0) { | |
194 break; | |
195 } | |
196 } | |
197 CFX_PtrArray* codewords = rowIndicatorColumn->getCodewords(); | |
198 for (FX_INT32 row = 0; missingStartRows > 0 && codewords->GetAt(row) == NULL
; row++) { | |
199 missingStartRows--; | |
200 } | |
201 FX_INT32 missingEndRows = 0; | |
202 for (FX_INT32 row1 = rowHeights->GetSize() - 1; row1 >= 0; row1--) { | |
203 missingEndRows += maxRowHeight - rowHeights->GetAt(row1); | |
204 if (rowHeights->GetAt(row1) > 0) { | |
205 break; | |
206 } | |
207 } | |
208 for (FX_INT32 row2 = codewords->GetSize() - 1; missingEndRows > 0 && codewor
ds->GetAt(row2) == NULL; row2--) { | |
209 missingEndRows--; | |
210 } | |
211 CBC_BoundingBox* boundingBox = rowIndicatorColumn->getBoundingBox()->addMiss
ingRows(missingStartRows, missingEndRows, rowIndicatorColumn->isLeft(), e); | |
212 BC_EXCEPTION_CHECK_ReturnValue(e, NULL); | |
213 return boundingBox; | |
214 } | |
215 FX_INT32 CBC_PDF417ScanningDecoder::getMax(CFX_Int32Array& values) | |
216 { | |
217 FX_INT32 maxValue = -1; | |
218 for (FX_INT32 i = 0; i < values.GetSize(); i++) { | |
219 FX_INT32 value = values.GetAt(i); | |
220 maxValue = maxValue > value ? maxValue : value; | |
221 } | |
222 return maxValue; | |
223 } | |
224 CBC_BarcodeMetadata* CBC_PDF417ScanningDecoder::getBarcodeMetadata(CBC_Detection
ResultRowIndicatorColumn* leftRowIndicatorColumn, | |
225 CBC_DetectionResultRowIndicatorColumn* rightRowIndicatorColumn) | |
226 { | |
227 CBC_BarcodeMetadata* leftBarcodeMetadata = NULL; | |
228 CBC_BarcodeMetadata* rightBarcodeMetadata = NULL; | |
229 if (leftRowIndicatorColumn == NULL || (leftBarcodeMetadata = leftRowIndicato
rColumn->getBarcodeMetadata()) == NULL) { | |
230 return rightRowIndicatorColumn == NULL ? NULL : rightRowIndicatorColumn-
>getBarcodeMetadata(); | |
231 } | |
232 if (rightRowIndicatorColumn == NULL || (rightBarcodeMetadata = rightRowIndic
atorColumn->getBarcodeMetadata()) == NULL) { | |
233 return leftRowIndicatorColumn == NULL ? NULL : leftRowIndicatorColumn->g
etBarcodeMetadata(); | |
234 } | |
235 if (leftBarcodeMetadata->getColumnCount() != rightBarcodeMetadata->getColumn
Count() && | |
236 leftBarcodeMetadata->getErrorCorrectionLevel() != rightBarcodeMetada
ta->getErrorCorrectionLevel() && | |
237 leftBarcodeMetadata->getRowCount() != rightBarcodeMetadata->getRowCo
unt()) { | |
238 delete leftBarcodeMetadata; | |
239 delete rightBarcodeMetadata; | |
240 return NULL; | |
241 } | |
242 delete rightBarcodeMetadata; | |
243 return leftBarcodeMetadata; | |
244 } | |
245 CBC_DetectionResultRowIndicatorColumn* CBC_PDF417ScanningDecoder::getRowIndicato
rColumn(CBC_CommonBitMatrix* image, CBC_BoundingBox* boundingBox, CBC_ResultPoin
t startPoint, | |
246 FX_BOOL leftToRight, FX_INT32 minCodewordWidth, FX_INT32 maxCodewordWidt
h) | |
247 { | |
248 CBC_DetectionResultRowIndicatorColumn* rowIndicatorColumn = FX_NEW CBC_Detec
tionResultRowIndicatorColumn(boundingBox, leftToRight); | |
249 for (FX_INT32 i = 0; i < 2; i++) { | |
250 FX_INT32 increment = i == 0 ? 1 : -1; | |
251 FX_INT32 startColumn = (FX_INT32) startPoint.GetX(); | |
252 for (FX_INT32 imageRow = (FX_INT32) startPoint.GetY(); imageRow <= bound
ingBox->getMaxY() && imageRow >= boundingBox->getMinY(); imageRow += increment)
{ | |
253 CBC_Codeword* codeword = detectCodeword(image, 0, image->GetWidth(),
leftToRight, startColumn, imageRow, minCodewordWidth, maxCodewordWidth); | |
254 if (codeword != NULL) { | |
255 rowIndicatorColumn->setCodeword(imageRow, codeword); | |
256 if (leftToRight) { | |
257 startColumn = codeword->getStartX(); | |
258 } else { | |
259 startColumn = codeword->getEndX(); | |
260 } | |
261 } | |
262 } | |
263 } | |
264 return rowIndicatorColumn; | |
265 } | |
266 void CBC_PDF417ScanningDecoder::adjustCodewordCount(CBC_DetectionResult* detecti
onResult, CFX_PtrArray* barcodeMatrix, FX_INT32 &e) | |
267 { | |
268 CFX_Int32Array* numberOfCodewords = ((CBC_BarcodeValue*)((CFX_PtrArray*)barc
odeMatrix->GetAt(0))->GetAt(1))->getValue(); | |
269 FX_INT32 calculatedNumberOfCodewords = detectionResult->getBarcodeColumnCoun
t() * detectionResult->getBarcodeRowCount() - getNumberOfECCodeWords(detectionRe
sult->getBarcodeECLevel()); | |
270 if (numberOfCodewords->GetSize() == 0) { | |
271 if (calculatedNumberOfCodewords < 1 || calculatedNumberOfCodewords > CBC
_PDF417Common::MAX_CODEWORDS_IN_BARCODE) { | |
272 e = BCExceptiontNotFoundInstance; | |
273 delete numberOfCodewords; | |
274 BC_EXCEPTION_CHECK_ReturnVoid(e); | |
275 } | |
276 ((CBC_BarcodeValue*)((CFX_PtrArray*)barcodeMatrix->GetAt(0))->GetAt(1))-
>setValue(calculatedNumberOfCodewords); | |
277 } else if (numberOfCodewords->GetAt(0) != calculatedNumberOfCodewords) { | |
278 ((CBC_BarcodeValue*)((CFX_PtrArray*)barcodeMatrix->GetAt(0))->GetAt(1))-
>setValue(calculatedNumberOfCodewords); | |
279 } | |
280 delete numberOfCodewords; | |
281 } | |
282 CBC_CommonDecoderResult* CBC_PDF417ScanningDecoder::createDecoderResult(CBC_Dete
ctionResult* detectionResult, FX_INT32 &e) | |
283 { | |
284 CFX_PtrArray* barcodeMatrix = createBarcodeMatrix(detectionResult); | |
285 adjustCodewordCount(detectionResult, barcodeMatrix, e); | |
286 if (e != BCExceptionNO) { | |
287 for (FX_INT32 i = 0; i < barcodeMatrix->GetSize(); i++) { | |
288 CFX_PtrArray* temp = (CFX_PtrArray*)barcodeMatrix->GetAt(i); | |
289 for (FX_INT32 j = 0; j < temp->GetSize(); j++) { | |
290 delete (CBC_BarcodeValue*)temp->GetAt(j); | |
291 } | |
292 temp->RemoveAll(); | |
293 delete temp; | |
294 } | |
295 barcodeMatrix->RemoveAll(); | |
296 delete barcodeMatrix; | |
297 return NULL; | |
298 } | |
299 CFX_Int32Array erasures; | |
300 CFX_Int32Array codewords; | |
301 codewords.SetSize(detectionResult->getBarcodeRowCount() * detectionResult->g
etBarcodeColumnCount()); | |
302 CFX_PtrArray ambiguousIndexValuesList; | |
303 CFX_Int32Array ambiguousIndexesList; | |
304 for (FX_INT32 row = 0; row < detectionResult->getBarcodeRowCount(); row++) { | |
305 for (FX_INT32 l = 0; l < detectionResult->getBarcodeColumnCount(); l++)
{ | |
306 CFX_Int32Array* values = ((CBC_BarcodeValue*)((CFX_PtrArray*)barcode
Matrix->GetAt(row))->GetAt(l + 1))->getValue(); | |
307 FX_INT32 codewordIndex = row * detectionResult->getBarcodeColumnCoun
t() + l; | |
308 if (values->GetSize() == 0) { | |
309 erasures.Add(codewordIndex); | |
310 } else if (values->GetSize() == 1) { | |
311 codewords[codewordIndex] = values->GetAt(0); | |
312 } else { | |
313 ambiguousIndexesList.Add(codewordIndex); | |
314 ambiguousIndexValuesList.Add(values); | |
315 } | |
316 } | |
317 } | |
318 CFX_PtrArray ambiguousIndexValues; | |
319 ambiguousIndexValues.SetSize(ambiguousIndexValuesList.GetSize()); | |
320 for (FX_INT32 i = 0; i < ambiguousIndexValues.GetSize(); i++) { | |
321 ambiguousIndexValues.SetAt(i, ambiguousIndexValuesList.GetAt(i)); | |
322 } | |
323 for (FX_INT32 l = 0; l < barcodeMatrix->GetSize(); l++) { | |
324 CFX_PtrArray* temp = (CFX_PtrArray*)barcodeMatrix->GetAt(l); | |
325 for (FX_INT32 j = 0; j < temp->GetSize(); j++) { | |
326 delete (CBC_BarcodeValue*)temp->GetAt(j); | |
327 } | |
328 temp->RemoveAll(); | |
329 delete temp; | |
330 } | |
331 barcodeMatrix->RemoveAll(); | |
332 delete barcodeMatrix; | |
333 CBC_CommonDecoderResult* decoderResult = createDecoderResultFromAmbiguousVal
ues(detectionResult->getBarcodeECLevel(), codewords, erasures, ambiguousIndexesL
ist, ambiguousIndexValues, e); | |
334 BC_EXCEPTION_CHECK_ReturnValue(e, NULL); | |
335 return decoderResult; | |
336 } | |
337 CBC_CommonDecoderResult* CBC_PDF417ScanningDecoder::createDecoderResultFromAmbig
uousValues(FX_INT32 ecLevel, CFX_Int32Array &codewords, CFX_Int32Array &erasureA
rray, CFX_Int32Array &ambiguousIndexes, | |
338 CFX_PtrArray& ambiguousIndexValues, FX_INT32 &e) | |
339 { | |
340 CFX_Int32Array ambiguousIndexCount; | |
341 ambiguousIndexCount.SetSize(ambiguousIndexes.GetSize()); | |
342 FX_INT32 tries = 100; | |
343 while (tries-- > 0) { | |
344 for (FX_INT32 l = 0; l < ambiguousIndexCount.GetSize(); l++) { | |
345 codewords[ambiguousIndexes[l]] = ((CFX_Int32Array*)ambiguousIndexVal
ues.GetAt(l))->GetAt(ambiguousIndexCount[l]); | |
346 } | |
347 CBC_CommonDecoderResult* decoderResult = decodeCodewords(codewords, ecLe
vel, erasureArray, e); | |
348 if (e != BCExceptionNO) { | |
349 e = BCExceptionNO; | |
350 continue; | |
351 } else { | |
352 return decoderResult; | |
353 } | |
354 if (ambiguousIndexCount.GetSize() == 0) { | |
355 e = BCExceptionChecksumInstance; | |
356 return NULL; | |
357 } | |
358 for (FX_INT32 i = 0; i < ambiguousIndexCount.GetSize(); i++) { | |
359 if (ambiguousIndexCount[i] < ((CFX_Int32Array*)(ambiguousIndexValues
.GetAt(i)))->GetSize() - 1) { | |
360 ambiguousIndexCount[i]++; | |
361 break; | |
362 } else { | |
363 ambiguousIndexCount[i] = 0; | |
364 if (i == ambiguousIndexCount.GetSize() - 1) { | |
365 e = BCExceptionChecksumInstance; | |
366 return NULL; | |
367 } | |
368 } | |
369 } | |
370 } | |
371 e = BCExceptionChecksumInstance; | |
372 return NULL; | |
373 } | |
374 CFX_PtrArray* CBC_PDF417ScanningDecoder::createBarcodeMatrix(CBC_DetectionResult
* detectionResult) | |
375 { | |
376 CFX_PtrArray* barcodeMatrix = FX_NEW CFX_PtrArray; | |
377 barcodeMatrix->SetSize(detectionResult->getBarcodeRowCount()); | |
378 CFX_PtrArray* temp = NULL; | |
379 FX_INT32 colume = 0; | |
380 for (FX_INT32 row = 0; row < barcodeMatrix->GetSize(); row++) { | |
381 temp = FX_NEW CFX_PtrArray; | |
382 temp->SetSize(detectionResult->getBarcodeColumnCount() + 2); | |
383 for (colume = 0; colume < detectionResult->getBarcodeColumnCount() + 2;
colume++) { | |
384 temp->SetAt(colume, FX_NEW CBC_BarcodeValue()); | |
385 } | |
386 barcodeMatrix->SetAt(row, temp); | |
387 } | |
388 colume = -1; | |
389 for (FX_INT32 i = 0; i < detectionResult->getDetectionResultColumns().GetSiz
e(); i++) { | |
390 CBC_DetectionResultColumn* detectionResultColumn = (CBC_DetectionResultC
olumn*) detectionResult->getDetectionResultColumns().GetAt(i); | |
391 colume++; | |
392 if (detectionResultColumn == NULL) { | |
393 continue; | |
394 } | |
395 CFX_PtrArray* temp = detectionResultColumn->getCodewords(); | |
396 for (FX_INT32 l = 0; l < temp->GetSize(); l++) { | |
397 CBC_Codeword* codeword = (CBC_Codeword*) temp->GetAt(l); | |
398 if (codeword == NULL || codeword->getRowNumber() == -1) { | |
399 continue; | |
400 } | |
401 ((CBC_BarcodeValue*)((CFX_PtrArray*)barcodeMatrix->GetAt(codeword->g
etRowNumber()))->GetAt(colume))->setValue(codeword->getValue()); | |
402 } | |
403 } | |
404 return barcodeMatrix; | |
405 } | |
406 FX_BOOL CBC_PDF417ScanningDecoder::isValidBarcodeColumn(CBC_DetectionResult* det
ectionResult, FX_INT32 barcodeColumn) | |
407 { | |
408 return barcodeColumn >= 0 && barcodeColumn <= detectionResult->getBarcodeCol
umnCount() + 1; | |
409 } | |
410 FX_INT32 CBC_PDF417ScanningDecoder::getStartColumn(CBC_DetectionResult* detectio
nResult, FX_INT32 barcodeColumn, FX_INT32 imageRow, FX_BOOL leftToRight) | |
411 { | |
412 FX_INT32 offset = leftToRight ? 1 : -1; | |
413 CBC_Codeword* codeword = NULL; | |
414 if (isValidBarcodeColumn(detectionResult, barcodeColumn - offset)) { | |
415 codeword = detectionResult->getDetectionResultColumn(barcodeColumn - off
set)->getCodeword(imageRow); | |
416 } | |
417 if (codeword != NULL) { | |
418 return leftToRight ? codeword->getEndX() : codeword->getStartX(); | |
419 } | |
420 codeword = detectionResult->getDetectionResultColumn(barcodeColumn)->getCode
wordNearby(imageRow); | |
421 if (codeword != NULL) { | |
422 return leftToRight ? codeword->getStartX() : codeword->getEndX(); | |
423 } | |
424 if (isValidBarcodeColumn(detectionResult, barcodeColumn - offset)) { | |
425 codeword = detectionResult->getDetectionResultColumn(barcodeColumn - off
set)->getCodewordNearby(imageRow); | |
426 } | |
427 if (codeword != NULL) { | |
428 return leftToRight ? codeword->getEndX() : codeword->getStartX(); | |
429 } | |
430 FX_INT32 skippedColumns = 0; | |
431 while (isValidBarcodeColumn(detectionResult, barcodeColumn - offset)) { | |
432 barcodeColumn -= offset; | |
433 for (FX_INT32 i = 0; i < detectionResult->getDetectionResultColumn(barco
deColumn)->getCodewords()->GetSize(); i++) { | |
434 CBC_Codeword* previousRowCodeword = (CBC_Codeword*) detectionResult-
>getDetectionResultColumn(barcodeColumn)->getCodewords()->GetAt(i); | |
435 if (previousRowCodeword != NULL) { | |
436 return (leftToRight ? previousRowCodeword->getEndX() : previousR
owCodeword->getStartX()) + | |
437 offset * skippedColumns * (previousRowCodeword->getEndX()
- previousRowCodeword->getStartX()); | |
438 } | |
439 } | |
440 skippedColumns++; | |
441 } | |
442 return leftToRight ? detectionResult->getBoundingBox()->getMinX() : detectio
nResult->getBoundingBox()->getMaxX(); | |
443 } | |
444 CBC_Codeword* CBC_PDF417ScanningDecoder::detectCodeword(CBC_CommonBitMatrix* ima
ge, FX_INT32 minColumn, FX_INT32 maxColumn, FX_BOOL leftToRight, FX_INT32 startC
olumn, | |
445 FX_INT32 imageRow, FX_INT32 minCodewordWidth, FX_INT32 maxCodewordWidth) | |
446 { | |
447 startColumn = adjustCodewordStartColumn(image, minColumn, maxColumn, leftToR
ight, startColumn, imageRow); | |
448 CFX_Int32Array* moduleBitCount = getModuleBitCount(image, minColumn, maxColu
mn, leftToRight, startColumn, imageRow); | |
449 if (moduleBitCount == NULL) { | |
450 return NULL; | |
451 } | |
452 FX_INT32 endColumn; | |
453 FX_INT32 codewordBitCount = CBC_PDF417Common::getBitCountSum(*moduleBitCount
); | |
454 if (leftToRight) { | |
455 endColumn = startColumn + codewordBitCount; | |
456 } else { | |
457 for (FX_INT32 i = 0; i < moduleBitCount->GetSize() >> 1; i++) { | |
458 FX_INT32 tmpCount = moduleBitCount->GetAt(i); | |
459 moduleBitCount->SetAt(i, moduleBitCount->GetAt(moduleBitCount->GetSi
ze() - 1 - i)); | |
460 moduleBitCount->SetAt(moduleBitCount->GetSize() - 1 - i, tmpCount); | |
461 } | |
462 endColumn = startColumn; | |
463 startColumn = endColumn - codewordBitCount; | |
464 } | |
465 FX_INT32 decodedValue = CBC_PDF417CodewordDecoder::getDecodedValue(*moduleBi
tCount); | |
466 FX_INT32 codeword = CBC_PDF417Common::getCodeword(decodedValue); | |
467 delete moduleBitCount; | |
468 if (codeword == -1) { | |
469 return NULL; | |
470 } | |
471 return FX_NEW CBC_Codeword(startColumn, endColumn, getCodewordBucketNumber(d
ecodedValue), codeword); | |
472 } | |
473 CFX_Int32Array* CBC_PDF417ScanningDecoder::getModuleBitCount(CBC_CommonBitMatrix
* image, FX_INT32 minColumn, FX_INT32 maxColumn, FX_BOOL leftToRight, FX_INT32 s
tartColumn, FX_INT32 imageRow) | |
474 { | |
475 FX_INT32 imageColumn = startColumn; | |
476 CFX_Int32Array* moduleBitCount = FX_NEW CFX_Int32Array; | |
477 moduleBitCount->SetSize(8); | |
478 FX_INT32 moduleNumber = 0; | |
479 FX_INT32 increment = leftToRight ? 1 : -1; | |
480 FX_BOOL previousPixelValue = leftToRight; | |
481 while (((leftToRight && imageColumn < maxColumn) || (!leftToRight && imageCo
lumn >= minColumn)) && moduleNumber < moduleBitCount->GetSize()) { | |
482 if (image->Get(imageColumn, imageRow) == previousPixelValue) { | |
483 moduleBitCount->SetAt(moduleNumber, moduleBitCount->GetAt(moduleNumb
er) + 1); | |
484 imageColumn += increment; | |
485 } else { | |
486 moduleNumber++; | |
487 previousPixelValue = !previousPixelValue; | |
488 } | |
489 } | |
490 if (moduleNumber == moduleBitCount->GetSize() || (((leftToRight && imageColu
mn == maxColumn) || (!leftToRight && imageColumn == minColumn)) && moduleNumber
== moduleBitCount->GetSize() - 1)) { | |
491 return moduleBitCount; | |
492 } | |
493 delete moduleBitCount; | |
494 return NULL; | |
495 } | |
496 FX_INT32 CBC_PDF417ScanningDecoder::getNumberOfECCodeWords(FX_INT32 barcodeECLev
el) | |
497 { | |
498 return 2 << barcodeECLevel; | |
499 } | |
500 FX_INT32 CBC_PDF417ScanningDecoder::adjustCodewordStartColumn(CBC_CommonBitMatri
x* image, FX_INT32 minColumn, FX_INT32 maxColumn, FX_BOOL leftToRight, FX_INT32
codewordStartColumn, FX_INT32 imageRow) | |
501 { | |
502 FX_INT32 correctedStartColumn = codewordStartColumn; | |
503 FX_INT32 increment = leftToRight ? -1 : 1; | |
504 for (FX_INT32 i = 0; i < 2; i++) { | |
505 FX_BOOL l = image->Get(correctedStartColumn, imageRow); | |
506 while (((leftToRight && correctedStartColumn >= minColumn) || (!leftToRi
ght && correctedStartColumn < maxColumn)) && leftToRight == image->Get(corrected
StartColumn, imageRow)) { | |
507 if (abs(codewordStartColumn - correctedStartColumn) > CODEWORD_SKEW_
SIZE) { | |
508 return codewordStartColumn; | |
509 } | |
510 correctedStartColumn += increment; | |
511 } | |
512 increment = -increment; | |
513 leftToRight = !leftToRight; | |
514 } | |
515 return correctedStartColumn; | |
516 } | |
517 FX_BOOL CBC_PDF417ScanningDecoder::checkCodewordSkew(FX_INT32 codewordSize, FX_I
NT32 minCodewordWidth, FX_INT32 maxCodewordWidth) | |
518 { | |
519 return minCodewordWidth - CODEWORD_SKEW_SIZE <= codewordSize && codewordSize
<= maxCodewordWidth + CODEWORD_SKEW_SIZE; | |
520 } | |
521 CBC_CommonDecoderResult* CBC_PDF417ScanningDecoder::decodeCodewords(CFX_Int32Arr
ay &codewords, FX_INT32 ecLevel, CFX_Int32Array &erasures, FX_INT32 &e) | |
522 { | |
523 if (codewords.GetSize() == 0) { | |
524 e = BCExceptionFormatInstance; | |
525 return NULL; | |
526 } | |
527 FX_INT32 numECCodewords = 1 << (ecLevel + 1); | |
528 FX_INT32 correctedErrorsCount = correctErrors(codewords, erasures, numECCode
words, e); | |
529 BC_EXCEPTION_CHECK_ReturnValue(e , NULL); | |
530 verifyCodewordCount(codewords, numECCodewords, e); | |
531 BC_EXCEPTION_CHECK_ReturnValue(e, NULL); | |
532 CFX_ByteString bytestring; | |
533 CBC_CommonDecoderResult* decoderResult = CBC_DecodedBitStreamPaser::decode(c
odewords, bytestring.FormatInteger(ecLevel), e); | |
534 BC_EXCEPTION_CHECK_ReturnValue(e, NULL); | |
535 return decoderResult; | |
536 } | |
537 FX_INT32 CBC_PDF417ScanningDecoder::correctErrors(CFX_Int32Array &codewords, CFX
_Int32Array &erasures, FX_INT32 numECCodewords, FX_INT32 &e) | |
538 { | |
539 if ((erasures.GetSize() != 0 && erasures.GetSize() > (numECCodewords / 2 + M
AX_ERRORS)) || numECCodewords < 0 || numECCodewords > MAX_EC_CODEWORDS) { | |
540 e = BCExceptionChecksumInstance; | |
541 return -1; | |
542 } | |
543 FX_INT32 result = CBC_PDF417ECErrorCorrection::decode(codewords, numECCodewo
rds, erasures, e); | |
544 BC_EXCEPTION_CHECK_ReturnValue(e, -1); | |
545 return result; | |
546 } | |
547 void CBC_PDF417ScanningDecoder::verifyCodewordCount(CFX_Int32Array &codewords, F
X_INT32 numECCodewords, FX_INT32 &e) | |
548 { | |
549 if (codewords.GetSize() < 4) { | |
550 e = BCExceptionFormatInstance; | |
551 return; | |
552 } | |
553 FX_INT32 numberOfCodewords = codewords.GetAt(0); | |
554 if (numberOfCodewords > codewords.GetSize()) { | |
555 e = BCExceptionFormatInstance; | |
556 return; | |
557 } | |
558 if (numberOfCodewords == 0) { | |
559 if (numECCodewords < codewords.GetSize()) { | |
560 codewords[0] = codewords.GetSize() - numECCodewords; | |
561 } else { | |
562 e = BCExceptionFormatInstance; | |
563 return; | |
564 } | |
565 } | |
566 } | |
567 CFX_Int32Array* CBC_PDF417ScanningDecoder::getBitCountForCodeword(FX_INT32 codew
ord) | |
568 { | |
569 CFX_Int32Array* result = FX_NEW CFX_Int32Array; | |
570 result->SetSize(8); | |
571 FX_INT32 previousValue = 0; | |
572 FX_INT32 i = result->GetSize() - 1; | |
573 while (TRUE) { | |
574 if ((codeword & 0x1) != previousValue) { | |
575 previousValue = codeword & 0x1; | |
576 i--; | |
577 if (i < 0) { | |
578 break; | |
579 } | |
580 } | |
581 result->SetAt(i, result->GetAt(i) + 1); | |
582 codeword >>= 1; | |
583 } | |
584 return result; | |
585 } | |
586 FX_INT32 CBC_PDF417ScanningDecoder::getCodewordBucketNumber(FX_INT32 codeword) | |
587 { | |
588 CFX_Int32Array* array = getBitCountForCodeword(codeword); | |
589 FX_INT32 result = getCodewordBucketNumber(*array); | |
590 delete array; | |
591 return result; | |
592 } | |
593 FX_INT32 CBC_PDF417ScanningDecoder::getCodewordBucketNumber(CFX_Int32Array& modu
leBitCount) | |
594 { | |
595 return (moduleBitCount.GetAt(0) - moduleBitCount.GetAt(2) + moduleBitCount.G
etAt(4) - moduleBitCount.GetAt(6) + 9) % 9; | |
596 } | |
OLD | NEW |