Beispiel #1
0
        /**
         * <p>This method attempts to find the bottom-right alignment pattern in the image. It is a bit messy since
         * it's pretty performance-critical and so is written to be fast foremost.</p>
         *
         * @return {@link AlignmentPattern} if found
         * @throws ReaderException if not found
         */
        public AlignmentPattern find()
        {
            int      startX       = this.startX;
            int      height       = this.height;
            int      maxJ         = startX + width;
            int      middleI      = startY + (height >> 1);
            BitArray luminanceRow = new BitArray(width);

            // We are looking for black/white/black modules in 1:1:1 ratio;
            // this tracks the number of black/white/black modules seen so far
            int[] stateCount = new int[3];
            for (int iGen = 0; iGen < height; iGen++)
            {
                // Search from middle outwards
                int i = middleI + ((iGen & 0x01) == 0 ? ((iGen + 1) >> 1) : -((iGen + 1) >> 1));
                image.getBlackRow(i, luminanceRow, startX, width);
                stateCount[0] = 0;
                stateCount[1] = 0;
                stateCount[2] = 0;
                int j = startX;
                // Burn off leading white pixels before anything else; if we start in the middle of
                // a white run, it doesn't make sense to count its length, since we don't know if the
                // white run continued to the left of the start point
                while (j < maxJ && !luminanceRow.get(j - startX))
                {
                    j++;
                }
                int currentState = 0;
                while (j < maxJ)
                {
                    if (luminanceRow.get(j - startX))
                    {
                        // Black pixel
                        if (currentState == 1) // Counting black pixels
                        {
                            stateCount[currentState]++;
                        }
                        else // Counting white pixels
                        {
                            if (currentState == 2) // A winner?
                            {
                                if (foundPatternCross(stateCount)) // Yes
                                {
                                    AlignmentPattern confirmed = handlePossibleCenter(stateCount, i, j);
                                    if (confirmed != null)
                                    {
                                        return(confirmed);
                                    }
                                }
                                stateCount[0] = stateCount[2];
                                stateCount[1] = 1;
                                stateCount[2] = 0;
                                currentState  = 1;
                            }
                            else
                            {
                                stateCount[++currentState]++;
                            }
                        }
                    }
                    else // White pixel
                    {
                        if (currentState == 1) // Counting black pixels
                        {
                            currentState++;
                        }
                        stateCount[currentState]++;
                    }
                    j++;
                }
                if (foundPatternCross(stateCount))
                {
                    AlignmentPattern confirmed = handlePossibleCenter(stateCount, i, maxJ);
                    if (confirmed != null)
                    {
                        return(confirmed);
                    }
                }
            }

            // Hmm, nothing we saw was observed and confirmed twice. If we had
            // any guess at all, return it.
            if (!(possibleCenters.Count == 0))
            {
                return((AlignmentPattern)possibleCenters[0]);
            }

            throw new ReaderException();
        }
