Beispiel #1
0
        /// <summary>
        /// Returns a <see cref="System.String"/> that represents the current <see cref="ZXing.PDF417.Internal.DetectionResult"/>.
        /// </summary>
        /// <returns>A <see cref="System.String"/> that represents the current <see cref="ZXing.PDF417.Internal.DetectionResult"/>.</returns>
        public override string ToString()
        {
            StringBuilder         formatter          = new StringBuilder();
            DetectionResultColumn rowIndicatorColumn = DetectionResultColumns[0];

            if (rowIndicatorColumn == null)
            {
                rowIndicatorColumn = DetectionResultColumns[ColumnCount + 1];
            }
            for (int codewordsRow = 0; codewordsRow < rowIndicatorColumn.Codewords.Length; codewordsRow++)
            {
                formatter.AppendFormat(CultureInfo.InvariantCulture, "CW {0,3}:", codewordsRow);
                for (int barcodeColumn = 0; barcodeColumn < ColumnCount + 2; barcodeColumn++)
                {
                    if (DetectionResultColumns[barcodeColumn] == null)
                    {
                        formatter.Append("    |   ");
                        continue;
                    }
                    Codeword codeword = DetectionResultColumns[barcodeColumn].Codewords[codewordsRow];
                    if (codeword == null)
                    {
                        formatter.Append("    |   ");
                        continue;
                    }
                    formatter.AppendFormat(CultureInfo.InvariantCulture, " {0,3}|{1,3}", codeword.RowNumber, codeword.Value);
                }
                formatter.Append("\n");
            }

            return(formatter.ToString());
        }
Beispiel #2
0
        /// <summary>
        /// Gets the codeword closest to the specified row in the image
        /// </summary>
        /// <param name="imageRow">Image row.</param>
        public Codeword GetCodewordNearby(int imageRow)
        {
            Codeword codeword = GetCodeword(imageRow);

            if (codeword == null)
            {
                int index = IndexForRow(imageRow);

                // TODO verify that this LINQ works the same?
                // Codeword nearestCW = Codewords[(from n in Codewords.Select((cw, n) => n) where Codewords[n] != null select n).Aggregate((x, y) => Math.Abs(x - index) > Math.Abs(y - index) ? x : y)];

                int nearby;
                for (int i = 1; i < MAX_NEARBY_DISTANCE; i++)
                {
                    nearby = index - i;
                    if (nearby >= 0)
                    {
                        codeword = Codewords[nearby];
                        if (codeword != null)
                        {
                            break;
                        }
                    }

                    nearby = index + i;
                    if (nearby < Codewords.Length)
                    {
                        codeword = Codewords[nearby];
                        break;
                    }
                }
            }
            return(codeword);
        }
Beispiel #3
0
 /// <summary>
 /// Adjusts the row numbers from both Row Indicators
 /// </summary>
 /// <returns> zero </returns>
 private void adjustRowNumbersFromBothRI()
 {
     if (DetectionResultColumns[0] == null || DetectionResultColumns[ColumnCount + 1] == null)
     {
         return;
     }
     Codeword[] LRIcodewords = DetectionResultColumns[0].Codewords;
     Codeword[] RRIcodewords = DetectionResultColumns[ColumnCount + 1].Codewords;
     for (int codewordsRow = 0; codewordsRow < LRIcodewords.Length; codewordsRow++)
     {
         if (LRIcodewords[codewordsRow] != null &&
             RRIcodewords[codewordsRow] != null &&
             LRIcodewords[codewordsRow].RowNumber == RRIcodewords[codewordsRow].RowNumber)
         {
             for (int barcodeColumn = 1; barcodeColumn <= ColumnCount; barcodeColumn++)
             {
                 Codeword codeword = DetectionResultColumns[barcodeColumn].Codewords[codewordsRow];
                 if (codeword == null)
                 {
                     continue;
                 }
                 codeword.RowNumber = LRIcodewords[codewordsRow].RowNumber;
                 if (!codeword.HasValidRowNumber)
                 {
                     // LOG.info("Removing codeword with invalid row number, cw[" + codewordsRow + "][" + barcodeColumn + "]");
                     DetectionResultColumns[barcodeColumn].Codewords[codewordsRow] = null;
                 }
             }
         }
     }
 }
