Esempio n. 1
0
        public override Result decodeRow(int rowNumber, BitArray row, System.Collections.Hashtable hints)
        {
            StringBuilder result = new StringBuilder(20);

            // Find out where the Middle section (payload) starts & ends
            int[] startRange = decodeStart(row);
            int[] endRange = decodeEnd(row);

            decodeMiddle(row, startRange[1], endRange[0], result);

            string resultString = result.ToString();

            // To avoid false positives with 2D barcodes (and other patterns), make
            // an assumption that the decoded string must be 6, 10 or 14 digits.
            int length = resultString.Length;
            if (length != 6 && length != 10 && length != 14) {
              throw new ReaderException();
            }

            return new Result(
                resultString,
                null, // no natural byte representation for these barcodes
                new ResultPoint[] { new GenericResultPoint(startRange[1], (float) rowNumber),
                                    new GenericResultPoint(startRange[0], (float) rowNumber)},
                BarcodeFormat.ITF);
        }
      public BitArray getBlackRow(int y, BitArray row, int startX, int getWidth) {
        if (row == null || row.getSize() < getWidth) {
          row = new BitArray(getWidth);
        } else {
          row.clear();
        }

        // Reuse the same int array each time
        initLuminances();
        luminances = getLuminanceRow(y, luminances);

        // If the current decoder calculated the blackPoint based on one row, assume we're trying to
        // decode a 1D barcode, and apply some sharpening.
        if (lastMethod.Equals(BlackPointEstimationMethod.ROW_SAMPLING)) {
          int left = luminances[startX];
          int center = luminances[startX + 1];
          for (int x = 1; x < getWidth - 1; x++) {
            int right = luminances[startX + x + 1];
            // Simple -1 4 -1 box filter with a weight of 2
            int luminance = ((center << 2) - left - right) >> 1;
            if (luminance < blackPoint) {
              row.set(x);
            }
            left = center;
            center = right;
          }
        } else {
          for (int x = 0; x < getWidth; x++) {
            if (luminances[startX + x] < blackPoint) {
              row.set(x);
            }
          }
        }
        return row;
      }
Esempio n. 3
0
        protected override int decodeMiddle(BitArray row, int[] startRange, StringBuilder result)
        {
            int[] counters = decodeMiddleCounters;
            counters[0] = 0;
            counters[1] = 0;
            counters[2] = 0;
            counters[3] = 0;
            int end = row.getSize();
            int rowOffset = startRange[1];

            for (int x = 0; x < 4 && rowOffset < end; x++) {
              int bestMatch = decodeDigit(row, counters, rowOffset, L_PATTERNS);
              result.Append((char) ('0' + bestMatch));
              for (int i = 0; i < counters.Length; i++) {
                rowOffset += counters[i];
              }
            }

            int[] middleRange = findGuardPattern(row, rowOffset, true, MIDDLE_PATTERN);
            rowOffset = middleRange[1];

            for (int x = 0; x < 4 && rowOffset < end; x++) {
              int bestMatch = decodeDigit(row, counters, rowOffset, L_PATTERNS);
              result.Append((char) ('0' + bestMatch));
              for (int i = 0; i < counters.Length; i++) {
                rowOffset += counters[i];
              }
            }

            return rowOffset;
        }
Esempio n. 4
0
        public BitArray getBlackColumn(int x, BitArray column, int startY, int getHeight)
        {
            if (column == null || column.getSize() < getHeight)
            {
                column = new BitArray(getHeight);
            }
            else
            {
                column.clear();
            }

            // Reuse the same int array each time
            initLuminances();
            luminances = getLuminanceColumn(x, luminances);

            // We don't handle "row sampling" specially here
            for (int y = 0; y < getHeight; y++)
            {
                if (luminances[startY + y] < blackPoint)
                {
                    column.set(y);
                }
            }
            return(column);
        }
        public override Result decodeRow(int rowNumber, BitArray row, System.Collections.Hashtable hints)
        {
            // Compute this location once and reuse it on multiple implementations
            int[] startGuardPattern = AbstractUPCEANReader.findStartGuardPattern(row);
            int size = readers.Count;
            for (int i = 0; i < size; i++) {
              UPCEANReader reader = (UPCEANReader) readers[i];
              Result result;
              try {
                result = reader.decodeRow(rowNumber, row, startGuardPattern);
              } catch (ReaderException re) {
                continue;
              }
              // Special case: a 12-digit code encoded in UPC-A is identical to a "0"
              // followed by those 12 digits encoded as EAN-13. Each will recognize such a code,
              // UPC-A as a 12-digit string and EAN-13 as a 13-digit string starting with "0".
              // Individually these are correct and their readers will both read such a code
              // and correctly call it EAN-13, or UPC-A, respectively.
              //
              // In this case, if we've been looking for both types, we'd like to call it
              // a UPC-A code. But for efficiency we only run the EAN-13 decoder to also read
              // UPC-A. So we special case it here, and convert an EAN-13 result to a UPC-A
              // result if appropriate.
              if (result.getBarcodeFormat().Equals(BarcodeFormat.EAN_13) && result.getText()[0] == '0') {
                return new Result(result.getText().Substring(1), null, result.getResultPoints(), BarcodeFormat.UPC_A);
              }
              return result;
            }

            throw new ReaderException();
        }
        public override Result decodeRow(int rowNumber, BitArray row, System.Collections.Hashtable hints)
        {
            int size = readers.Count;
            for (int i = 0; i < size; i++) {
              OneDReader reader = (OneDReader) readers[i];
              try {
                return reader.decodeRow(rowNumber, row, hints);
              } catch (ReaderException re) {
                // continue
              }
            }

            throw new ReaderException();
        }
