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