Beispiel #4
0
        /// <summary>
        /// Adjusts the row numbers from Left Row Indicator.
        /// </summary>
        /// <returns> Unadjusted row Count.</returns>
        private int adjustRowNumbersFromLRI()
        {
            if (DetectionResultColumns[0] == null)
            {
                return(0);
            }
            int unadjustedCount = 0;

            Codeword[] codewords = DetectionResultColumns[0].Codewords;
            for (int codewordsRow = 0; codewordsRow < codewords.Length; codewordsRow++)
            {
                if (codewords[codewordsRow] == null)
                {
                    continue;
                }
                int rowIndicatorRowNumber = codewords[codewordsRow].RowNumber;
                int invalidRowCounts      = 0;
                for (int barcodeColumn = 1; barcodeColumn < ColumnCount + 1 && invalidRowCounts < ADJUST_ROW_NUMBER_SKIP; barcodeColumn++)
                {
                    Codeword codeword = DetectionResultColumns[barcodeColumn].Codewords[codewordsRow];
                    if (codeword != null)
                    {
                        invalidRowCounts = adjustRowNumberIfValid(rowIndicatorRowNumber, invalidRowCounts, codeword);
                        if (!codeword.HasValidRowNumber)
                        {
                            unadjustedCount++;
                        }
                    }
                }
            }
            return(unadjustedCount);
        }
        /// <summary>
        /// Gets the codeword closest to the specified row in the image
        /// </summary>
        /// <param name="imageRow">Image row.</param>
        public Codeword getCodewordNearby(int imageRow)
        {
            Codeword codeword = getCodeword(imageRow);

            if (codeword != null)
            {
                return(codeword);
            }
            for (int i = 1; i < MAX_NEARBY_DISTANCE; i++)
            {
                int nearImageRow = imageRowToCodewordIndex(imageRow) - i;
                if (nearImageRow >= 0)
                {
                    codeword = Codewords[nearImageRow];
                    if (codeword != null)
                    {
                        return(codeword);
                    }
                }
                nearImageRow = imageRowToCodewordIndex(imageRow) + i;
                if (nearImageRow < Codewords.Length)
                {
                    codeword = Codewords[nearImageRow];
                    if (codeword != null)
                    {
                        return(codeword);
                    }
                }
            }
            return(null);
        }
        /// <summary>
        /// Gets the row indicator column.
        /// </summary>
        /// <returns>The row indicator column.</returns>
        /// <param name="image">Image.</param>
        /// <param name="boundingBox">Bounding box.</param>
        /// <param name="startPoint">Start point.</param>
        /// <param name="leftToRight">If set to <c>true</c> left to right.</param>
        /// <param name="minCodewordWidth">Minimum codeword width.</param>
        /// <param name="maxCodewordWidth">Max codeword width.</param>
        private static DetectionResultRowIndicatorColumn getRowIndicatorColumn(BitMatrix image,
                                                                               BoundingBox boundingBox,
                                                                               ResultPoint startPoint,
                                                                               bool leftToRight,
                                                                               int minCodewordWidth,
                                                                               int maxCodewordWidth)
        {
            DetectionResultRowIndicatorColumn rowIndicatorColumn = new DetectionResultRowIndicatorColumn(boundingBox, leftToRight);

            for (int i = 0; i < 2; i++)
            {
                int increment   = i == 0 ? 1 : -1;
                int startColumn = (int)startPoint.X;
                for (int imageRow = (int)startPoint.Y; imageRow <= boundingBox.MaxY &&
                     imageRow >= boundingBox.MinY; imageRow += increment)
                {
                    Codeword codeword = detectCodeword(image, 0, image.Width, leftToRight, startColumn, imageRow,
                                                       minCodewordWidth, maxCodewordWidth);
                    if (codeword != null)
                    {
                        rowIndicatorColumn.setCodeword(imageRow, codeword);
                        if (leftToRight)
                        {
                            startColumn = codeword.StartX;
                        }
                        else
                        {
                            startColumn = codeword.EndX;
                        }
                    }
                }
            }
            return(rowIndicatorColumn);
        }