Esempio n. 7
0
        public BitArray getBlackRow(int y, BitArray row, int startX, int getWidth)
        {
            if (row == null || row.getSize() < getWidth)
            {
                row = new BitArray(getWidth);
            }
            else
            {
                row.clear();
            }

            // Reuse the same int array each time
            initLuminances();
            luminances = getLuminanceRow(y, luminances);

            // If the current decoder calculated the blackPoint based on one row, assume we're trying to
            // decode a 1D barcode, and apply some sharpening.
            if (lastMethod.Equals(BlackPointEstimationMethod.ROW_SAMPLING))
            {
                int left   = luminances[startX];
                int center = luminances[startX + 1];
                for (int x = 1; x < getWidth - 1; x++)
                {
                    int right = luminances[startX + x + 1];
                    // Simple -1 4 -1 box filter with a weight of 2
                    int luminance = ((center << 2) - left - right) >> 1;
                    if (luminance < blackPoint)
                    {
                        row.set(x);
                    }
                    left   = center;
                    center = right;
                }
            }
            else
            {
                for (int x = 0; x < getWidth; x++)
                {
                    if (luminances[startX + x] < blackPoint)
                    {
                        row.set(x);
                    }
                }
            }
            return(row);
        }
Esempio n. 8
0
        protected override int decodeMiddle(BitArray row, int[] startRange, StringBuilder resultString)
        {
            int[] counters = decodeMiddleCounters;
            counters[0] = 0;
            counters[1] = 0;
            counters[2] = 0;
            counters[3] = 0;
            int end = row.getSize();
            int rowOffset = startRange[1];

            int lgPatternFound = 0;

            for (int x = 0; x < 6 && rowOffset < end; x++) {
              int bestMatch = decodeDigit(row, counters, rowOffset, L_AND_G_PATTERNS);
              resultString.Append((char) ('0' + bestMatch % 10));
              for (int i = 0; i < counters.Length; i++) {
                rowOffset += counters[i];
              }
              if (bestMatch >= 10) {
                lgPatternFound |= 1 << (5 - x);
              }
            }

            determineFirstDigit(resultString, lgPatternFound);

            int[] middleRange = findGuardPattern(row, rowOffset, true, MIDDLE_PATTERN);
            rowOffset = middleRange[1];

            for (int x = 0; x < 6 && rowOffset < end; x++) {
              int bestMatch = decodeDigit(row, counters, rowOffset, L_PATTERNS);
              resultString.Append((char) ('0' + bestMatch));
              for (int i = 0; i < counters.Length; i++) {
                rowOffset += counters[i];
              }
            }

            return rowOffset;
        }
 /**
    * Attempts to decode a single UPC/EAN-encoded digit.
    *
    * @param row row of black/white values to decode
    * @param counters the counts of runs of observed black/white/black/... values
    * @param rowOffset horizontal offset to start decoding from
    * @param patterns the set of patterns to use to decode -- sometimes different encodings
    * for the digits 0-9 are used, and this indicates the encodings for 0 to 9 that should
    * be used
    * @return horizontal offset of first pixel beyond the decoded digit
    * @throws ReaderException if digit cannot be decoded
    */
 public static int decodeDigit(BitArray row, int[] counters, int rowOffset, int[][] patterns)
 {
     recordPattern(row, rowOffset, counters);
     int bestVariance = MAX_AVG_VARIANCE; // worst variance we'll accept
     int bestMatch = -1;
     int max = patterns.Length;
     for (int i = 0; i < max; i++) {
       int[] pattern = patterns[i];
       int variance = patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE);
       if (variance < bestVariance) {
         bestVariance = variance;
         bestMatch = i;
       }
     }
     if (bestMatch >= 0) {
       return bestMatch;
     } else {
       throw new ReaderException();
     }
 }
        private void Worker()
        {
            float fY1;
                float fY2;

                float scale;

                // calculate picFrame just once
                if (picFrame == RectangleF.Empty)
                {

                    // check if device has retina display, if so scale factor by 2
                    if (UIScreen.MainScreen.RespondsToSelector(new MonoTouch.ObjCRuntime.Selector(@"scale")) &&
                        UIScreen.MainScreen.Scale == 2)
                        scale = 2f;
                    else
                        scale = 1f;

                    // check if the device is an ipad or an iphone
                    if (UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Phone)
                    {
                        fY1 = 146f / UIScreen.MainScreen.Bounds.Height * scale;
                        fY2 = 157f / UIScreen.MainScreen.Bounds.Height * scale;
                    }
                    else
                    {
                        // ipad - constants probably need to be modified if running at native screen res

                        fY1 = 146f / UIScreen.MainScreen.Bounds.Height * scale;
                        fY2 = 157f / UIScreen.MainScreen.Bounds.Height * scale;
                    }

                    picFrame = new RectangleF(0, UIScreen.MainScreen.Bounds.Height * fY1, UIScreen.MainScreen.Bounds.Width * scale, UIScreen.MainScreen.Bounds.Height * fY2);
                }

                if(hints==null)
                {
                    var list = new ArrayList();
                    list.Add(com.google.zxing.BarcodeFormat.EAN_8);
                    list.Add(com.google.zxing.BarcodeFormat.EAN_13);

                    hints = new Hashtable();
                    hints.Add(com.google.zxing.DecodeHintType.POSSIBLE_FORMATS, list);
                    hints.Add(com.google.zxing.DecodeHintType.NEED_RESULT_POINT_CALLBACK, new ResultCallBack(this));
                }

                if(_multiFormatOneDReader == null)
                {
                    _multiFormatOneDReader = new com.google.zxing.oned.MultiFormatOneDReader(hints);
                }

                // Capturing screen image
                using (var screenImage = CGImage.ScreenImage.WithImageInRect(picFrame))
                {
                    _theScreenImage = UIImage.FromImage(screenImage);
                    Bitmap srcbitmap = new System.Drawing.Bitmap(_theScreenImage);
                    LuminanceSource source = null;
                    BinaryBitmap bitmap = null;
                    try {
                        source = new RGBLuminanceSource(srcbitmap, screenImage.Width, screenImage.Height);
                      	bitmap = new BinaryBitmap(new HybridBinarizer(source));

                        com.google.zxing.common.BitArray row = new com.google.zxing.common.BitArray(screenImage.Width);
                        int middle = screenImage.Height >> 1;
                        int rowStep = System.Math.Max(1, screenImage.Height >> (4));

                        for (int x = 0; x < 9; 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 >= screenImage.Height)
                            {
                                // Oops, if we run off the top or bottom, stop
                                break;
                            }

                            // Estimate black point for this row and load it:
                            try
                            {
                                row = bitmap.getBlackRow(rowNumber, row);

                                var resultb = _multiFormatOneDReader.decodeRow(rowNumber, row, hints);
                                if(resultb.Text!=null)
                                {
                                    BeepOrVibrate();
                                    _parentViewController.BarCodeScanned(resultb);

                                    break;
                                }
                                else {
                                    continue;
                                }

                            }
                            catch (ReaderException re)
                            {
                                continue;
                            }

                        }

            //					var result = _barcodeReader.decodeWithState(bitmap);
            //
            //					if(result.Text!=null)
            //					{
            //						_multiFormatOneDReader = null;
            //						BeepOrVibrate();
            //						_parentViewController.BarCodeScanned(result);
            //					}

                    } catch (Exception ex) {
                        Console.WriteLine(ex.Message);
                    }
                    finally {
                        if(bitmap!=null)
                            bitmap = null;

                         if(source!=null)
                            source = null;

                        if(srcbitmap!=null)
                            srcbitmap = null;

                    }

                }
        }
 int[] decodeEnd(BitArray row, int endStart)
 {
     return findGuardPattern(row, endStart, false, START_END_PATTERN);
 }
