BC_PDF417DetectionResult.cpp revision ac3d58cff7c80b0ef56bf55130d91da17cbaa3c4
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/barcode.h"
24#include "BC_PDF417Codeword.h"
25#include "BC_PDF417BarcodeMetadata.h"
26#include "BC_PDF417BoundingBox.h"
27#include "BC_PDF417DetectionResultColumn.h"
28#include "BC_PDF417Common.h"
29#include "BC_PDF417DetectionResultRowIndicatorColumn.h"
30#include "BC_PDF417DetectionResult.h"
31int32_t CBC_DetectionResult::ADJUST_ROW_NUMBER_SKIP = 2;
32CBC_DetectionResult::CBC_DetectionResult(CBC_BarcodeMetadata* barcodeMetadata,
33                                         CBC_BoundingBox* boundingBox) {
34  m_barcodeMetadata = barcodeMetadata;
35  m_barcodeColumnCount = barcodeMetadata->getColumnCount();
36  m_boundingBox = boundingBox;
37  m_detectionResultColumns.SetSize(m_barcodeColumnCount + 2);
38  for (int32_t i = 0; i < m_barcodeColumnCount + 2; i++) {
39    m_detectionResultColumns[i] = NULL;
40  }
41}
42CBC_DetectionResult::~CBC_DetectionResult() {
43  delete m_boundingBox;
44  delete m_barcodeMetadata;
45  m_detectionResultColumns.RemoveAll();
46}
47CFX_PtrArray& CBC_DetectionResult::getDetectionResultColumns() {
48  adjustIndicatorColumnRowNumbers(
49      (CBC_DetectionResultColumn*)m_detectionResultColumns.GetAt(0));
50  adjustIndicatorColumnRowNumbers(
51      (CBC_DetectionResultColumn*)m_detectionResultColumns.GetAt(
52          m_barcodeColumnCount + 1));
53  int32_t unadjustedCodewordCount = CBC_PDF417Common::MAX_CODEWORDS_IN_BARCODE;
54  int32_t previousUnadjustedCount;
55  do {
56    previousUnadjustedCount = unadjustedCodewordCount;
57    unadjustedCodewordCount = adjustRowNumbers();
58  } while (unadjustedCodewordCount > 0 &&
59           unadjustedCodewordCount < previousUnadjustedCount);
60  return m_detectionResultColumns;
61}
62void CBC_DetectionResult::setBoundingBox(CBC_BoundingBox* boundingBox) {
63  m_boundingBox = boundingBox;
64}
65CBC_BoundingBox* CBC_DetectionResult::getBoundingBox() {
66  return m_boundingBox;
67}
68void CBC_DetectionResult::setDetectionResultColumn(
69    int32_t barcodeColumn,
70    CBC_DetectionResultColumn* detectionResultColumn) {
71  m_detectionResultColumns[barcodeColumn] = detectionResultColumn;
72}
73CBC_DetectionResultColumn* CBC_DetectionResult::getDetectionResultColumn(
74    int32_t barcodeColumn) {
75  return (CBC_DetectionResultColumn*)m_detectionResultColumns[barcodeColumn];
76}
77CFX_ByteString CBC_DetectionResult::toString() {
78  CBC_DetectionResultColumn* rowIndicatorColumn =
79      (CBC_DetectionResultColumn*)m_detectionResultColumns[0];
80  if (rowIndicatorColumn == NULL) {
81    rowIndicatorColumn = (CBC_DetectionResultColumn*)
82        m_detectionResultColumns[m_barcodeColumnCount + 1];
83  }
84  CFX_ByteString result;
85  for (int32_t codewordsRow = 0;
86       codewordsRow < rowIndicatorColumn->getCodewords()->GetSize();
87       codewordsRow++) {
88    result += (FX_CHAR)codewordsRow;
89    for (int32_t barcodeColumn = 0; barcodeColumn < m_barcodeColumnCount + 2;
90         barcodeColumn++) {
91      if (m_detectionResultColumns[barcodeColumn] == NULL) {
92        result += "    |   ";
93        continue;
94      }
95      CBC_Codeword* codeword =
96          (CBC_Codeword*)((CBC_DetectionResultColumn*)
97                              m_detectionResultColumns[barcodeColumn])
98              ->getCodewords()
99              ->GetAt(codewordsRow);
100      if (codeword == NULL) {
101        result += "    |   ";
102        continue;
103      }
104      result += codeword->getRowNumber();
105      result += codeword->getValue();
106    }
107  }
108  return result;
109}
110void CBC_DetectionResult::adjustIndicatorColumnRowNumbers(
111    CBC_DetectionResultColumn* detectionResultColumn) {
112  if (detectionResultColumn != NULL) {
113    ((CBC_DetectionResultRowIndicatorColumn*)detectionResultColumn)
114        ->adjustCompleteIndicatorColumnRowNumbers(*m_barcodeMetadata);
115  }
116}
117int32_t CBC_DetectionResult::adjustRowNumbers() {
118  int32_t unadjustedCount = adjustRowNumbersByRow();
119  if (unadjustedCount == 0) {
120    return 0;
121  }
122  for (int32_t barcodeColumn = 1; barcodeColumn < m_barcodeColumnCount + 1;
123       barcodeColumn++) {
124    CFX_PtrArray* codewords =
125        ((CBC_DetectionResultColumn*)m_detectionResultColumns[barcodeColumn])
126            ->getCodewords();
127    for (int32_t codewordsRow = 0; codewordsRow < codewords->GetSize();
128         codewordsRow++) {
129      if (codewords->GetAt(codewordsRow) == NULL) {
130        continue;
131      }
132      if (!((CBC_Codeword*)codewords->GetAt(codewordsRow))
133               ->hasValidRowNumber()) {
134        adjustRowNumbers(barcodeColumn, codewordsRow, codewords);
135      }
136    }
137  }
138  return unadjustedCount;
139}
140int32_t CBC_DetectionResult::adjustRowNumbersByRow() {
141  adjustRowNumbersFromBothRI();
142  int32_t unadjustedCount = adjustRowNumbersFromLRI();
143  return unadjustedCount + adjustRowNumbersFromRRI();
144}
145int32_t CBC_DetectionResult::adjustRowNumbersFromBothRI() {
146  if (m_detectionResultColumns[0] == NULL ||
147      m_detectionResultColumns[m_barcodeColumnCount + 1] == NULL) {
148    return 0;
149  }
150  CFX_PtrArray* LRIcodewords =
151      ((CBC_DetectionResultColumn*)m_detectionResultColumns[0])->getCodewords();
152  CFX_PtrArray* RRIcodewords =
153      ((CBC_DetectionResultColumn*)
154           m_detectionResultColumns[m_barcodeColumnCount + 1])
155          ->getCodewords();
156  for (int32_t codewordsRow = 0; codewordsRow < LRIcodewords->GetSize();
157       codewordsRow++) {
158    if (LRIcodewords->GetAt(codewordsRow) != NULL &&
159        RRIcodewords->GetAt(codewordsRow) != NULL &&
160        ((CBC_Codeword*)LRIcodewords->GetAt(codewordsRow))->getRowNumber() ==
161            ((CBC_Codeword*)RRIcodewords->GetAt(codewordsRow))
162                ->getRowNumber()) {
163      for (int32_t barcodeColumn = 1; barcodeColumn <= m_barcodeColumnCount;
164           barcodeColumn++) {
165        CBC_Codeword* codeword =
166            (CBC_Codeword*)((CBC_DetectionResultColumn*)
167                                m_detectionResultColumns[barcodeColumn])
168                ->getCodewords()
169                ->GetAt(codewordsRow);
170        if (codeword == NULL) {
171          continue;
172        }
173        codeword->setRowNumber(
174            ((CBC_Codeword*)LRIcodewords->GetAt(codewordsRow))->getRowNumber());
175        if (!codeword->hasValidRowNumber()) {
176          ((CBC_DetectionResultColumn*)m_detectionResultColumns[barcodeColumn])
177              ->getCodewords()
178              ->SetAt(codewordsRow, NULL);
179        }
180      }
181    }
182  }
183  return 0;
184}
185int32_t CBC_DetectionResult::adjustRowNumbersFromRRI() {
186  if (m_detectionResultColumns[m_barcodeColumnCount + 1] == NULL) {
187    return 0;
188  }
189  int32_t unadjustedCount = 0;
190  CFX_PtrArray* codewords =
191      ((CBC_DetectionResultColumn*)m_detectionResultColumns.GetAt(
192           m_barcodeColumnCount + 1))
193          ->getCodewords();
194  for (int32_t codewordsRow = 0; codewordsRow < codewords->GetSize();
195       codewordsRow++) {
196    if (codewords->GetAt(codewordsRow) == NULL) {
197      continue;
198    }
199    int32_t rowIndicatorRowNumber =
200        ((CBC_Codeword*)codewords->GetAt(codewordsRow))->getRowNumber();
201    int32_t invalidRowCounts = 0;
202    for (int32_t barcodeColumn = m_barcodeColumnCount + 1;
203         barcodeColumn > 0 && invalidRowCounts < ADJUST_ROW_NUMBER_SKIP;
204         barcodeColumn--) {
205      CBC_Codeword* codeword =
206          (CBC_Codeword*)((CBC_DetectionResultColumn*)
207                              m_detectionResultColumns.GetAt(barcodeColumn))
208              ->getCodewords()
209              ->GetAt(codewordsRow);
210      if (codeword != NULL) {
211        invalidRowCounts = adjustRowNumberIfValid(rowIndicatorRowNumber,
212                                                  invalidRowCounts, codeword);
213        if (!codeword->hasValidRowNumber()) {
214          unadjustedCount++;
215        }
216      }
217    }
218  }
219  return unadjustedCount;
220}
221int32_t CBC_DetectionResult::adjustRowNumbersFromLRI() {
222  if (m_detectionResultColumns[0] == NULL) {
223    return 0;
224  }
225  int32_t unadjustedCount = 0;
226  CFX_PtrArray* codewords =
227      ((CBC_DetectionResultColumn*)m_detectionResultColumns.GetAt(0))
228          ->getCodewords();
229  for (int32_t codewordsRow = 0; codewordsRow < codewords->GetSize();
230       codewordsRow++) {
231    if (codewords->GetAt(codewordsRow) == NULL) {
232      continue;
233    }
234    int32_t rowIndicatorRowNumber =
235        ((CBC_Codeword*)codewords->GetAt(codewordsRow))->getRowNumber();
236    int32_t invalidRowCounts = 0;
237    for (int32_t barcodeColumn = 1; barcodeColumn < m_barcodeColumnCount + 1 &&
238                                    invalidRowCounts < ADJUST_ROW_NUMBER_SKIP;
239         barcodeColumn++) {
240      CBC_Codeword* codeword =
241          (CBC_Codeword*)((CBC_DetectionResultColumn*)
242                              m_detectionResultColumns[barcodeColumn])
243              ->getCodewords()
244              ->GetAt(codewordsRow);
245      if (codeword != NULL) {
246        invalidRowCounts = adjustRowNumberIfValid(rowIndicatorRowNumber,
247                                                  invalidRowCounts, codeword);
248        if (!codeword->hasValidRowNumber()) {
249          unadjustedCount++;
250        }
251      }
252    }
253  }
254  return unadjustedCount;
255}
256int32_t CBC_DetectionResult::adjustRowNumberIfValid(
257    int32_t rowIndicatorRowNumber,
258    int32_t invalidRowCounts,
259    CBC_Codeword* codeword) {
260  if (codeword == NULL) {
261    return invalidRowCounts;
262  }
263  if (!codeword->hasValidRowNumber()) {
264    if (codeword->isValidRowNumber(rowIndicatorRowNumber)) {
265      codeword->setRowNumber(rowIndicatorRowNumber);
266      invalidRowCounts = 0;
267    } else {
268      ++invalidRowCounts;
269    }
270  }
271  return invalidRowCounts;
272}
273void CBC_DetectionResult::adjustRowNumbers(int32_t barcodeColumn,
274                                           int32_t codewordsRow,
275                                           CFX_PtrArray* codewords) {
276  CBC_Codeword* codeword = (CBC_Codeword*)codewords->GetAt(codewordsRow);
277  CFX_PtrArray* previousColumnCodewords =
278      ((CBC_DetectionResultColumn*)m_detectionResultColumns.GetAt(
279           barcodeColumn - 1))
280          ->getCodewords();
281  CFX_PtrArray* nextColumnCodewords = previousColumnCodewords;
282  if (m_detectionResultColumns[barcodeColumn + 1] != NULL) {
283    nextColumnCodewords = ((CBC_DetectionResultColumn*)
284                               m_detectionResultColumns[barcodeColumn + 1])
285                              ->getCodewords();
286  }
287  CFX_PtrArray otherCodewords;
288  otherCodewords.SetSize(14);
289  otherCodewords[2] = previousColumnCodewords->GetAt(codewordsRow);
290  otherCodewords[3] = nextColumnCodewords->GetAt(codewordsRow);
291  if (codewordsRow > 0) {
292    otherCodewords[0] = codewords->GetAt(codewordsRow - 1);
293    otherCodewords[4] = previousColumnCodewords->GetAt(codewordsRow - 1);
294    otherCodewords[5] = nextColumnCodewords->GetAt(codewordsRow - 1);
295  }
296  if (codewordsRow > 1) {
297    otherCodewords[8] = codewords->GetAt(codewordsRow - 2);
298    otherCodewords[10] = previousColumnCodewords->GetAt(codewordsRow - 2);
299    otherCodewords[11] = nextColumnCodewords->GetAt(codewordsRow - 2);
300  }
301  if (codewordsRow < codewords->GetSize() - 1) {
302    otherCodewords[1] = codewords->GetAt(codewordsRow + 1);
303    otherCodewords[6] = previousColumnCodewords->GetAt(codewordsRow + 1);
304    otherCodewords[7] = nextColumnCodewords->GetAt(codewordsRow + 1);
305  }
306  if (codewordsRow < codewords->GetSize() - 2) {
307    otherCodewords[9] = codewords->GetAt(codewordsRow + 2);
308    otherCodewords[12] = previousColumnCodewords->GetAt(codewordsRow + 2);
309    otherCodewords[13] = nextColumnCodewords->GetAt(codewordsRow + 2);
310  }
311  for (int32_t i = 0; i < otherCodewords.GetSize(); i++) {
312    CBC_Codeword* otherCodeword = (CBC_Codeword*)otherCodewords.GetAt(i);
313    if (adjustRowNumber(codeword, otherCodeword)) {
314      return;
315    }
316  }
317}
318FX_BOOL CBC_DetectionResult::adjustRowNumber(CBC_Codeword* codeword,
319                                             CBC_Codeword* otherCodeword) {
320  if (otherCodeword == NULL) {
321    return FALSE;
322  }
323  if (otherCodeword->hasValidRowNumber() &&
324      otherCodeword->getBucket() == codeword->getBucket()) {
325    codeword->setRowNumber(otherCodeword->getRowNumber());
326    return TRUE;
327  }
328  return FALSE;
329}
330int32_t CBC_DetectionResult::getBarcodeColumnCount() {
331  return m_barcodeColumnCount;
332}
333int32_t CBC_DetectionResult::getBarcodeRowCount() {
334  return m_barcodeMetadata->getRowCount();
335}
336int32_t CBC_DetectionResult::getBarcodeECLevel() {
337  return m_barcodeMetadata->getErrorCorrectionLevel();
338}
339