Beispiel #7
0
 /// <summary>
 /// Adjusts the row number.
 /// </summary>
 /// <returns><c>true</c>, if row number was adjusted, <c>false</c> otherwise.</returns>
 /// <param name="codeword">Codeword.</param>
 /// <param name="otherCodeword">Other codeword.</param>
 private static bool adjustRowNumber(Codeword codeword, Codeword otherCodeword)
 {
     if (otherCodeword == null)
     {
         return(false);
     }
     if (otherCodeword.HasValidRowNumber && otherCodeword.Bucket == codeword.Bucket)
     {
         codeword.RowNumber = otherCodeword.RowNumber;
         return(true);
     }
     return(false);
 }
Beispiel #8
0
        /// <summary>
        /// Adjusts the row numbers.
        /// </summary>
        /// <param name="barcodeColumn">Barcode column.</param>
        /// <param name="codewordsRow">Codewords row.</param>
        /// <param name="codewords">Codewords.</param>
        private void adjustRowNumbers(int barcodeColumn, int codewordsRow, Codeword[] codewords)
        {
            Codeword codeword = codewords[codewordsRow];

            Codeword[] previousColumnCodewords = DetectionResultColumns[barcodeColumn - 1].Codewords;
            Codeword[] nextColumnCodewords     = previousColumnCodewords;
            if (DetectionResultColumns[barcodeColumn + 1] != null)
            {
                nextColumnCodewords = DetectionResultColumns[barcodeColumn + 1].Codewords;
            }

            Codeword[] otherCodewords = new Codeword[14];

            otherCodewords[2] = previousColumnCodewords[codewordsRow];
            otherCodewords[3] = nextColumnCodewords[codewordsRow];

            if (codewordsRow > 0)
            {
                otherCodewords[0] = codewords[codewordsRow - 1];
                otherCodewords[4] = previousColumnCodewords[codewordsRow - 1];
                otherCodewords[5] = nextColumnCodewords[codewordsRow - 1];
            }
            if (codewordsRow > 1)
            {
                otherCodewords[8]  = codewords[codewordsRow - 2];
                otherCodewords[10] = previousColumnCodewords[codewordsRow - 2];
                otherCodewords[11] = nextColumnCodewords[codewordsRow - 2];
            }
            if (codewordsRow < codewords.Length - 1)
            {
                otherCodewords[1] = codewords[codewordsRow + 1];
                otherCodewords[6] = previousColumnCodewords[codewordsRow + 1];
                otherCodewords[7] = nextColumnCodewords[codewordsRow + 1];
            }
            if (codewordsRow < codewords.Length - 2)
            {
                otherCodewords[9]  = codewords[codewordsRow + 2];
                otherCodewords[12] = previousColumnCodewords[codewordsRow + 2];
                otherCodewords[13] = nextColumnCodewords[codewordsRow + 2];
            }
            foreach (Codeword otherCodeword in otherCodewords)
            {
                if (adjustRowNumber(codeword, otherCodeword))
                {
                    return;
                }
            }
        }
        /// <summary>
        /// Gets the start column.
        /// </summary>
        /// <returns>The start column.</returns>
        /// <param name="detectionResult">Detection result.</param>
        /// <param name="barcodeColumn">Barcode column.</param>
        /// <param name="imageRow">Image row.</param>
        /// <param name="leftToRight">If set to <c>true</c> left to right.</param>
        private static int getStartColumn(DetectionResult detectionResult,
                                          int barcodeColumn,
                                          int imageRow,
                                          bool leftToRight)
        {
            int      offset   = leftToRight ? 1 : -1;
            Codeword codeword = null;

            if (isValidBarcodeColumn(detectionResult, barcodeColumn - offset))
            {
                codeword = detectionResult.DetectionResultColumns[barcodeColumn - offset].getCodeword(imageRow);
            }
            if (codeword != null)
            {
                return(leftToRight ? codeword.EndX : codeword.StartX);
            }
            codeword = detectionResult.DetectionResultColumns[barcodeColumn].getCodewordNearby(imageRow);
            if (codeword != null)
            {
                return(leftToRight ? codeword.StartX : codeword.EndX);
            }
            if (isValidBarcodeColumn(detectionResult, barcodeColumn - offset))
            {
                codeword = detectionResult.DetectionResultColumns[barcodeColumn - offset].getCodewordNearby(imageRow);
            }
            if (codeword != null)
            {
                return(leftToRight ? codeword.EndX : codeword.StartX);
            }
            int skippedColumns = 0;

            while (isValidBarcodeColumn(detectionResult, barcodeColumn - offset))
            {
                barcodeColumn -= offset;
                foreach (Codeword previousRowCodeword in detectionResult.DetectionResultColumns[barcodeColumn].Codewords)
                {
                    if (previousRowCodeword != null)
                    {
                        return((leftToRight ? previousRowCodeword.EndX : previousRowCodeword.StartX) +
                               offset *
                               skippedColumns *
                               (previousRowCodeword.EndX - previousRowCodeword.StartX));
                    }
                }
                skippedColumns++;
            }
            return(leftToRight ? detectionResult.Box.MinX : detectionResult.Box.MaxX);
        }