Esempio n. 12
0
 /// <summary> A fast method to retrieve one row of data from the matrix as a BitArray.
 /// 
 /// </summary>
 /// <param name="y">The row to retrieve
 /// </param>
 /// <param name="row">An optional caller-allocated BitArray, will be allocated if null or too small
 /// </param>
 /// <returns> The resulting BitArray - this reference should always be used even when passing
 /// your own row
 /// </returns>
 public BitArray getRow(int y, BitArray row)
 {
     if (row == null || row.Size < width)
     {
         row = new BitArray(width);
     }
     int offset = y * rowSize;
     for (int x = 0; x < rowSize; x++)
     {
         row.setBulk(x << 5, bits[offset + x]);
     }
     return row;
 }
        private void Worker()
        {
            //iphone 4 : 960 x 640
                //iphone 3 : 320 x 480
                if(DeviceHardware.Version == DeviceHardware.HardwareVersion.iPhone4)
                {
                    picFrame = new RectangleF(0, 146*2, 320*2, 157*2);
                }

                if(hints==null)
                {
                    var list = new ArrayList();
                    list.Add(com.google.zxing.BarcodeFormat.EAN_8);
                    list.Add(com.google.zxing.BarcodeFormat.EAN_13);

                    hints = new Hashtable();
                    hints.Add(com.google.zxing.DecodeHintType.POSSIBLE_FORMATS, list);
                    hints.Add(com.google.zxing.DecodeHintType.NEED_RESULT_POINT_CALLBACK, new ResultCallBack(this));
                }

                if(_multiFormatOneDReader == null)
                {
                    _multiFormatOneDReader = new com.google.zxing.oned.MultiFormatOneDReader(hints);
                }

                // Capturing screen image
                using (var screenImage = CGImage.ScreenImage.WithImageInRect(picFrame))
                {
                    _theScreenImage = UIImage.FromImage(screenImage);
                    Bitmap srcbitmap = new System.Drawing.Bitmap(_theScreenImage);
                    LuminanceSource source = null;
                    BinaryBitmap bitmap = null;
                    try {
                        source = new RGBLuminanceSource(srcbitmap, screenImage.Width, screenImage.Height);
                      	bitmap = new BinaryBitmap(new HybridBinarizer(source));

                        com.google.zxing.common.BitArray row = new com.google.zxing.common.BitArray(screenImage.Width);
                        int middle = screenImage.Height >> 1;
                        int rowStep = System.Math.Max(1, screenImage.Height >> (4));

                        for (int x = 0; x < 9; 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 >= screenImage.Height)
                            {
                                // Oops, if we run off the top or bottom, stop
                                break;
                            }

                            // Estimate black point for this row and load it:
                            try
                            {
                                row = bitmap.getBlackRow(rowNumber, row);

                                var resultb = _multiFormatOneDReader.decodeRow(rowNumber, row, hints);
                                if(resultb.Text!=null)
                                {
                                    BeepOrVibrate();
                                    _parentViewController.BarCodeScanned(resultb);

                                    break;
                                }
                                else {
                                    continue;
                                }

                            }
                            catch (ReaderException re)
                            {
                                continue;
                            }

                        }

            //					var result = _barcodeReader.decodeWithState(bitmap);
            //
            //					if(result.Text!=null)
            //					{
            //						_multiFormatOneDReader = null;
            //						BeepOrVibrate();
            //						_parentViewController.BarCodeScanned(result);
            //					}

                    } catch (Exception ex) {
                        Console.WriteLine(ex.Message);
                    }
                    finally {
                        if(bitmap!=null)
                            bitmap = null;

                         if(source!=null)
                            source = null;

                        if(srcbitmap!=null)
                            srcbitmap = null;

                    }

                }
        }
 /**
    * Subclasses override this to decode the portion of a barcode between the start and end guard patterns.
    *
    * @param row row of black/white values to search
    * @param startRange start/end offset of start guard pattern
    * @param resultString {@link StringBuffer} to append decoded chars to
    * @return horizontal offset of first pixel after the "middle" that was decoded
    * @throws ReaderException if decoding could not complete successfully
    */
 protected abstract int decodeMiddle(BitArray row, int[] startRange, StringBuilder resultString);
