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

Side by Side Diff: xfa/src/fxbarcode/pdf417/BC_PDF417Detector.cpp

Issue 1803723002: Move xfa/src up to xfa/. (Closed) Base URL: https://pdfium.googlesource.com/pdfium.git@master
Patch Set: Rebase to master Created 4 years, 9 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 "xfa/src/fxbarcode/BC_BinaryBitmap.h"
24 #include "xfa/src/fxbarcode/BC_ResultPoint.h"
25 #include "xfa/src/fxbarcode/common/BC_CommonBitArray.h"
26 #include "xfa/src/fxbarcode/common/BC_CommonBitMatrix.h"
27 #include "xfa/src/fxbarcode/pdf417/BC_PDF417Detector.h"
28 #include "xfa/src/fxbarcode/pdf417/BC_PDF417DetectorResult.h"
29 #include "xfa/src/fxbarcode/utils.h"
30
31 #define INTEGER_MAX 2147483647
32
33 int32_t CBC_Detector::INDEXES_START_PATTERN[] = {0, 4, 1, 5};
34 int32_t CBC_Detector::INDEXES_STOP_PATTERN[] = {6, 2, 7, 3};
35 int32_t CBC_Detector::INTEGER_MATH_SHIFT = 8;
36 int32_t CBC_Detector::PATTERN_MATCH_RESULT_SCALE_FACTOR = 1
37 << INTEGER_MATH_SHIFT;
38 int32_t CBC_Detector::MAX_AVG_VARIANCE =
39 (int32_t)(PATTERN_MATCH_RESULT_SCALE_FACTOR * 0.42f);
40 int32_t CBC_Detector::MAX_INDIVIDUAL_VARIANCE =
41 (int32_t)(PATTERN_MATCH_RESULT_SCALE_FACTOR * 0.8f);
42 int32_t CBC_Detector::START_PATTERN[] = {8, 1, 1, 1, 1, 1, 1, 3};
43 int32_t CBC_Detector::STOP_PATTERN[] = {7, 1, 1, 3, 1, 1, 1, 2, 1};
44 int32_t CBC_Detector::MAX_PIXEL_DRIFT = 3;
45 int32_t CBC_Detector::MAX_PATTERN_DRIFT = 5;
46 int32_t CBC_Detector::SKIPPED_ROW_COUNT_MAX = 25;
47 int32_t CBC_Detector::ROW_STEP = 5;
48 int32_t CBC_Detector::BARCODE_MIN_HEIGHT = 10;
49
50 CBC_Detector::CBC_Detector() {}
51 CBC_Detector::~CBC_Detector() {}
52 CBC_PDF417DetectorResult* CBC_Detector::detect(CBC_BinaryBitmap* image,
53 int32_t hints,
54 FX_BOOL multiple,
55 int32_t& e) {
56 CBC_CommonBitMatrix* bitMatrix = image->GetBlackMatrix(e);
57 BC_EXCEPTION_CHECK_ReturnValue(e, NULL);
58 CFX_PtrArray* barcodeCoordinates = detect(multiple, bitMatrix);
59 if (barcodeCoordinates->GetSize() == 0) {
60 rotate180(bitMatrix);
61 barcodeCoordinates = detect(multiple, bitMatrix);
62 }
63 if (barcodeCoordinates->GetSize() == 0) {
64 e = BCExceptionUnSupportedBarcode;
65 BC_EXCEPTION_CHECK_ReturnValue(e, NULL);
66 }
67 CBC_PDF417DetectorResult* detectorResult =
68 new CBC_PDF417DetectorResult(bitMatrix, barcodeCoordinates);
69 return detectorResult;
70 }
71 void CBC_Detector::rotate180(CBC_CommonBitMatrix* bitMatrix) {
72 int32_t width = bitMatrix->GetWidth();
73 int32_t height = bitMatrix->GetHeight();
74 CBC_CommonBitArray* firstRowBitArray = new CBC_CommonBitArray(width);
75 CBC_CommonBitArray* secondRowBitArray = new CBC_CommonBitArray(width);
76 CBC_CommonBitArray* tmpBitArray = new CBC_CommonBitArray(width);
77 for (int32_t y = 0; y<(height + 1)>> 1; y++) {
78 CBC_CommonBitArray* temp =
79 bitMatrix->GetRow(height - 1 - y, secondRowBitArray);
80 CBC_CommonBitArray* tempfirstRow = firstRowBitArray;
81 firstRowBitArray = bitMatrix->GetRow(y, tempfirstRow);
82 delete tempfirstRow;
83 CBC_CommonBitArray* row = mirror(temp, tmpBitArray);
84 delete temp;
85 bitMatrix->SetRow(y, row);
86 delete row;
87 CBC_CommonBitArray* rowfirstRow = mirror(firstRowBitArray, tmpBitArray);
88 bitMatrix->SetRow(height - 1 - y, rowfirstRow);
89 delete rowfirstRow;
90 }
91 delete tmpBitArray;
92 delete firstRowBitArray;
93 delete secondRowBitArray;
94 }
95 CBC_CommonBitArray* CBC_Detector::mirror(CBC_CommonBitArray* input,
96 CBC_CommonBitArray* result) {
97 CBC_CommonBitArray* array = new CBC_CommonBitArray(result->GetSize());
98 array->Clear();
99 int32_t size = input->GetSize();
100 for (int32_t i = 0; i < size; i++) {
101 if (input->Get(i)) {
102 array->Set(size - 1 - i);
103 }
104 }
105 return array;
106 }
107 CFX_PtrArray* CBC_Detector::detect(FX_BOOL multiple,
108 CBC_CommonBitMatrix* bitMatrix) {
109 CFX_PtrArray* barcodeCoordinates = new CFX_PtrArray;
110 int32_t row = 0;
111 int32_t column = 0;
112 FX_BOOL foundBarcodeInRow = FALSE;
113 while (row < bitMatrix->GetHeight()) {
114 CFX_PtrArray* vertices = findVertices(bitMatrix, row, column);
115 if (vertices->GetAt(0) == NULL && vertices->GetAt(3) == NULL) {
116 if (!foundBarcodeInRow) {
117 if (vertices) {
118 delete (vertices);
119 }
120 break;
121 }
122 foundBarcodeInRow = FALSE;
123 column = 0;
124 for (int32_t i = 0; i < barcodeCoordinates->GetSize(); i++) {
125 CFX_PtrArray* barcodeCoordinate =
126 (CFX_PtrArray*)barcodeCoordinates->GetAt(i);
127 if (barcodeCoordinate->GetAt(1)) {
128 row = row > ((CBC_ResultPoint*)barcodeCoordinate->GetAt(1))->GetY();
129 }
130 if (barcodeCoordinate->GetAt(3)) {
131 row = row > ((CBC_ResultPoint*)barcodeCoordinate->GetAt(3))->GetY();
132 }
133 }
134 row += ROW_STEP;
135 if (vertices) {
136 delete (vertices);
137 }
138 continue;
139 }
140 foundBarcodeInRow = TRUE;
141 barcodeCoordinates->Add(vertices);
142 if (!multiple) {
143 break;
144 }
145 if (vertices->GetAt(2)) {
146 column = (int32_t)((CBC_ResultPoint*)vertices->GetAt(2))->GetX();
147 row = (int32_t)((CBC_ResultPoint*)vertices->GetAt(2))->GetY();
148 } else {
149 column = (int32_t)((CBC_ResultPoint*)vertices->GetAt(4))->GetX();
150 row = (int32_t)((CBC_ResultPoint*)vertices->GetAt(4))->GetY();
151 }
152 }
153 return barcodeCoordinates;
154 }
155 CFX_PtrArray* CBC_Detector::findVertices(CBC_CommonBitMatrix* matrix,
156 int32_t startRow,
157 int32_t startColumn) {
158 int32_t height = matrix->GetHeight();
159 int32_t width = matrix->GetWidth();
160 CFX_PtrArray* result = new CFX_PtrArray;
161 result->SetSize(8);
162 CFX_PtrArray* startptr = findRowsWithPattern(
163 matrix, height, width, startRow, startColumn, START_PATTERN,
164 sizeof(START_PATTERN) / sizeof(START_PATTERN[0]));
165 copyToResult(
166 result, startptr, INDEXES_START_PATTERN,
167 sizeof(INDEXES_START_PATTERN) / sizeof(INDEXES_START_PATTERN[0]));
168 startptr->RemoveAll();
169 delete startptr;
170 if (result->GetAt(4)) {
171 startColumn = (int32_t)((CBC_ResultPoint*)result->GetAt(4))->GetX();
172 startRow = (int32_t)((CBC_ResultPoint*)result->GetAt(4))->GetY();
173 }
174 CFX_PtrArray* stopptr = findRowsWithPattern(
175 matrix, height, width, startRow, startColumn, STOP_PATTERN,
176 sizeof(STOP_PATTERN) / sizeof(STOP_PATTERN[0]));
177 copyToResult(result, stopptr, INDEXES_STOP_PATTERN,
178 sizeof(INDEXES_STOP_PATTERN) / sizeof(INDEXES_STOP_PATTERN[0]));
179 stopptr->RemoveAll();
180 delete stopptr;
181 return result;
182 }
183 void CBC_Detector::copyToResult(CFX_PtrArray* result,
184 CFX_PtrArray* tmpResult,
185 int32_t* destinationIndexes,
186 int32_t destinationLength) {
187 for (int32_t i = 0; i < destinationLength; i++) {
188 result->SetAt(destinationIndexes[i], tmpResult->GetAt(i));
189 }
190 }
191 CFX_PtrArray* CBC_Detector::findRowsWithPattern(CBC_CommonBitMatrix* matrix,
192 int32_t height,
193 int32_t width,
194 int32_t startRow,
195 int32_t startColumn,
196 int32_t* pattern,
197 int32_t patternLength) {
198 CFX_PtrArray* result = new CFX_PtrArray;
199 result->SetSize(4);
200 FX_BOOL found = FALSE;
201 CFX_Int32Array counters;
202 counters.SetSize(patternLength);
203 for (; startRow < height; startRow += ROW_STEP) {
204 CFX_Int32Array* loc =
205 findGuardPattern(matrix, startColumn, startRow, width, FALSE, pattern,
206 patternLength, counters);
207 if (loc) {
208 while (startRow > 0) {
209 CFX_Int32Array* previousRowLoc =
210 findGuardPattern(matrix, startColumn, --startRow, width, FALSE,
211 pattern, patternLength, counters);
212 if (previousRowLoc) {
213 delete loc;
214 loc = previousRowLoc;
215 } else {
216 startRow++;
217 break;
218 }
219 }
220 result->SetAt(
221 0, new CBC_ResultPoint((FX_FLOAT)loc->GetAt(0), (FX_FLOAT)startRow));
222 result->SetAt(
223 1, new CBC_ResultPoint((FX_FLOAT)loc->GetAt(1), (FX_FLOAT)startRow));
224 found = TRUE;
225 delete loc;
226 break;
227 }
228 }
229 int32_t stopRow = startRow + 1;
230 if (found) {
231 int32_t skippedRowCount = 0;
232 CFX_Int32Array previousRowLoc;
233 previousRowLoc.Add((int32_t)((CBC_ResultPoint*)result->GetAt(0))->GetX());
234 previousRowLoc.Add((int32_t)((CBC_ResultPoint*)result->GetAt(1))->GetX());
235 for (; stopRow < height; stopRow++) {
236 CFX_Int32Array* loc =
237 findGuardPattern(matrix, previousRowLoc[0], stopRow, width, FALSE,
238 pattern, patternLength, counters);
239 if (loc && abs(previousRowLoc[0] - loc->GetAt(0)) < MAX_PATTERN_DRIFT &&
240 abs(previousRowLoc[1] - loc->GetAt(1)) < MAX_PATTERN_DRIFT) {
241 previousRowLoc.Copy(*loc);
242 skippedRowCount = 0;
243 } else {
244 if (skippedRowCount > SKIPPED_ROW_COUNT_MAX) {
245 delete loc;
246 break;
247 } else {
248 skippedRowCount++;
249 }
250 }
251 delete loc;
252 }
253 stopRow -= skippedRowCount + 1;
254 result->SetAt(2, new CBC_ResultPoint((FX_FLOAT)previousRowLoc.GetAt(0),
255 (FX_FLOAT)stopRow));
256 result->SetAt(3, new CBC_ResultPoint((FX_FLOAT)previousRowLoc.GetAt(1),
257 (FX_FLOAT)stopRow));
258 }
259 if (stopRow - startRow < BARCODE_MIN_HEIGHT) {
260 for (int32_t i = 0; i < result->GetSize(); i++) {
261 result->SetAt(i, NULL);
262 }
263 }
264 return result;
265 }
266 CFX_Int32Array* CBC_Detector::findGuardPattern(CBC_CommonBitMatrix* matrix,
267 int32_t column,
268 int32_t row,
269 int32_t width,
270 FX_BOOL whiteFirst,
271 int32_t* pattern,
272 int32_t patternLength,
273 CFX_Int32Array& counters) {
274 for (int32_t i = 0; i < counters.GetSize(); i++) {
275 counters.SetAt(i, 0);
276 }
277 FX_BOOL isWhite = whiteFirst;
278 int32_t patternStart = column;
279 int32_t pixelDrift = 0;
280 CFX_Int32Array* intarray = new CFX_Int32Array;
281 while (matrix->Get(patternStart, row) && patternStart > 0 &&
282 pixelDrift++ < MAX_PIXEL_DRIFT) {
283 patternStart--;
284 }
285 int32_t x = patternStart;
286 int32_t counterPosition = 0;
287 for (; x < width; x++) {
288 FX_BOOL pixel = matrix->Get(x, row);
289 if (pixel ^ isWhite) {
290 counters[counterPosition]++;
291 } else {
292 if (counterPosition == patternLength - 1) {
293 if (patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE) <
294 MAX_AVG_VARIANCE) {
295 intarray->Add(patternStart);
296 intarray->Add(x);
297 return intarray;
298 }
299 patternStart += counters[0] + counters[1];
300 for (int32_t l = 2, k = 0; l < patternLength; l++, k++) {
301 counters.SetAt(k, counters.GetAt(l));
302 }
303 counters.SetAt(patternLength - 2, 0);
304 counters.SetAt(patternLength - 1, 0);
305 counterPosition--;
306 } else {
307 counterPosition++;
308 }
309 counters[counterPosition] = 1;
310 isWhite = !isWhite;
311 }
312 }
313 if (counterPosition == patternLength - 1) {
314 if (patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE) <
315 MAX_AVG_VARIANCE) {
316 intarray->Add(patternStart);
317 intarray->Add(x - 1);
318 return intarray;
319 }
320 }
321 delete intarray;
322 return NULL;
323 }
324 int32_t CBC_Detector::patternMatchVariance(CFX_Int32Array& counters,
325 int32_t* pattern,
326 int32_t maxIndividualVariance) {
327 int32_t numCounters = counters.GetSize();
328 int32_t total = 0;
329 int32_t patternLength = 0;
330 for (int32_t i = 0; i < numCounters; i++) {
331 total += counters[i];
332 patternLength += pattern[i];
333 }
334 if (total < patternLength) {
335 return INTEGER_MAX;
336 }
337 int32_t unitBarWidth = (total << INTEGER_MATH_SHIFT) / patternLength;
338 maxIndividualVariance =
339 (maxIndividualVariance * unitBarWidth) >> INTEGER_MATH_SHIFT;
340 int32_t totalVariance = 0;
341 for (int32_t x = 0; x < numCounters; x++) {
342 int32_t counter = counters[x] << INTEGER_MATH_SHIFT;
343 int32_t scaledPattern = pattern[x] * unitBarWidth;
344 int32_t variance = counter > scaledPattern ? counter - scaledPattern
345 : scaledPattern - counter;
346 if (variance > maxIndividualVariance) {
347 return INTEGER_MAX;
348 }
349 totalVariance += variance;
350 }
351 return totalVariance / total;
352 }
OLDNEW
« no previous file with comments | « xfa/src/fxbarcode/pdf417/BC_PDF417Detector.h ('k') | xfa/src/fxbarcode/pdf417/BC_PDF417DetectorResult.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698