Beispiel #10
0
      /// <summary>
      /// Adjusts the row number if valid.
      /// </summary>
      /// <returns>The invalid rows</returns>
      /// <param name="rowIndicatorRowNumber">Row indicator row number.</param>
      /// <param name="invalidRowCounts">Invalid row counts.</param>
      /// <param name="codeword">Codeword.</param>
      private static int adjustRowNumberIfValid(int rowIndicatorRowNumber, int invalidRowCounts, Codeword codeword)
      {

         if (codeword == null)
         {
            return invalidRowCounts;
         }
         if (!codeword.HasValidRowNumber)
         {
            if (codeword.IsValidRowNumber(rowIndicatorRowNumber))
            {
               codeword.RowNumber = rowIndicatorRowNumber;
               invalidRowCounts = 0;
            }
            else
            {
               ++invalidRowCounts;
            }
         }
         return invalidRowCounts;
      }
Beispiel #11
0
 /// <summary>
 /// Adjusts the row number if valid.
 /// </summary>
 /// <returns>The invalid rows</returns>
 /// <param name="rowIndicatorRowNumber">Row indicator row number.</param>
 /// <param name="invalidRowCounts">Invalid row counts.</param>
 /// <param name="codeword">Codeword.</param>
 private static int adjustRowNumberIfValid(int rowIndicatorRowNumber, int invalidRowCounts, Codeword codeword)
 {
     if (codeword == null)
     {
         return(invalidRowCounts);
     }
     if (!codeword.HasValidRowNumber)
     {
         if (codeword.IsValidRowNumber(rowIndicatorRowNumber))
         {
             codeword.RowNumber = rowIndicatorRowNumber;
             invalidRowCounts   = 0;
         }
         else
         {
             ++invalidRowCounts;
         }
     }
     return(invalidRowCounts);
 }
Beispiel #12
0
 /// <summary>
 /// Adjusts the row number.
 /// </summary>
 /// <returns><c>true</c>, if row number was adjusted, <c>false</c> otherwise.</returns>
 /// <param name="codeword">Codeword.</param>
 /// <param name="otherCodeword">Other codeword.</param>
 private static bool adjustRowNumber(Codeword codeword, Codeword otherCodeword)
 {
    if (otherCodeword == null)
    {
       return false;
    }
    if (otherCodeword.HasValidRowNumber && otherCodeword.Bucket == codeword.Bucket)
    {
       codeword.RowNumber = otherCodeword.RowNumber;
       return true;
    }
    return false;
 }