Esempio n. 15
0
        /**
           * @param row       row of black/white values to search
           * @param rowOffset position to start search
           * @param pattern   pattern of counts of number of black and white pixels that are
           *                  being searched for as a pattern
           * @return start/end horizontal offset of guard pattern, as an array of two
           *         ints
           * @throws ReaderException if pattern is not found
           */
        int[] findGuardPattern(BitArray row, int rowOffset, int[] pattern)
        {
            // TODO: This is very similar to implementation in AbstractUPCEANReader. Consider if they can be merged to
            // a single method.

            int patternLength = pattern.Length;
            int[] counters = new int[patternLength];
            int width = row.getSize();
            bool isWhite = false;

            int counterPosition = 0;
            int patternStart = rowOffset;
            for (int x = rowOffset; x < width; x++) {
              bool pixel = row.get(x);
              if ((!pixel && isWhite) || (pixel && !isWhite)) {
                counters[counterPosition]++;
              } else {
                if (counterPosition == patternLength - 1) {
                  if (patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE) < MAX_AVG_VARIANCE) {
                    return new int[]{patternStart, x};
                  }
                  patternStart += counters[0] + counters[1];
                  for (int y = 2; y < patternLength; y++) {
                    counters[y - 2] = counters[y];
                  }
                  counters[patternLength - 2] = 0;
                  counters[patternLength - 1] = 0;
                  counterPosition--;
                } else {
                  counterPosition++;
                }
                counters[counterPosition] = 1;
                isWhite = !isWhite;
              }
            }
            throw new ReaderException();
        }
Esempio n. 16
0
        /**
           * The start & end patterns must be pre/post fixed by a quiet zone. This
           * zone must be at least 10 times the width of a narrow line.  Scan back until
           * we either get to the start of the barcode or match the necessary number of
           * quiet zone pixels.
           *
           * Note: Its assumed the row is reversed when using this method to find
           * quiet zone after the end pattern.
           *
           * ref: http://www.barcode-1.net/i25code.html
           *
           * @param row bit array representing the scanned barcode.
           * @param startPattern index into row of the start or end pattern.
           * @throws ReaderException if the quiet zone cannot be found, a ReaderException is thrown.
           */
        private void validateQuietZone(BitArray row, int startPattern)
        {
            int quietCount = this.narrowLineWidth * 10;  // expect to find this many pixels of quiet zone

            for (int i = startPattern - 1; quietCount > 0 && i >= 0; i--) {
              if (row.get(i)) {
                break;
              }
              quietCount--;
            }
            if (quietCount != 0) {
              // Unable to find the necessary number of quiet zone pixels.
              throw new ReaderException();
            }
        }
