Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(38)

Side by Side Diff: xfa/src/fxbarcode/src/BC_PDF417ScanningDecoder.cpp

Issue 842043002: Organize barcode codes into modules. (Closed) Base URL: https://pdfium.googlesource.com/pdfium.git@xfa
Patch Set: rebase Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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 }
OLDNEW
« no previous file with comments | « xfa/src/fxbarcode/src/BC_PDF417ResultMetadata.cpp ('k') | xfa/src/fxbarcode/src/BC_PDF417Writer.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698