Beispiel #13
0
      /// <summary>
      /// Adjusts the row numbers.
      /// </summary>
      /// <param name="barcodeColumn">Barcode column.</param>
      /// <param name="codewordsRow">Codewords row.</param>
      /// <param name="codewords">Codewords.</param>
      private void adjustRowNumbers(int barcodeColumn, int codewordsRow, Codeword[] codewords)
      {
         Codeword codeword = codewords[codewordsRow];
         Codeword[] previousColumnCodewords = DetectionResultColumns[barcodeColumn - 1].Codewords;
         Codeword[] nextColumnCodewords = previousColumnCodewords;
         if (DetectionResultColumns[barcodeColumn + 1] != null)
         {
            nextColumnCodewords = DetectionResultColumns[barcodeColumn + 1].Codewords;
         }

         Codeword[] otherCodewords = new Codeword[14];

         otherCodewords[2] = previousColumnCodewords[codewordsRow];
         otherCodewords[3] = nextColumnCodewords[codewordsRow];

         if (codewordsRow > 0)
         {
            otherCodewords[0] = codewords[codewordsRow - 1];
            otherCodewords[4] = previousColumnCodewords[codewordsRow - 1];
            otherCodewords[5] = nextColumnCodewords[codewordsRow - 1];
         }
         if (codewordsRow > 1)
         {
            otherCodewords[8] = codewords[codewordsRow - 2];
            otherCodewords[10] = previousColumnCodewords[codewordsRow - 2];
            otherCodewords[11] = nextColumnCodewords[codewordsRow - 2];
         }
         if (codewordsRow < codewords.Length - 1)
         {
            otherCodewords[1] = codewords[codewordsRow + 1];
            otherCodewords[6] = previousColumnCodewords[codewordsRow + 1];
            otherCodewords[7] = nextColumnCodewords[codewordsRow + 1];
         }
         if (codewordsRow < codewords.Length - 2)
         {
            otherCodewords[9] = codewords[codewordsRow + 2];
            otherCodewords[12] = previousColumnCodewords[codewordsRow + 2];
            otherCodewords[13] = nextColumnCodewords[codewordsRow + 2];
         }
         foreach (Codeword otherCodeword in otherCodewords)
         {
            if (adjustRowNumber(codeword, otherCodeword))
            {
               return;
            }
         }
      }
 /// <summary>
 /// Sets the codeword for an image row
 /// </summary>
 /// <param name="imageRow">Image row.</param>
 /// <param name="codeword">Codeword.</param>
 public void setCodeword(int imageRow, Codeword codeword)
 {
    Codewords[IndexForRow(imageRow)] = codeword;
 }
 /// <summary>
 /// Sets the codeword for an image row
 /// </summary>
 /// <param name="imageRow">Image row.</param>
 /// <param name="codeword">Codeword.</param>
 public void setCodeword(int imageRow, Codeword codeword)
 {
     Codewords[IndexForRow(imageRow)] = codeword;
 }
      /// <summary>
      /// Prune the codewords which do not match the metadata
      /// TODO Maybe we should keep the incorrect codewords for the start and end positions?
      /// </summary>
      /// <param name="codewords">Codewords.</param>
      /// <param name="metadata">Metadata.</param>
      private void removeIncorrectCodewords(Codeword[] codewords, BarcodeMetadata metadata)
      {
         for (int row = 0; row < codewords.Length; row++)
         {
            var codeword = codewords[row];
            if (codeword == null)
               continue;

            int indicatorValue = codeword.Value%30;
            int rowNumber = codeword.RowNumber;

            // Row does not exist in the metadata
            if (rowNumber >= metadata.RowCount) // different to java rowNumber > metadata.RowCount
            {
               codewords[row] = null; // remove this.
               continue;
            }

            if (!IsLeft)
            {
               rowNumber += 2;
            }

            switch (rowNumber%3)
            {
               default:
               case 0:
                  if (indicatorValue*3 + 1 != metadata.RowCountUpper)
                  {
                     codewords[row] = null;
                  }
                  break;

               case 1:
                  if (indicatorValue%3 != metadata.RowCountLower ||
                      indicatorValue/3 != metadata.ErrorCorrectionLevel)
                  {
                     codewords[row] = null;
                  }
                  break;

               case 2:
                  if (indicatorValue + 1 != metadata.ColumnCount)
                  {
                     codewords[row] = null;
                  }
                  break;
            }

         }
      }
        /// <summary>
        /// Decode the specified image, imageTopLeft, imageBottomLeft, imageTopRight, imageBottomRight, minCodewordWidth
        /// and maxCodewordWidth.
        /// TODO: don't pass in minCodewordWidth and maxCodewordWidth, pass in barcode columns for start and stop pattern
        /// columns. That way width can be deducted from the pattern column.
        /// This approach also allows to detect more details about the barcode, e.g. if a bar type (white or black) is wider
        /// than it should be. This can happen if the scanner used a bad blackpoint.
        /// </summary>
        /// <param name="image">Image.</param>
        /// <param name="imageTopLeft">Image top left.</param>
        /// <param name="imageBottomLeft">Image bottom left.</param>
        /// <param name="imageTopRight">Image top right.</param>
        /// <param name="imageBottomRight">Image bottom right.</param>
        /// <param name="minCodewordWidth">Minimum codeword width.</param>
        /// <param name="maxCodewordWidth">Max codeword width.</param>
        public static DecoderResult decode(BitMatrix image,
                                           ResultPoint imageTopLeft,
                                           ResultPoint imageBottomLeft,
                                           ResultPoint imageTopRight,
                                           ResultPoint imageBottomRight,
                                           int minCodewordWidth,
                                           int maxCodewordWidth)
        {
            BoundingBox boundingBox = BoundingBox.Create(image, imageTopLeft, imageBottomLeft, imageTopRight, imageBottomRight);

            if (boundingBox == null)
            {
                return(null);
            }

            DetectionResultRowIndicatorColumn leftRowIndicatorColumn  = null;
            DetectionResultRowIndicatorColumn rightRowIndicatorColumn = null;
            DetectionResult detectionResult = null;

            for (int i = 0; i < 2; i++)
            {
                if (imageTopLeft != null)
                {
                    leftRowIndicatorColumn = getRowIndicatorColumn(image, boundingBox, imageTopLeft, true, minCodewordWidth, maxCodewordWidth);
                }
                if (imageTopRight != null)
                {
                    rightRowIndicatorColumn = getRowIndicatorColumn(image, boundingBox, imageTopRight, false, minCodewordWidth, maxCodewordWidth);
                }
                detectionResult = merge(leftRowIndicatorColumn, rightRowIndicatorColumn);
                if (detectionResult == null)
                {
                    // TODO Based on Owen's Comments in <see cref="ZXing.ReaderException"/>, this method has been modified to continue silently
                    // if a barcode was not decoded where it was detected instead of throwing a new exception object.
                    return(null);
                }
                if (i == 0 && detectionResult.Box != null &&
                    (detectionResult.Box.MinY < boundingBox.MinY || detectionResult.Box.MaxY > boundingBox.MaxY))
                {
                    boundingBox = detectionResult.Box;
                }
                else
                {
                    detectionResult.Box = boundingBox;
                    break;
                }
            }
            int maxBarcodeColumn = detectionResult.ColumnCount + 1;

            detectionResult.DetectionResultColumns[0] = leftRowIndicatorColumn;

            detectionResult.DetectionResultColumns[maxBarcodeColumn] = rightRowIndicatorColumn;

            bool leftToRight = leftRowIndicatorColumn != null;

            for (int barcodeColumnCount = 1; barcodeColumnCount <= maxBarcodeColumn; barcodeColumnCount++)
            {
                int barcodeColumn = leftToRight ? barcodeColumnCount : maxBarcodeColumn - barcodeColumnCount;
                if (detectionResult.DetectionResultColumns[barcodeColumn] != null)
                {
                    // This will be the case for the opposite row indicator column, which doesn't need to be decoded again.
                    continue;
                }
                DetectionResultColumn detectionResultColumn;
                if (barcodeColumn == 0 || barcodeColumn == maxBarcodeColumn)
                {
                    detectionResultColumn = new DetectionResultRowIndicatorColumn(boundingBox, barcodeColumn == 0);
                }
                else
                {
                    detectionResultColumn = new DetectionResultColumn(boundingBox);
                }
                detectionResult.DetectionResultColumns[barcodeColumn] = detectionResultColumn;
                int startColumn         = -1;
                int previousStartColumn = startColumn;
                // TODO start at a row for which we know the start position, then detect upwards and downwards from there.
                for (int imageRow = boundingBox.MinY; imageRow <= boundingBox.MaxY; imageRow++)
                {
                    startColumn = getStartColumn(detectionResult, barcodeColumn, imageRow, leftToRight);
                    if (startColumn < 0 || startColumn > boundingBox.MaxX)
                    {
                        if (previousStartColumn == -1)
                        {
                            continue;
                        }
                        startColumn = previousStartColumn;
                    }
                    Codeword codeword = detectCodeword(image, boundingBox.MinX, boundingBox.MaxX, leftToRight,
                                                       startColumn, imageRow, minCodewordWidth, maxCodewordWidth);
                    if (codeword != null)
                    {
                        detectionResultColumn.setCodeword(imageRow, codeword);
                        previousStartColumn = startColumn;
                        minCodewordWidth    = Math.Min(minCodewordWidth, codeword.Width);
                        maxCodewordWidth    = Math.Max(maxCodewordWidth, codeword.Width);
                    }
                }
            }
            return(createDecoderResult(detectionResult));
        }