Esempio n. 17
0
        private void Worker()
        {
            //iphone 4 : 960 x 640
            //iphone 3 : 320 x 480
            if (DeviceHardware.Version == DeviceHardware.HardwareVersion.iPhone4)
            {
                picFrame = new RectangleF(0, 146 * 2, 320 * 2, 157 * 2);
            }

            if (hints == null)
            {
                var list = new ArrayList();
                list.Add(com.google.zxing.BarcodeFormat.EAN_8);
                list.Add(com.google.zxing.BarcodeFormat.EAN_13);

                hints = new Hashtable();
                hints.Add(com.google.zxing.DecodeHintType.POSSIBLE_FORMATS, list);
                hints.Add(com.google.zxing.DecodeHintType.NEED_RESULT_POINT_CALLBACK, new ResultCallBack(this));
            }

            if (_multiFormatOneDReader == null)
            {
                _multiFormatOneDReader = new com.google.zxing.oned.MultiFormatOneDReader(hints);
            }


            // Capturing screen image
            using (var screenImage = CGImage.ScreenImage.WithImageInRect(picFrame))
            {
                _theScreenImage = UIImage.FromImage(screenImage);
                Bitmap          srcbitmap = new System.Drawing.Bitmap(_theScreenImage);
                LuminanceSource source    = null;
                BinaryBitmap    bitmap    = null;
                try {
                    source = new RGBLuminanceSource(srcbitmap, screenImage.Width, screenImage.Height);
                    bitmap = new BinaryBitmap(new HybridBinarizer(source));

                    com.google.zxing.common.BitArray row = new com.google.zxing.common.BitArray(screenImage.Width);
                    int middle  = screenImage.Height >> 1;
                    int rowStep = System.Math.Max(1, screenImage.Height >> (4));

                    for (int x = 0; x < 9; 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 >= screenImage.Height)
                        {
                            // Oops, if we run off the top or bottom, stop
                            break;
                        }

                        // Estimate black point for this row and load it:
                        try
                        {
                            row = bitmap.getBlackRow(rowNumber, row);

                            var resultb = _multiFormatOneDReader.decodeRow(rowNumber, row, hints);
                            if (resultb.Text != null)
                            {
                                BeepOrVibrate();
                                _parentViewController.BarCodeScanned(resultb);


                                break;
                            }
                            else
                            {
                                continue;
                            }
                        }
                        catch (ReaderException re)
                        {
                            continue;
                        }
                    }



                    //					var result = _barcodeReader.decodeWithState(bitmap);
                    //
                    //					if(result.Text!=null)
                    //					{
                    //						_multiFormatOneDReader = null;
                    //						BeepOrVibrate();
                    //						_parentViewController.BarCodeScanned(result);
                    //					}
                } catch (Exception ex) {
                    Console.WriteLine(ex.Message);
                }
                finally {
                    if (bitmap != null)
                    {
                        bitmap = null;
                    }

                    if (source != null)
                    {
                        source = null;
                    }

                    if (srcbitmap != null)
                    {
                        srcbitmap = null;
                    }
                }
            }
        }
