1 // Copyright 2014 PDFium Authors. All rights reserved.
\r
2 // Use of this source code is governed by a BSD-style license that can be
\r
3 // found in the LICENSE file.
\r
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
\r
8 #include "include/BC_ResultPoint.h"
\r
9 #include "include/BC_PDF417BarcodeMetadata.h"
\r
10 #include "include/BC_PDF417BoundingBox.h"
\r
11 #include "include/BC_PDF417Codeword.h"
\r
12 #include "include/BC_PDF417BarcodeValue.h"
\r
13 #include "include/BC_PDF417Common.h"
\r
14 #include "include/BC_PDF417DetectionResultColumn.h"
\r
15 #include "include/BC_PDF417DetectionResultRowIndicatorColumn.h"
\r
16 CBC_DetectionResultRowIndicatorColumn::CBC_DetectionResultRowIndicatorColumn(CBC_BoundingBox* boundingBox, FX_BOOL isLeft)
\r
17 : CBC_DetectionResultColumn(boundingBox)
\r
21 CBC_DetectionResultRowIndicatorColumn::~CBC_DetectionResultRowIndicatorColumn()
\r
24 void CBC_DetectionResultRowIndicatorColumn::setRowNumbers()
\r
26 for (FX_INT32 i = 0; i < m_codewords->GetSize(); i++) {
\r
27 CBC_Codeword * codeword = (CBC_Codeword*)m_codewords->GetAt(i);
\r
28 if (codeword != NULL) {
\r
29 codeword->setRowNumberAsRowIndicatorColumn();
\r
33 FX_INT32 CBC_DetectionResultRowIndicatorColumn::adjustCompleteIndicatorColumnRowNumbers(CBC_BarcodeMetadata barcodeMetadata)
\r
35 CFX_PtrArray* codewords = getCodewords();
\r
37 removeIncorrectCodewords(codewords, barcodeMetadata);
\r
38 CBC_BoundingBox* boundingBox = getBoundingBox();
\r
39 CBC_ResultPoint* top = m_isLeft ? boundingBox->getTopLeft() : boundingBox->getTopRight();
\r
40 CBC_ResultPoint* bottom = m_isLeft ? boundingBox->getBottomLeft() : boundingBox->getBottomRight();
\r
41 FX_INT32 firstRow = imageRowToCodewordIndex((FX_INT32) top->GetY());
\r
42 FX_INT32 lastRow = imageRowToCodewordIndex((FX_INT32) bottom->GetY());
\r
43 FX_FLOAT averageRowHeight = (lastRow - firstRow) / (FX_FLOAT) barcodeMetadata.getRowCount();
\r
44 FX_INT32 barcodeRow = -1;
\r
45 FX_INT32 maxRowHeight = 1;
\r
46 FX_INT32 currentRowHeight = 0;
\r
47 for (FX_INT32 codewordsRow = firstRow; codewordsRow < lastRow; codewordsRow++) {
\r
48 if (codewords->GetAt(codewordsRow) == NULL) {
\r
51 CBC_Codeword* codeword = (CBC_Codeword*)codewords->GetAt(codewordsRow);
\r
52 FX_INT32 rowDifference = codeword->getRowNumber() - barcodeRow;
\r
53 if (rowDifference == 0) {
\r
55 } else if (rowDifference == 1) {
\r
56 maxRowHeight = maxRowHeight > currentRowHeight ? maxRowHeight : currentRowHeight;
\r
57 currentRowHeight = 1;
\r
58 barcodeRow = codeword->getRowNumber();
\r
59 } else if (rowDifference < 0) {
\r
60 codewords->SetAt(codewordsRow, NULL);
\r
61 } else if (codeword->getRowNumber() >= barcodeMetadata.getRowCount()) {
\r
62 codewords->SetAt(codewordsRow, NULL);
\r
63 } else if (rowDifference > codewordsRow) {
\r
64 codewords->SetAt(codewordsRow, NULL);
\r
66 FX_INT32 checkedRows;
\r
67 if (maxRowHeight > 2) {
\r
68 checkedRows = (maxRowHeight - 2) * rowDifference;
\r
70 checkedRows = rowDifference;
\r
72 FX_BOOL closePreviousCodewordFound = checkedRows >= codewordsRow;
\r
73 for (FX_INT32 i = 1; i <= checkedRows && !closePreviousCodewordFound; i++) {
\r
74 closePreviousCodewordFound = codewords->GetAt(codewordsRow - i) != NULL;
\r
76 if (closePreviousCodewordFound) {
\r
77 codewords->SetAt(codewordsRow, NULL);
\r
79 barcodeRow = codeword->getRowNumber();
\r
80 currentRowHeight = 1;
\r
84 return (FX_INT32) (averageRowHeight + 0.5);
\r
86 CFX_Int32Array* CBC_DetectionResultRowIndicatorColumn::getRowHeights(FX_INT32 &e)
\r
88 CBC_BarcodeMetadata* barcodeMetadata = getBarcodeMetadata();
\r
89 if (barcodeMetadata == NULL) {
\r
90 e = BCExceptionCannotMetadata;
\r
93 adjustIncompleteIndicatorColumnRowNumbers(*barcodeMetadata);
\r
94 CFX_Int32Array* result = FX_NEW CFX_Int32Array;
\r
95 result->SetSize(barcodeMetadata->getRowCount());
\r
96 for (FX_INT32 i = 0; i < getCodewords()->GetSize(); i++) {
\r
97 CBC_Codeword* codeword = (CBC_Codeword*)getCodewords()->GetAt(i);
\r
98 if (codeword != NULL) {
\r
99 result->SetAt(codeword->getRowNumber(), result->GetAt(codeword->getRowNumber()) + 1);
\r
104 FX_INT32 CBC_DetectionResultRowIndicatorColumn::adjustIncompleteIndicatorColumnRowNumbers(CBC_BarcodeMetadata barcodeMetadata)
\r
106 CBC_BoundingBox* boundingBox = getBoundingBox();
\r
107 CBC_ResultPoint* top = m_isLeft ? boundingBox->getTopLeft() : boundingBox->getTopRight();
\r
108 CBC_ResultPoint* bottom = m_isLeft ? boundingBox->getBottomLeft() : boundingBox->getBottomRight();
\r
109 FX_INT32 firstRow = imageRowToCodewordIndex((FX_INT32) top->GetY());
\r
110 FX_INT32 lastRow = imageRowToCodewordIndex((FX_INT32) bottom->GetY());
\r
111 FX_FLOAT averageRowHeight = (lastRow - firstRow) / (FX_FLOAT) barcodeMetadata.getRowCount();
\r
112 CFX_PtrArray* codewords = getCodewords();
\r
113 FX_INT32 barcodeRow = -1;
\r
114 FX_INT32 maxRowHeight = 1;
\r
115 FX_INT32 currentRowHeight = 0;
\r
116 for (FX_INT32 codewordsRow = firstRow; codewordsRow < lastRow; codewordsRow++) {
\r
117 if (codewords->GetAt(codewordsRow) == NULL) {
\r
120 CBC_Codeword* codeword = (CBC_Codeword*)codewords->GetAt(codewordsRow);
\r
121 codeword->setRowNumberAsRowIndicatorColumn();
\r
122 FX_INT32 rowDifference = codeword->getRowNumber() - barcodeRow;
\r
123 if (rowDifference == 0) {
\r
124 currentRowHeight++;
\r
125 } else if (rowDifference == 1) {
\r
126 maxRowHeight = maxRowHeight > currentRowHeight ? maxRowHeight : currentRowHeight;
\r
127 currentRowHeight = 1;
\r
128 barcodeRow = codeword->getRowNumber();
\r
129 } else if (codeword->getRowNumber() >= barcodeMetadata.getRowCount()) {
\r
130 codewords->SetAt(codewordsRow, NULL);
\r
132 barcodeRow = codeword->getRowNumber();
\r
133 currentRowHeight = 1;
\r
136 return (FX_INT32) (averageRowHeight + 0.5);
\r
138 CBC_BarcodeMetadata* CBC_DetectionResultRowIndicatorColumn::getBarcodeMetadata()
\r
140 CFX_PtrArray* codewords = getCodewords();
\r
141 CBC_BarcodeValue barcodeColumnCount;
\r
142 CBC_BarcodeValue barcodeRowCountUpperPart;
\r
143 CBC_BarcodeValue barcodeRowCountLowerPart;
\r
144 CBC_BarcodeValue barcodeECLevel;
\r
145 for (FX_INT32 i = 0; i < codewords->GetSize(); i++) {
\r
146 CBC_Codeword* codeword = (CBC_Codeword*)codewords->GetAt(i);
\r
147 if (codeword == NULL) {
\r
150 codeword->setRowNumberAsRowIndicatorColumn();
\r
151 FX_INT32 rowIndicatorValue = codeword->getValue() % 30;
\r
152 FX_INT32 codewordRowNumber = codeword->getRowNumber();
\r
154 codewordRowNumber += 2;
\r
156 switch (codewordRowNumber % 3) {
\r
158 barcodeRowCountUpperPart.setValue(rowIndicatorValue * 3 + 1);
\r
161 barcodeECLevel.setValue(rowIndicatorValue / 3);
\r
162 barcodeRowCountLowerPart.setValue(rowIndicatorValue % 3);
\r
165 barcodeColumnCount.setValue(rowIndicatorValue + 1);
\r
169 if ((barcodeColumnCount.getValue()->GetSize() == 0) ||
\r
170 (barcodeRowCountUpperPart.getValue()->GetSize() == 0) ||
\r
171 (barcodeRowCountLowerPart.getValue()->GetSize() == 0) ||
\r
172 (barcodeECLevel.getValue()->GetSize() == 0) ||
\r
173 barcodeColumnCount.getValue()->GetAt(0) < 1 ||
\r
174 barcodeRowCountUpperPart.getValue()->GetAt(0) + barcodeRowCountLowerPart.getValue()->GetAt(0) < CBC_PDF417Common::MIN_ROWS_IN_BARCODE ||
\r
175 barcodeRowCountUpperPart.getValue()->GetAt(0) + barcodeRowCountLowerPart.getValue()->GetAt(0) > CBC_PDF417Common::MAX_ROWS_IN_BARCODE) {
\r
178 CBC_BarcodeMetadata* barcodeMetadata = FX_NEW CBC_BarcodeMetadata(barcodeColumnCount.getValue()->GetAt(0), barcodeRowCountUpperPart.getValue()->GetAt(0), barcodeRowCountLowerPart.getValue()->GetAt(0), barcodeECLevel.getValue()->GetAt(0));
\r
179 removeIncorrectCodewords(codewords, *barcodeMetadata);
\r
180 return barcodeMetadata;
\r
182 FX_BOOL CBC_DetectionResultRowIndicatorColumn::isLeft()
\r
186 CFX_ByteString CBC_DetectionResultRowIndicatorColumn::toString()
\r
188 return (CFX_ByteString)"IsLeft: " + (CFX_ByteString)m_isLeft + '\n' + CBC_DetectionResultColumn::toString();
\r
190 void CBC_DetectionResultRowIndicatorColumn::removeIncorrectCodewords(CFX_PtrArray* codewords, CBC_BarcodeMetadata barcodeMetadata)
\r
192 for (FX_INT32 codewordRow = 0; codewordRow < codewords->GetSize(); codewordRow++) {
\r
193 CBC_Codeword* codeword = (CBC_Codeword*)codewords->GetAt(codewordRow);
\r
194 if (codeword == NULL) {
\r
197 FX_INT32 rowIndicatorValue = codeword->getValue() % 30;
\r
198 FX_INT32 codewordRowNumber = codeword->getRowNumber();
\r
199 if (codewordRowNumber > barcodeMetadata.getRowCount()) {
\r
200 codewords->SetAt(codewordRow, NULL);
\r
204 codewordRowNumber += 2;
\r
206 switch (codewordRowNumber % 3) {
\r
208 if (rowIndicatorValue * 3 + 1 != barcodeMetadata.getRowCountUpperPart()) {
\r
209 codewords->SetAt(codewordRow, NULL);
\r
213 if (rowIndicatorValue / 3 != barcodeMetadata.getErrorCorrectionLevel() ||
\r
214 rowIndicatorValue % 3 != barcodeMetadata.getRowCountLowerPart()) {
\r
215 codewords->SetAt(codewordRow, NULL);
\r
219 if (rowIndicatorValue + 1 != barcodeMetadata.getColumnCount()) {
\r
220 codewords->SetAt(codewordRow, NULL);
\r