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

Side by Side Diff: xfa/src/fxbarcode/src/BC_PDF417Detector.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 2009 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_ResultPoint.h"
25 #include "include/BC_PDF417DetectorResult.h"
26 #include "include/BC_BinaryBitmap.h"
27 #include "include/BC_CommonBitMatrix.h"
28 #include "include/BC_CommonBitArray.h"
29 #include "include/BC_PDF417Detector.h"
30 #define INTERGER_MAX 2147483647
31 FX_INT32 CBC_Detector::INDEXES_START_PATTERN[] = {0, 4, 1, 5};
32 FX_INT32 CBC_Detector::INDEXES_STOP_PATTERN[] = {6, 2, 7, 3};
33 FX_INT32 CBC_Detector::INTEGER_MATH_SHIFT = 8;
34 FX_INT32 CBC_Detector::PATTERN_MATCH_RESULT_SCALE_FACTOR = 1 << INTEGER_MATH_SHI FT;
35 FX_INT32 CBC_Detector::MAX_AVG_VARIANCE = (FX_INT32) (PATTERN_MATCH_RESULT_SCALE _FACTOR * 0.42f);
36 FX_INT32 CBC_Detector::MAX_INDIVIDUAL_VARIANCE = (FX_INT32) (PATTERN_MATCH_RESUL T_SCALE_FACTOR * 0.8f);
37 FX_INT32 CBC_Detector::START_PATTERN[] = {8, 1, 1, 1, 1, 1, 1, 3};
38 FX_INT32 CBC_Detector::STOP_PATTERN[] = {7, 1, 1, 3, 1, 1, 1, 2, 1};
39 FX_INT32 CBC_Detector::MAX_PIXEL_DRIFT = 3;
40 FX_INT32 CBC_Detector::MAX_PATTERN_DRIFT = 5;
41 FX_INT32 CBC_Detector::SKIPPED_ROW_COUNT_MAX = 25;
42 FX_INT32 CBC_Detector::ROW_STEP = 5;
43 FX_INT32 CBC_Detector::BARCODE_MIN_HEIGHT = 10;
44 CBC_Detector::CBC_Detector()
45 {
46 }
47 CBC_Detector::~CBC_Detector()
48 {
49 }
50 CBC_PDF417DetectorResult* CBC_Detector::detect(CBC_BinaryBitmap* image, FX_INT32 hints, FX_BOOL multiple, FX_INT32 &e)
51 {
52 CBC_CommonBitMatrix* bitMatrix = image->GetBlackMatrix(e);
53 BC_EXCEPTION_CHECK_ReturnValue(e, NULL);
54 CFX_PtrArray* barcodeCoordinates = detect(multiple, bitMatrix);
55 if (barcodeCoordinates->GetSize() == 0) {
56 rotate180(bitMatrix);
57 barcodeCoordinates = detect(multiple, bitMatrix);
58 }
59 if (barcodeCoordinates->GetSize() == 0) {
60 e = BCExceptionUnSupportedBarcode;
61 BC_EXCEPTION_CHECK_ReturnValue(e, NULL);
62 }
63 CBC_PDF417DetectorResult* detectorResult = FX_NEW CBC_PDF417DetectorResult(b itMatrix, barcodeCoordinates);
64 return detectorResult;
65 }
66 void CBC_Detector::rotate180(CBC_CommonBitMatrix* bitMatrix)
67 {
68 FX_INT32 width = bitMatrix->GetWidth();
69 FX_INT32 height = bitMatrix->GetHeight();
70 CBC_CommonBitArray* firstRowBitArray = FX_NEW CBC_CommonBitArray(width);
71 CBC_CommonBitArray* secondRowBitArray = FX_NEW CBC_CommonBitArray(width);
72 CBC_CommonBitArray* tmpBitArray = FX_NEW CBC_CommonBitArray(width);
73 for (FX_INT32 y = 0; y < (height + 1) >> 1; y++) {
74 CBC_CommonBitArray* temp = bitMatrix->GetRow(height - 1 - y, secondRowBi tArray);
75 CBC_CommonBitArray* tempfirstRow = firstRowBitArray;
76 firstRowBitArray = bitMatrix->GetRow(y, tempfirstRow);
77 delete tempfirstRow;
78 CBC_CommonBitArray* row = mirror(temp, tmpBitArray);
79 delete temp;
80 bitMatrix->SetRow(y, row);
81 delete row;
82 CBC_CommonBitArray* rowfirstRow = mirror(firstRowBitArray, tmpBitArray);
83 bitMatrix->SetRow(height - 1 - y, rowfirstRow);
84 delete rowfirstRow;
85 }
86 delete tmpBitArray;
87 delete firstRowBitArray;
88 delete secondRowBitArray;
89 }
90 CBC_CommonBitArray* CBC_Detector::mirror(CBC_CommonBitArray* input, CBC_CommonBi tArray* result)
91 {
92 CBC_CommonBitArray* array = FX_NEW CBC_CommonBitArray(result->GetSize());
93 array->Clear();
94 FX_INT32 size = input->GetSize();
95 for (FX_INT32 i = 0; i < size; i++) {
96 if (input->Get(i)) {
97 array->Set(size - 1 - i);
98 }
99 }
100 return array;
101 }
102 CFX_PtrArray* CBC_Detector::detect(FX_BOOL multiple, CBC_CommonBitMatrix* bitMat rix)
103 {
104 CFX_PtrArray* barcodeCoordinates = FX_NEW CFX_PtrArray;
105 FX_INT32 row = 0;
106 FX_INT32 column = 0;
107 FX_BOOL foundBarcodeInRow = FALSE;
108 while (row < bitMatrix->GetHeight()) {
109 CFX_PtrArray* vertices = findVertices(bitMatrix, row, column);
110 if (vertices->GetAt(0) == NULL && vertices->GetAt(3) == NULL) {
111 if (!foundBarcodeInRow) {
112 if (vertices) {
113 delete(vertices);
114 }
115 break;
116 }
117 foundBarcodeInRow = FALSE;
118 column = 0;
119 for (FX_INT32 i = 0; i < barcodeCoordinates->GetSize(); i++) {
120 CFX_PtrArray* barcodeCoordinate = (CFX_PtrArray*)barcodeCoordina tes->GetAt(i);
121 if (barcodeCoordinate->GetAt(1) != NULL) {
122 row = row > ((CBC_ResultPoint*)barcodeCoordinate->GetAt(1))- >GetY();
123 }
124 if (barcodeCoordinate->GetAt(3) != NULL) {
125 row = row > ((CBC_ResultPoint*)barcodeCoordinate->GetAt(3))- >GetY();
126 }
127 }
128 row += ROW_STEP;
129 if (vertices) {
130 delete(vertices);
131 }
132 continue;
133 }
134 foundBarcodeInRow = TRUE;
135 barcodeCoordinates->Add(vertices);
136 if (!multiple) {
137 break;
138 }
139 if (vertices->GetAt(2) != NULL) {
140 column = (FX_INT32) ((CBC_ResultPoint*)vertices->GetAt(2))->GetX();
141 row = (FX_INT32) ((CBC_ResultPoint*)vertices->GetAt(2))->GetY();
142 } else {
143 column = (FX_INT32) ((CBC_ResultPoint*)vertices->GetAt(4))->GetX();
144 row = (FX_INT32) ((CBC_ResultPoint*)vertices->GetAt(4))->GetY();
145 }
146 }
147 return barcodeCoordinates;
148 }
149 CFX_PtrArray* CBC_Detector::findVertices(CBC_CommonBitMatrix* matrix, FX_INT32 s tartRow, FX_INT32 startColumn)
150 {
151 FX_INT32 height = matrix->GetHeight();
152 FX_INT32 width = matrix->GetWidth();
153 CFX_PtrArray* result = FX_NEW CFX_PtrArray;
154 result->SetSize(8);
155 CFX_PtrArray* startptr = findRowsWithPattern(matrix, height, width, startRo w, startColumn, START_PATTERN, sizeof(START_PATTERN) / sizeof(START_PATTERN[0])) ;
156 copyToResult(result, startptr, INDEXES_START_PATTERN, sizeof(INDEXES_START_P ATTERN) / sizeof(INDEXES_START_PATTERN[0]));
157 startptr->RemoveAll();
158 delete startptr;
159 if (result->GetAt(4) != NULL) {
160 startColumn = (FX_INT32) ((CBC_ResultPoint*)result->GetAt(4))->GetX();
161 startRow = (FX_INT32) ((CBC_ResultPoint*)result->GetAt(4))->GetY();
162 }
163 CFX_PtrArray* stopptr = findRowsWithPattern(matrix, height, width, startRow , startColumn, STOP_PATTERN, sizeof(STOP_PATTERN) / sizeof(STOP_PATTERN[0]));
164 copyToResult(result, stopptr, INDEXES_STOP_PATTERN, sizeof(INDEXES_STOP_PATT ERN) / sizeof(INDEXES_STOP_PATTERN[0]));
165 stopptr->RemoveAll();
166 delete stopptr;
167 return result;
168 }
169 void CBC_Detector::copyToResult(CFX_PtrArray *result, CFX_PtrArray* tmpResult, F X_INT32* destinationIndexes, FX_INT32 destinationLength)
170 {
171 for (FX_INT32 i = 0; i < destinationLength; i++) {
172 result->SetAt(destinationIndexes[i], tmpResult->GetAt(i));
173 }
174 }
175 CFX_PtrArray* CBC_Detector::findRowsWithPattern(CBC_CommonBitMatrix* matrix, FX_ INT32 height, FX_INT32 width, FX_INT32 startRow, FX_INT32 startColumn, FX_INT32* pattern, FX_INT32 patternLength)
176 {
177 CFX_PtrArray* result = FX_NEW CFX_PtrArray;
178 result->SetSize(4);
179 FX_BOOL found = FALSE;
180 CFX_Int32Array counters;
181 counters.SetSize(patternLength);
182 for (; startRow < height; startRow += ROW_STEP) {
183 CFX_Int32Array* loc = findGuardPattern(matrix, startColumn, startRow, wi dth, FALSE, pattern, patternLength, counters);
184 if (loc != NULL) {
185 while (startRow > 0) {
186 CFX_Int32Array* previousRowLoc = findGuardPattern(matrix, startC olumn, --startRow, width, FALSE, pattern, patternLength, counters);
187 if (previousRowLoc != NULL) {
188 delete loc;
189 loc = previousRowLoc;
190 } else {
191 startRow++;
192 break;
193 }
194 }
195 result->SetAt(0, FX_NEW CBC_ResultPoint((FX_FLOAT)loc->GetAt(0), (FX _FLOAT)startRow));
196 result->SetAt(1, FX_NEW CBC_ResultPoint((FX_FLOAT)loc->GetAt(1), (FX _FLOAT)startRow));
197 found = TRUE;
198 delete loc;
199 break;
200 }
201 }
202 FX_INT32 stopRow = startRow + 1;
203 if (found) {
204 FX_INT32 skippedRowCount = 0;
205 CFX_Int32Array previousRowLoc;
206 previousRowLoc.Add((FX_INT32)((CBC_ResultPoint*)result->GetAt(0))->GetX( ));
207 previousRowLoc.Add((FX_INT32)((CBC_ResultPoint*)result->GetAt(1))->GetX( ));
208 for (; stopRow < height; stopRow++) {
209 CFX_Int32Array* loc = findGuardPattern(matrix, previousRowLoc[0], st opRow, width, FALSE, pattern, patternLength, counters);
210 if (loc != NULL &&
211 abs(previousRowLoc[0] - loc->GetAt(0)) < MAX_PATTERN_DRIFT & &
212 abs(previousRowLoc[1] - loc->GetAt(1)) < MAX_PATTERN_DRIFT) {
213 previousRowLoc.Copy(*loc);
214 skippedRowCount = 0;
215 } else {
216 if (skippedRowCount > SKIPPED_ROW_COUNT_MAX) {
217 delete loc;
218 break;
219 } else {
220 skippedRowCount++;
221 }
222 }
223 delete loc;
224 }
225 stopRow -= skippedRowCount + 1;
226 result->SetAt(2, FX_NEW CBC_ResultPoint((FX_FLOAT)previousRowLoc.GetAt(0 ), (FX_FLOAT)stopRow));
227 result->SetAt(3, FX_NEW CBC_ResultPoint((FX_FLOAT)previousRowLoc.GetAt(1 ), (FX_FLOAT)stopRow));
228 }
229 if (stopRow - startRow < BARCODE_MIN_HEIGHT) {
230 for (FX_INT32 i = 0; i < result->GetSize(); i++) {
231 result->SetAt(i, NULL);
232 }
233 }
234 return result;
235 }
236 CFX_Int32Array* CBC_Detector::findGuardPattern(CBC_CommonBitMatrix* matrix, FX_I NT32 column, FX_INT32 row, FX_INT32 width, FX_BOOL whiteFirst, FX_INT32* pattern , FX_INT32 patternLength, CFX_Int32Array &counters)
237 {
238 for (FX_INT32 i = 0; i < counters.GetSize(); i++) {
239 counters.SetAt(i, 0);
240 }
241 FX_BOOL isWhite = whiteFirst;
242 FX_INT32 patternStart = column;
243 FX_INT32 pixelDrift = 0;
244 CFX_Int32Array* intarray = FX_NEW CFX_Int32Array;
245 while (matrix->Get(patternStart, row) && patternStart > 0 && pixelDrift++ < MAX_PIXEL_DRIFT) {
246 patternStart--;
247 }
248 FX_INT32 x = patternStart;
249 FX_INT32 counterPosition = 0;
250 for (; x < width; x++) {
251 FX_BOOL pixel = matrix->Get(x, row);
252 if (pixel ^ isWhite) {
253 counters[counterPosition]++;
254 } else {
255 if (counterPosition == patternLength - 1) {
256 if (patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIA NCE) < MAX_AVG_VARIANCE) {
257 intarray->Add(patternStart);
258 intarray->Add(x);
259 return intarray;
260 }
261 patternStart += counters[0] + counters[1];
262 for (FX_INT32 l = 2, k = 0; l < patternLength; l++, k++) {
263 counters.SetAt(k, counters.GetAt(l));
264 }
265 counters.SetAt(patternLength - 2, 0);
266 counters.SetAt(patternLength - 1, 0);
267 counterPosition--;
268 } else {
269 counterPosition++;
270 }
271 counters[counterPosition] = 1;
272 isWhite = !isWhite;
273 }
274 }
275 if (counterPosition == patternLength - 1) {
276 if (patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE) < M AX_AVG_VARIANCE) {
277 intarray->Add(patternStart);
278 intarray->Add(x - 1);
279 return intarray;
280 }
281 }
282 delete intarray;
283 return NULL;
284 }
285 FX_INT32 CBC_Detector::patternMatchVariance(CFX_Int32Array &counters, FX_INT32* pattern, FX_INT32 maxIndividualVariance)
286 {
287 FX_INT32 numCounters = counters.GetSize();
288 FX_INT32 total = 0;
289 FX_INT32 patternLength = 0;
290 for (FX_INT32 i = 0; i < numCounters; i++) {
291 total += counters[i];
292 patternLength += pattern[i];
293 }
294 if (total < patternLength) {
295 return INTERGER_MAX;
296 }
297 FX_INT32 unitBarWidth = (total << INTEGER_MATH_SHIFT) / patternLength;
298 maxIndividualVariance = (maxIndividualVariance * unitBarWidth) >> INTEGER_MA TH_SHIFT;
299 FX_INT32 totalVariance = 0;
300 for (FX_INT32 x = 0; x < numCounters; x++) {
301 FX_INT32 counter = counters[x] << INTEGER_MATH_SHIFT;
302 FX_INT32 scaledPattern = pattern[x] * unitBarWidth;
303 FX_INT32 variance = counter > scaledPattern ? counter - scaledPattern : scaledPattern - counter;
304 if (variance > maxIndividualVariance) {
305 return INTERGER_MAX;
306 }
307 totalVariance += variance;
308 }
309 return totalVariance / total;
310 }
311
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698