Esempio n. 18
0
        /**
           * Identify where the end of the middle / payload section ends.
           *
           * @param row row of black/white values to search
           * @return Array, containing index of start of 'end block' and end of 'end
           *         block'
           * @throws ReaderException
           */
        int[] decodeEnd(BitArray row)
        {
            // For convenience, reverse the row and then
            // search from 'the start' for the end block
            row.reverse();

            int endStart = skipWhiteSpace(row);
            int[] endPattern;
            try {
              endPattern = findGuardPattern(row, endStart, END_PATTERN_REVERSED);
            } catch (ReaderException e) {
              // Put our row of data back the right way before throwing
              row.reverse();
              throw e;
            }

            // The start & end patterns must be pre/post fixed by a quiet zone. This
            // zone must be at least 10 times the width of a narrow line.
            // ref: http://www.barcode-1.net/i25code.html
            validateQuietZone(row, endPattern[0]);

            // Now recalc the indicies of where the 'endblock' starts & stops to
            // accomodate
            // the reversed nature of the search
            int temp = endPattern[0];
            endPattern[0] = row.getSize() - endPattern[1];
            endPattern[1] = row.getSize() - temp;

            // Put the row back the righ way.
            row.reverse();
            return endPattern;
        }
          /**
           * <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();
          }
Esempio n. 20
0
 public Result decodeRow(int rowNumber, BitArray row, int[] startGuardRange)
 {
     return maybeReturnResult(ean13Reader.decodeRow(rowNumber, row, startGuardRange));
 }
Esempio n. 21
0
        //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
        //ORIGINAL LINE: private static int[] findAsteriskPattern(com.google.zxing.common.BitArray row, int[] counters) throws com.google.zxing.NotFoundException
        private static int[] findAsteriskPattern(BitArray row, int[] counters)
        {
            int width = row.Size;
            int rowOffset = row.getNextSet(0);

            int counterPosition = 0;
            int patternStart = rowOffset;
            bool isWhite = false;
            int patternLength = counters.Length;

            for (int i = rowOffset; i < width; i++)
            {
              if (row.get(i) ^ isWhite)
              {
            counters[counterPosition]++;
              }
              else
              {
            if (counterPosition == patternLength - 1)
            {
              // Look for whitespace before start pattern, >= 50% of width of start pattern
              if (toNarrowWidePattern(counters) == ASTERISK_ENCODING && row.isRange(Math.Max(0, patternStart - ((i - patternStart) >> 1)), patternStart, false))
              {
                return new int[]{patternStart, i};
              }
              patternStart += counters[0] + counters[1];
              Array.Copy(counters, 2, counters, 0, patternLength - 2);
              counters[patternLength - 2] = 0;
              counters[patternLength - 1] = 0;
              counterPosition--;
            }
            else
            {
              counterPosition++;
            }
            counters[counterPosition] = 1;
            isWhite = !isWhite;
              }
            }
            throw NotFoundException.NotFoundInstance;
        }
Esempio n. 22
0
        //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
        //ORIGINAL LINE: public com.google.zxing.Result decodeRow(int rowNumber, com.google.zxing.common.BitArray row, java.util.Map<com.google.zxing.DecodeHintType,?> hints) throws com.google.zxing.NotFoundException, com.google.zxing.ChecksumException, com.google.zxing.FormatException
        public override Result decodeRow(int rowNumber, BitArray row, IDictionary<DecodeHintType, object> hints)
        {
            int[] theCounters = counters;
            theCounters.Fill(0);
            StringBuilder result = decodeRowResult;
            result.Length = 0;

            int[] start = findAsteriskPattern(row, theCounters);
            // Read off white space
            int nextStart = row.getNextSet(start[1]);
            int end = row.Size;

            char decodedChar;
            int lastStart;
            do
            {
              recordPattern(row, nextStart, theCounters);
              int pattern = toNarrowWidePattern(theCounters);
              if (pattern < 0)
              {
            throw NotFoundException.NotFoundInstance;
              }
              decodedChar = patternToChar(pattern);
              result.Append(decodedChar);
              lastStart = nextStart;
              foreach (int counter in theCounters)
              {
            nextStart += counter;
              }
              // Read off white space
              nextStart = row.getNextSet(nextStart);
            } while (decodedChar != '*');
            result.Length = result.Length - 1; // remove asterisk

            // Look for whitespace after pattern:
            int lastPatternSize = 0;
            foreach (int counter in theCounters)
            {
              lastPatternSize += counter;
            }
            int whiteSpaceAfterEnd = nextStart - lastStart - lastPatternSize;
            // If 50% of last pattern size, following last pattern, is not whitespace, fail
            // (but if it's whitespace to the very end of the image, that's OK)
            if (nextStart != end && (whiteSpaceAfterEnd >> 1) < lastPatternSize)
            {
              throw NotFoundException.NotFoundInstance;
            }

            if (usingCheckDigit)
            {
              int max = result.Length - 1;
              int total = 0;
              for (int i = 0; i < max; i++)
              {
            total += ALPHABET_STRING.IndexOf(decodeRowResult[i]);
              }
              if (result[max] != ALPHABET[total % 43])
              {
            throw ChecksumException.ChecksumInstance;
              }
              result.Length = max;
            }

            if (result.Length == 0)
            {
              // false positive
              throw NotFoundException.NotFoundInstance;
            }

            string resultString;
            if (extendedMode)
            {
              resultString = decodeExtended(result.ToString());
            }
            else
            {
              resultString = result.ToString();
            }

            float left = (float)(start[1] + start[0]) / 2.0f;
            float right = (float)(nextStart + lastStart) / 2.0f;
            return new Result(resultString, null, new ResultPoint[]{new ResultPoint(left, (float) rowNumber), new ResultPoint(right, (float) rowNumber)}, BarcodeFormat.CODE_39);
        }
Esempio n. 23
0
 public Result decodeRow(int rowNumber, BitArray row, System.Collections.Hashtable hints)
 {
     return maybeReturnResult(ean13Reader.decodeRow(rowNumber, row, hints));
 }
Esempio n. 24
0
        /**
           * @param row          row of black/white values to search
           * @param payloadStart offset of start pattern
           * @param resultString {@link StringBuilder} to Append decoded chars to
           * @throws ReaderException if decoding could not complete successfully
           */
        static void decodeMiddle(BitArray row, int payloadStart, int payloadEnd, StringBuilder resultString)
        {
            // Digits are interleaved in pairs - 5 black lines for one digit, and the
            // 5
            // interleaved white lines for the second digit.
            // Therefore, need to scan 10 lines and then
            // split these into two arrays
            int[] counterDigitPair = new int[10];
            int[] counterBlack = new int[5];
            int[] counterWhite = new int[5];

            while (payloadStart < payloadEnd) {

              // Get 10 runs of black/white.
              recordPattern(row, payloadStart, counterDigitPair);
              // Split them into each array
              for (int k = 0; k < 5; k++) {
                int twoK = k << 1;
                counterBlack[k] = counterDigitPair[twoK];
                counterWhite[k] = counterDigitPair[twoK + 1];
              }

              int bestMatch = decodeDigit(counterBlack);
              resultString.Append((char) ('0' + bestMatch));
              bestMatch = decodeDigit(counterWhite);
              resultString.Append((char) ('0' + bestMatch));

              for (int i = 0; i < counterDigitPair.Length; i++) {
                payloadStart += counterDigitPair[i];
              }
            }
        }
        /**
           * @param row row of black/white values to search
           * @param rowOffset position to start search
           * @param whiteFirst if true, indicates that the pattern specifies white/black/white/...
           * pixel counts, otherwise, it is interpreted as black/white/black/...
           * @param pattern pattern of counts of number of black and white pixels that are being
           * searched for as a pattern
           * @return start/end horizontal offset of guard pattern, as an array of two ints
           * @throws ReaderException if pattern is not found
           */
        public static int[] findGuardPattern(BitArray row, int rowOffset, bool whiteFirst, int[] pattern)
        {
            int patternLength = pattern.Length;
            int[] counters = new int[patternLength];
            int width = row.getSize();
            bool isWhite = false;
            while (rowOffset < width) {
              isWhite = !row.get(rowOffset);
              if (whiteFirst == isWhite) {
                break;
              }
              rowOffset++;
            }

            int counterPosition = 0;
            int patternStart = rowOffset;
            for (int x = rowOffset; x < width; x++) {
              bool pixel = row.get(x);
              if ((!pixel && isWhite) || (pixel && !isWhite)) {
                counters[counterPosition]++;
              } else {
                if (counterPosition == patternLength - 1) {
                  if (patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE) < MAX_AVG_VARIANCE) {
                    return new int[]{patternStart, x};
                  }
                  patternStart += counters[0] + counters[1];
                  for (int y = 2; y < patternLength; y++) {
                    counters[y - 2] = counters[y];
                  }
                  counters[patternLength - 2] = 0;
                  counters[patternLength - 1] = 0;
                  counterPosition--;
                } else {
                  counterPosition++;
                }
                counters[counterPosition] = 1;
                isWhite = !isWhite;
              }
            }
            throw new ReaderException();
        }