Beispiel #2
0
        /**
         * We're going to examine rows from the middle outward, searching alternately above and below the
         * middle, and farther out each time. rowStep is the number of rows between each successive
         * attempt above and below the middle. So we'd scan row middle, then middle - rowStep, then
         * middle + rowStep, then middle - (2 * rowStep), etc.
         * rowStep is bigger as the image is taller, but is always at least 1. We've somewhat arbitrarily
         * decided that moving up and down by about 1/16 of the image is pretty good; we try more of the
         * image if "trying harder".
         *
         * @param image The image to decode
         * @param hints Any hints that were requested
         * @return The contents of the decoded barcode
         * @throws ReaderException Any spontaneous errors which occur
         */
        private Result doDecode(MonochromeBitmapSource image, System.Collections.Hashtable hints)
        {
            int      width  = image.getWidth();
            int      height = image.getHeight();
            BitArray row    = new BitArray(width);

            int  middle    = height >> 1;
            bool tryHarder = hints != null && hints.ContainsKey(DecodeHintType.TRY_HARDER);
            int  rowStep   = Math.Max(1, height >> (tryHarder ? 7 : 4));
            int  MaxLines;

            if (tryHarder)
            {
                MaxLines = height; // Look at the whole image, not just the center
            }
            else
            {
                MaxLines = 9; // Nine rows spaced 1/16 apart is roughly the middle half of the image
            }

            for (int x = 0; x < MaxLines; x++)
            {
                // Scanning from the middle out. Determine which row we're looking at next:
                int  rowStepsAboveOrBelow = (x + 1) >> 1;
                bool isAbove   = (x & 0x01) == 0; // i.e. is x even?
                int  rowNumber = middle + rowStep * (isAbove ? rowStepsAboveOrBelow : -rowStepsAboveOrBelow);
                if (rowNumber < 0 || rowNumber >= height)
                {
                    // Oops, if we run off the top or bottom, stop
                    break;
                }

                // Estimate black point for this row and load it:
                try {
                    image.estimateBlackPoint(BlackPointEstimationMethod.ROW_SAMPLING, rowNumber);
                } catch (ReaderException re) {
                    continue;
                }

                image.getBlackRow(rowNumber, row, 0, width);

                // While we have the image data in a BitArray, it's fairly cheap to reverse it in place to
                // handle decoding upside down barcodes.
                for (int attempt = 0; attempt < 2; attempt++)
                {
                    if (attempt == 1)  // trying again?
                    {
                        row.reverse(); // reverse the row and continue
                    }
                    try {
                        // Look for a barcode
                        Result result = decodeRow(rowNumber, row, hints);
                        // We found our barcode
                        if (attempt == 1)
                        {
                            // But it was upside down, so note that
                            result.putMetadata(ResultMetadataType.ORIENTATION, 180);
                            // And remember to flip the result points horizontally.
                            ResultPoint[] points = result.getResultPoints();
                            points[0] = (ResultPoint) new GenericResultPoint(width - points[0].getX() - 1, points[0].getY());
                            points[1] = (ResultPoint) new GenericResultPoint(width - points[1].getX() - 1, points[1].getY());
                        }
                        return(result);
                    } catch (ReaderException re) {
                        // continue -- just couldn't decode this row
                    }
                }
            }

            throw new ReaderException();
        }
        /**
           * We're going to examine rows from the middle outward, searching alternately above and below the
           * middle, and farther out each time. rowStep is the number of rows between each successive
           * attempt above and below the middle. So we'd scan row middle, then middle - rowStep, then
           * middle + rowStep, then middle - (2 * rowStep), etc.
           * rowStep is bigger as the image is taller, but is always at least 1. We've somewhat arbitrarily
           * decided that moving up and down by about 1/16 of the image is pretty good; we try more of the
           * image if "trying harder".
           *
           * @param image The image to decode
           * @param hints Any hints that were requested
           * @return The contents of the decoded barcode
           * @throws ReaderException Any spontaneous errors which occur
           */
        private Result doDecode(MonochromeBitmapSource image, System.Collections.Hashtable hints)
        {
            int width = image.getWidth();
            int height = image.getHeight();
            BitArray row = new BitArray(width);

            int middle = height >> 1;
            bool tryHarder = hints != null && hints.ContainsKey(DecodeHintType.TRY_HARDER);
            int rowStep = Math.Max(1, height >> (tryHarder ? 7 : 4));
            int MaxLines;
            if (tryHarder) {
              MaxLines = height; // Look at the whole image, not just the center
            } else {
              MaxLines = 9; // Nine rows spaced 1/16 apart is roughly the middle half of the image
            }

            for (int x = 0; x < MaxLines; x++) {

              // Scanning from the middle out. Determine which row we're looking at next:
              int rowStepsAboveOrBelow = (x + 1) >> 1;
              bool isAbove = (x & 0x01) == 0; // i.e. is x even?
              int rowNumber = middle + rowStep * (isAbove ? rowStepsAboveOrBelow : -rowStepsAboveOrBelow);
              if (rowNumber < 0 || rowNumber >= height) {
                // Oops, if we run off the top or bottom, stop
                break;
              }

              // Estimate black point for this row and load it:
              try {
                image.estimateBlackPoint(BlackPointEstimationMethod.ROW_SAMPLING, rowNumber);
              } catch (ReaderException re) {
                continue;
              }

              image.getBlackRow(rowNumber, row,0, width);

              // While we have the image data in a BitArray, it's fairly cheap to reverse it in place to
              // handle decoding upside down barcodes.
              for (int attempt = 0; attempt < 2; attempt++) {
                if (attempt == 1) { // trying again?
                  row.reverse(); // reverse the row and continue
                }
                try {
                  // Look for a barcode
                  Result result = decodeRow(rowNumber, row, hints);
                  // We found our barcode
                  if (attempt == 1) {
                    // But it was upside down, so note that
                    result.putMetadata(ResultMetadataType.ORIENTATION, 180);
                    // And remember to flip the result points horizontally.
                    ResultPoint[] points = result.getResultPoints();
                    points[0] = (ResultPoint) new GenericResultPoint(width - points[0].getX() - 1, points[0].getY());
                    points[1] = (ResultPoint)new GenericResultPoint(width - points[1].getX() - 1, points[1].getY());
                  }
                  return result;
                } catch (ReaderException re) {
                  // continue -- just couldn't decode this row
                }
              }
            }

            throw new ReaderException();
        }