CFX_PtrArray* CBC_Detector::findVertices(CBC_CommonBitMatrix* matrix, int32_t startRow, int32_t startColumn) { int32_t height = matrix->GetHeight(); int32_t width = matrix->GetWidth(); CFX_PtrArray* result = new CFX_PtrArray; result->SetSize(8); CFX_PtrArray* startptr = findRowsWithPattern( matrix, height, width, startRow, startColumn, START_PATTERN, sizeof(START_PATTERN) / sizeof(START_PATTERN[0])); copyToResult( result, startptr, INDEXES_START_PATTERN, sizeof(INDEXES_START_PATTERN) / sizeof(INDEXES_START_PATTERN[0])); startptr->RemoveAll(); delete startptr; if (result->GetAt(4) != NULL) { startColumn = (int32_t)((CBC_ResultPoint*)result->GetAt(4))->GetX(); startRow = (int32_t)((CBC_ResultPoint*)result->GetAt(4))->GetY(); } CFX_PtrArray* stopptr = findRowsWithPattern( matrix, height, width, startRow, startColumn, STOP_PATTERN, sizeof(STOP_PATTERN) / sizeof(STOP_PATTERN[0])); copyToResult(result, stopptr, INDEXES_STOP_PATTERN, sizeof(INDEXES_STOP_PATTERN) / sizeof(INDEXES_STOP_PATTERN[0])); stopptr->RemoveAll(); delete stopptr; return result; }
void CBC_DetectionResult::adjustRowNumbers(int32_t barcodeColumn, int32_t codewordsRow, CFX_PtrArray* codewords) { CBC_Codeword* codeword = (CBC_Codeword*)codewords->GetAt(codewordsRow); CFX_PtrArray* previousColumnCodewords = ((CBC_DetectionResultColumn*)m_detectionResultColumns.GetAt( barcodeColumn - 1)) ->getCodewords(); CFX_PtrArray* nextColumnCodewords = previousColumnCodewords; if (m_detectionResultColumns[barcodeColumn + 1]) { nextColumnCodewords = ((CBC_DetectionResultColumn*) m_detectionResultColumns[barcodeColumn + 1]) ->getCodewords(); } CFX_PtrArray otherCodewords; otherCodewords.SetSize(14); otherCodewords[2] = previousColumnCodewords->GetAt(codewordsRow); otherCodewords[3] = nextColumnCodewords->GetAt(codewordsRow); if (codewordsRow > 0) { otherCodewords[0] = codewords->GetAt(codewordsRow - 1); otherCodewords[4] = previousColumnCodewords->GetAt(codewordsRow - 1); otherCodewords[5] = nextColumnCodewords->GetAt(codewordsRow - 1); } if (codewordsRow > 1) { otherCodewords[8] = codewords->GetAt(codewordsRow - 2); otherCodewords[10] = previousColumnCodewords->GetAt(codewordsRow - 2); otherCodewords[11] = nextColumnCodewords->GetAt(codewordsRow - 2); } if (codewordsRow < codewords->GetSize() - 1) { otherCodewords[1] = codewords->GetAt(codewordsRow + 1); otherCodewords[6] = previousColumnCodewords->GetAt(codewordsRow + 1); otherCodewords[7] = nextColumnCodewords->GetAt(codewordsRow + 1); } if (codewordsRow < codewords->GetSize() - 2) { otherCodewords[9] = codewords->GetAt(codewordsRow + 2); otherCodewords[12] = previousColumnCodewords->GetAt(codewordsRow + 2); otherCodewords[13] = nextColumnCodewords->GetAt(codewordsRow + 2); } for (int32_t i = 0; i < otherCodewords.GetSize(); i++) { CBC_Codeword* otherCodeword = (CBC_Codeword*)otherCodewords.GetAt(i); if (adjustRowNumber(codeword, otherCodeword)) { return; } } }
CFX_PtrArray* CBC_QRDataBlock::GetDataBlocks( CFX_ByteArray* rawCodewords, CBC_QRCoderVersion* version, CBC_QRCoderErrorCorrectionLevel* ecLevel, int32_t& e) { if (rawCodewords->GetSize() != version->GetTotalCodeWords()) { e = BCExceptionIllegalArgument; BC_EXCEPTION_CHECK_ReturnValue(e, NULL); } CBC_QRCoderECBlocks* ecBlocks = version->GetECBlocksForLevel(ecLevel); int32_t totalBlocks = 0; CFX_PtrArray* ecBlockArray = ecBlocks->GetECBlocks(); int32_t i = 0; for (i = 0; i < ecBlockArray->GetSize(); i++) { totalBlocks += ((CBC_QRCoderECB*)(*ecBlockArray)[i])->GetCount(); } CFX_PtrArray* datablock = new CFX_PtrArray(); datablock->SetSize(totalBlocks); CBC_AutoPtr<CFX_PtrArray> result(datablock); int32_t numResultBlocks = 0; for (int32_t j = 0; j < ecBlockArray->GetSize(); j++) { CBC_QRCoderECB* ecBlock = (CBC_QRCoderECB*)(*ecBlockArray)[j]; for (int32_t k = 0; k < ecBlock->GetCount(); k++) { int32_t numDataCodewords = ecBlock->GetDataCodeWords(); int32_t numBlockCodewords = ecBlocks->GetECCodeWordsPerBlock() + numDataCodewords; CFX_ByteArray* bytearray = new CFX_ByteArray(); bytearray->SetSize(numBlockCodewords); (*result)[numResultBlocks++] = new CBC_QRDataBlock(numDataCodewords, bytearray); } } int32_t shorterBlocksTotalCodewords = ((CBC_QRDataBlock*)(*result)[0])->m_codewords->GetSize(); int32_t longerBlocksStartAt = result->GetSize() - 1; while (longerBlocksStartAt >= 0) { int32_t numCodewords = ((CBC_QRDataBlock*)(*result)[longerBlocksStartAt]) ->m_codewords->GetSize(); if (numCodewords == shorterBlocksTotalCodewords) { break; } longerBlocksStartAt--; } longerBlocksStartAt++; int32_t shorterBlocksNumDataCodewords = shorterBlocksTotalCodewords - ecBlocks->GetECCodeWordsPerBlock(); int32_t rawCodewordsOffset = 0; int32_t x = 0; for (int32_t k = 0; k < shorterBlocksNumDataCodewords; k++) { for (x = 0; x < numResultBlocks; x++) { (*(((CBC_QRDataBlock*)(*result)[x])->m_codewords))[k] = (*rawCodewords)[rawCodewordsOffset++]; } } for (x = longerBlocksStartAt; x < numResultBlocks; x++) { (*(((CBC_QRDataBlock*)(*result)[x]) ->m_codewords))[shorterBlocksNumDataCodewords] = (*rawCodewords)[rawCodewordsOffset++]; } int32_t max = ((CBC_QRDataBlock*)(*result)[0])->m_codewords->GetSize(); for (i = shorterBlocksNumDataCodewords; i < max; i++) { for (int32_t y = 0; y < numResultBlocks; y++) { int32_t iOffset = y < longerBlocksStartAt ? i : i + 1; (*(((CBC_QRDataBlock*)(*result)[y])->m_codewords))[iOffset] = (*rawCodewords)[rawCodewordsOffset++]; } } return result.release(); }
CFX_PtrArray* CBC_Detector::findRowsWithPattern(CBC_CommonBitMatrix* matrix, int32_t height, int32_t width, int32_t startRow, int32_t startColumn, int32_t* pattern, int32_t patternLength) { CFX_PtrArray* result = new CFX_PtrArray; result->SetSize(4); FX_BOOL found = FALSE; CFX_Int32Array counters; counters.SetSize(patternLength); for (; startRow < height; startRow += ROW_STEP) { CFX_Int32Array* loc = findGuardPattern(matrix, startColumn, startRow, width, FALSE, pattern, patternLength, counters); if (loc != NULL) { while (startRow > 0) { CFX_Int32Array* previousRowLoc = findGuardPattern(matrix, startColumn, --startRow, width, FALSE, pattern, patternLength, counters); if (previousRowLoc != NULL) { delete loc; loc = previousRowLoc; } else { startRow++; break; } } result->SetAt( 0, new CBC_ResultPoint((FX_FLOAT)loc->GetAt(0), (FX_FLOAT)startRow)); result->SetAt( 1, new CBC_ResultPoint((FX_FLOAT)loc->GetAt(1), (FX_FLOAT)startRow)); found = TRUE; delete loc; break; } } int32_t stopRow = startRow + 1; if (found) { int32_t skippedRowCount = 0; CFX_Int32Array previousRowLoc; previousRowLoc.Add((int32_t)((CBC_ResultPoint*)result->GetAt(0))->GetX()); previousRowLoc.Add((int32_t)((CBC_ResultPoint*)result->GetAt(1))->GetX()); for (; stopRow < height; stopRow++) { CFX_Int32Array* loc = findGuardPattern(matrix, previousRowLoc[0], stopRow, width, FALSE, pattern, patternLength, counters); if (loc != NULL && abs(previousRowLoc[0] - loc->GetAt(0)) < MAX_PATTERN_DRIFT && abs(previousRowLoc[1] - loc->GetAt(1)) < MAX_PATTERN_DRIFT) { previousRowLoc.Copy(*loc); skippedRowCount = 0; } else { if (skippedRowCount > SKIPPED_ROW_COUNT_MAX) { delete loc; break; } else { skippedRowCount++; } } delete loc; } stopRow -= skippedRowCount + 1; result->SetAt(2, new CBC_ResultPoint((FX_FLOAT)previousRowLoc.GetAt(0), (FX_FLOAT)stopRow)); result->SetAt(3, new CBC_ResultPoint((FX_FLOAT)previousRowLoc.GetAt(1), (FX_FLOAT)stopRow)); } if (stopRow - startRow < BARCODE_MIN_HEIGHT) { for (int32_t i = 0; i < result->GetSize(); i++) { result->SetAt(i, NULL); } } return result; }
CBC_QRDetectorResult* CBC_DataMatrixDetector::Detect(int32_t& e) { CFX_PtrArray* cornerPoints = m_rectangleDetector->Detect(e); BC_EXCEPTION_CHECK_ReturnValue(e, NULL); CBC_ResultPoint* pointA = (CBC_ResultPoint*)(*cornerPoints)[0]; CBC_ResultPoint* pointB = (CBC_ResultPoint*)(*cornerPoints)[1]; CBC_ResultPoint* pointC = (CBC_ResultPoint*)(*cornerPoints)[2]; CBC_ResultPoint* pointD = (CBC_ResultPoint*)(*cornerPoints)[3]; delete cornerPoints; cornerPoints = NULL; CFX_PtrArray transitions; transitions.Add(TransitionsBetween(pointA, pointB)); transitions.Add(TransitionsBetween(pointA, pointC)); transitions.Add(TransitionsBetween(pointB, pointD)); transitions.Add(TransitionsBetween(pointC, pointD)); BC_FX_PtrArray_Sort(transitions, &ResultPointsAndTransitionsComparator); delete ((CBC_ResultPointsAndTransitions*)transitions[2]); delete ((CBC_ResultPointsAndTransitions*)transitions[3]); CBC_ResultPointsAndTransitions* lSideOne = (CBC_ResultPointsAndTransitions*)transitions[0]; CBC_ResultPointsAndTransitions* lSideTwo = (CBC_ResultPointsAndTransitions*)transitions[1]; CFX_MapPtrTemplate<CBC_ResultPoint*, int32_t> pointCount; Increment(pointCount, lSideOne->GetFrom()); Increment(pointCount, lSideOne->GetTo()); Increment(pointCount, lSideTwo->GetFrom()); Increment(pointCount, lSideTwo->GetTo()); delete ((CBC_ResultPointsAndTransitions*)transitions[1]); delete ((CBC_ResultPointsAndTransitions*)transitions[0]); transitions.RemoveAll(); CBC_ResultPoint* maybeTopLeft = NULL; CBC_ResultPoint* bottomLeft = NULL; CBC_ResultPoint* maybeBottomRight = NULL; FX_POSITION itBegin = pointCount.GetStartPosition(); while (itBegin != NULL) { CBC_ResultPoint* key = 0; int32_t value = 0; pointCount.GetNextAssoc(itBegin, key, value); if (value == 2) { bottomLeft = key; } else { if (maybeBottomRight == NULL) { maybeBottomRight = key; } else { maybeTopLeft = key; } } } if (maybeTopLeft == NULL || bottomLeft == NULL || maybeBottomRight == NULL) { delete pointA; delete pointB; delete pointC; delete pointD; e = BCExceptionNotFound; return NULL; } CFX_PtrArray corners; corners.SetSize(3); corners[0] = maybeTopLeft; corners[1] = bottomLeft; corners[2] = maybeBottomRight; OrderBestPatterns(&corners); CBC_ResultPoint* bottomRight = (CBC_ResultPoint*)corners[0]; bottomLeft = (CBC_ResultPoint*)corners[1]; CBC_ResultPoint* topLeft = (CBC_ResultPoint*)corners[2]; CBC_ResultPoint* topRight = NULL; int32_t value; if (!pointCount.Lookup(pointA, value)) { topRight = pointA; } else if (!pointCount.Lookup(pointB, value)) { topRight = pointB; } else if (!pointCount.Lookup(pointC, value)) { topRight = pointC; } else { topRight = pointD; } int32_t dimensionTop = CBC_AutoPtr<CBC_ResultPointsAndTransitions>( TransitionsBetween(topLeft, topRight)) ->GetTransitions(); int32_t dimensionRight = CBC_AutoPtr<CBC_ResultPointsAndTransitions>( TransitionsBetween(bottomRight, topRight)) ->GetTransitions(); if ((dimensionTop & 0x01) == 1) { dimensionTop++; } dimensionTop += 2; if ((dimensionRight & 0x01) == 1) { dimensionRight++; } dimensionRight += 2; CBC_AutoPtr<CBC_CommonBitMatrix> bits(NULL); CBC_AutoPtr<CBC_ResultPoint> correctedTopRight(NULL); if (4 * dimensionTop >= 7 * dimensionRight || 4 * dimensionRight >= 7 * dimensionTop) { correctedTopRight = CBC_AutoPtr<CBC_ResultPoint>( CorrectTopRightRectangular(bottomLeft, bottomRight, topLeft, topRight, dimensionTop, dimensionRight)); if (correctedTopRight.get() == NULL) { correctedTopRight = CBC_AutoPtr<CBC_ResultPoint>(topRight); } else { delete topRight; topRight = NULL; } dimensionTop = CBC_AutoPtr<CBC_ResultPointsAndTransitions>( TransitionsBetween(topLeft, correctedTopRight.get())) ->GetTransitions(); dimensionRight = CBC_AutoPtr<CBC_ResultPointsAndTransitions>( TransitionsBetween(bottomRight, correctedTopRight.get())) ->GetTransitions(); if ((dimensionTop & 0x01) == 1) { dimensionTop++; } if ((dimensionRight & 0x01) == 1) { dimensionRight++; } bits = CBC_AutoPtr<CBC_CommonBitMatrix>( SampleGrid(m_image, topLeft, bottomLeft, bottomRight, correctedTopRight.get(), dimensionTop, dimensionRight, e)); BC_EXCEPTION_CHECK_ReturnValue(e, NULL); } else { int32_t dimension = std::min(dimensionRight, dimensionTop); correctedTopRight = CBC_AutoPtr<CBC_ResultPoint>( CorrectTopRight(bottomLeft, bottomRight, topLeft, topRight, dimension)); if (correctedTopRight.get() == NULL) { correctedTopRight = CBC_AutoPtr<CBC_ResultPoint>(topRight); } else { delete topRight; topRight = NULL; } int32_t dimensionCorrected = std::max(CBC_AutoPtr<CBC_ResultPointsAndTransitions>( TransitionsBetween(topLeft, correctedTopRight.get())) ->GetTransitions(), CBC_AutoPtr<CBC_ResultPointsAndTransitions>( TransitionsBetween(bottomRight, correctedTopRight.get())) ->GetTransitions()); dimensionCorrected++; if ((dimensionCorrected & 0x01) == 1) { dimensionCorrected++; } bits = CBC_AutoPtr<CBC_CommonBitMatrix>(SampleGrid( m_image, topLeft, bottomLeft, bottomRight, correctedTopRight.get(), dimensionCorrected, dimensionCorrected, e)); BC_EXCEPTION_CHECK_ReturnValue(e, NULL); } CFX_PtrArray* result = new CFX_PtrArray; result->SetSize(4); result->Add(topLeft); result->Add(bottomLeft); result->Add(bottomRight); result->Add(correctedTopRight.release()); return new CBC_QRDetectorResult(bits.release(), result); }