Esempio n. 26
0
        /**
           * Identify where the start of the middle / payload section starts.
           *
           * @param row row of black/white values to search
           * @return Array, containing index of start of 'start block' and end of
           *         'start block'
           * @throws ReaderException
           */
        int[] decodeStart(BitArray row)
        {
            int endStart = skipWhiteSpace(row);
            int[] startPattern = findGuardPattern(row, endStart, START_PATTERN);

            // Determine the width of a narrow line in pixels. We can do this by
            // getting the width of the start pattern and dividing by 4 because its
            // made up of 4 narrow lines.
            this.narrowLineWidth = (startPattern[1] - startPattern[0]) >> 2;

            validateQuietZone(row, startPattern[0]);

            return startPattern;
        }
 public static int[] findStartGuardPattern(BitArray row)
 {
     bool foundStart = false;
     int[] startRange = null;
     int nextStart = 0;
     while (!foundStart) {
       startRange = findGuardPattern(row, nextStart, false, START_END_PATTERN);
       int start = startRange[0];
       nextStart = startRange[1];
       // Make sure there is a quiet zone at least as big as the start pattern before the barcode. If
       // this check would run off the left edge of the image, do not accept this barcode, as it is
       // very likely to be a false positive.
       int quietStart = start - (nextStart - start);
       if (quietStart >= 0) {
         foundStart = row.isRange(quietStart, start, false);
       }
     }
     return startRange;
 }
Esempio n. 28
0
        /**
           * Skip all whitespace until we get to the first black line.
           *
           * @param row row of black/white values to search
           * @return index of the first black line.
           * @throws ReaderException Throws exception if no black lines are found in the row
           */
        private int skipWhiteSpace(BitArray row)
        {
            int width = row.getSize();
            int endStart = 0;
            while (endStart < width) {
              if (row.get(endStart)) {
                break;
              }
              endStart++;
            }
            if (endStart == width) {
              throw new ReaderException();
            }

            return endStart;
        }
Esempio n. 29
0
 public int[] decodeEnd(BitArray row, int endStart)
 {
     return findGuardPattern(row, endStart, true, MIDDLE_END_PATTERN);
 }
 public override Result decodeRow(int rowNumber, BitArray row, System.Collections.Hashtable hints)
 {
     return decodeRow(rowNumber, row, findStartGuardPattern(row));
 }
		// Applies simple sharpening to the row data to improve performance of the 1D Readers.
		public override BitArray getBlackRow(int y, BitArray row)
		{
			LuminanceSource source = LuminanceSource;
			int width = source.Width;
			if (row == null || row.Size < width)
			{
				row = new BitArray(width);
			}
			else
			{
				row.clear();
			}
			
			initArrays(width);
			sbyte[] localLuminances = source.getRow(y, luminances);
			int[] localBuckets = buckets;
			for (int x = 0; x < width; x++)
			{
				int pixel = localLuminances[x] & 0xff;
				localBuckets[pixel >> LUMINANCE_SHIFT]++;
			}
			int blackPoint = estimateBlackPoint(localBuckets);
			
			int left = localLuminances[0] & 0xff;
			int center = localLuminances[1] & 0xff;
			for (int x = 1; x < width - 1; x++)
			{
				int right = localLuminances[x + 1] & 0xff;
				// A simple -1 4 -1 box filter with a weight of 2.
				int luminance = ((center << 2) - left - right) >> 1;
				if (luminance < blackPoint)
				{
					row.set_Renamed(x);
				}
				left = center;
				center = right;
			}
			return row;
		}
        public FinderPatternInfo find(System.Collections.Hashtable hints)
        {
            bool tryHarder = hints != null && hints.ContainsKey(DecodeHintType.TRY_HARDER);
            int maxI = image.getHeight();
            int maxJ = image.getWidth();
            // We are looking for black/white/black/white/black modules in
            // 1:1:3:1:1 ratio; this tracks the number of such modules seen so far

            // Let's assume that the maximum version QR Code we support takes up 1/4 the height of the
            // image, and then account for the center being 3 modules in size. This gives the smallest
            // number of pixels the center could be, so skip this often. When trying harder, look for all
            // QR versions regardless of how dense they are.
            int iSkip = (int) (maxI / (MAX_MODULES * 4.0f) * 3);
            if (iSkip < MIN_SKIP || tryHarder) {
              iSkip = MIN_SKIP;
            }

            bool done = false;
            int[] stateCount = new int[5];
            BitArray blackRow = new BitArray(maxJ);
            for (int i = iSkip - 1; i < maxI && !done; i += iSkip) {
              // Get a row of black/white values
              blackRow = image.getBlackRow(i, blackRow, 0, maxJ);
              stateCount[0] = 0;
              stateCount[1] = 0;
              stateCount[2] = 0;
              stateCount[3] = 0;
              stateCount[4] = 0;
              int currentState = 0;
              for (int j = 0; j < maxJ; j++) {
                if (blackRow.get(j)) {
                  // Black pixel
                  if ((currentState & 1) == 1) { // Counting white pixels
                    currentState++;
                  }
                  stateCount[currentState]++;
                } else { // White pixel
                  if ((currentState & 1) == 0) { // Counting black pixels
                    if (currentState == 4) { // A winner?
                      if (foundPatternCross(stateCount)) { // Yes
                        bool confirmed = handlePossibleCenter(stateCount, i, j);
                        if (confirmed) {
                          // Start examining every other line. Checking each line turned out to be too
                          // expensive and didn't improve performance.
                          iSkip = 2;
                          if (hasSkipped) {
                            done = haveMulitplyConfirmedCenters();
                          } else {
                            int rowSkip = findRowSkip();
                            if (rowSkip > stateCount[2]) {
                              // Skip rows between row of lower confirmed center
                              // and top of presumed third confirmed center
                              // but back up a bit to get a full chance of detecting
                              // it, entire width of center of finder pattern

                              // Skip by rowSkip, but back off by stateCount[2] (size of last center
                              // of pattern we saw) to be conservative, and also back off by iSkip which
                              // is about to be re-added
                              i += rowSkip - stateCount[2] - iSkip;
                              j = maxJ - 1;
                            }
                          }
                        } else {
                          // Advance to next black pixel
                          do {
                            j++;
                          } while (j < maxJ && !blackRow.get(j));
                          j--; // back up to that last white pixel
                        }
                        // Clear state to start looking again
                        currentState = 0;
                        stateCount[0] = 0;
                        stateCount[1] = 0;
                        stateCount[2] = 0;
                        stateCount[3] = 0;
                        stateCount[4] = 0;
                      } else { // No, shift counts back by two
                        stateCount[0] = stateCount[2];
                        stateCount[1] = stateCount[3];
                        stateCount[2] = stateCount[4];
                        stateCount[3] = 1;
                        stateCount[4] = 0;
                        currentState = 3;
                      }
                    } else {
                      stateCount[++currentState]++;
                    }
                  } else { // Counting white pixels
                    stateCount[currentState]++;
                  }
                }
              }
              if (foundPatternCross(stateCount)) {
                bool confirmed = handlePossibleCenter(stateCount, i, maxJ);
                if (confirmed) {
                  iSkip = stateCount[0];
                  if (hasSkipped) {
                    // Found a third one
                    done = haveMulitplyConfirmedCenters();
                  }
                }
              }
            }

            FinderPattern[] patternInfo = selectBestPatterns();
            GenericResultPoint.orderBestPatterns(patternInfo);

            return new FinderPatternInfo(patternInfo);
        }
        public Result decodeRow(int rowNumber, BitArray row, int[] startGuardRange)
        {
            StringBuilder result = decodeRowStringBuffer;
            result.Length = 0;
            int endStart = decodeMiddle(row, startGuardRange, result);
            int[] endRange = decodeEnd(row, endStart);

            // Make sure there is a quiet zone at least as big as the end pattern after the barcode. The
            // spec might want more whitespace, but in practice this is the maximum we can count on.
            int end = endRange[1];
            int quietEnd = end + (end - endRange[0]);
            if (quietEnd >= row.getSize() || !row.isRange(end, quietEnd, false)) {
              throw new ReaderException();
            }

            String resultString = result.ToString();
            if (!checkChecksum(resultString)) {
              throw new ReaderException();
            }

            float left = (float) (startGuardRange[1] + startGuardRange[0]) / 2.0f;
            float right = (float) (endRange[1] + endRange[0]) / 2.0f;
            return new Result(resultString,
                null, // no natural byte representation for these barcodes
                new ResultPoint[]{
                    new GenericResultPoint(left, (float) rowNumber),
                    new GenericResultPoint(right, (float) rowNumber)},
                getBarcodeFormat());
        }