Esempio n. 1
0
        public override Result decodeRow(int rowNumber, BitArray row, System.Collections.Hashtable hints)
        {
            int[] start = findAsteriskPattern(row);
            int nextStart = start[1];
            int end = row.Size;

            // Read off white space
            while (nextStart < end && !row.get_Renamed(nextStart))
            {
                nextStart++;
            }

            System.Text.StringBuilder result = new System.Text.StringBuilder(20);
            int[] counters = new int[9];
            char decodedChar;
            int lastStart;
            do
            {
                recordPattern(row, nextStart, counters);
                int pattern = toNarrowWidePattern(counters);
                if (pattern < 0)
                {
                    throw ReaderException.Instance;
                }
                decodedChar = patternToChar(pattern);
                result.Append(decodedChar);
                lastStart = nextStart;
                for (int i = 0; i < counters.Length; i++)
                {
                    nextStart += counters[i];
                }
                // Read off white space
                while (nextStart < end && !row.get_Renamed(nextStart))
                {
                    nextStart++;
                }
            }
            while (decodedChar != '*');
            result.Remove(result.Length - 1, 1); // remove asterisk

            // Look for whitespace after pattern:
            int lastPatternSize = 0;
            for (int i = 0; i < counters.Length; i++)
            {
                lastPatternSize += counters[i];
            }
            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 / 2 < lastPatternSize)
            {
                throw ReaderException.Instance;
            }

            if (usingCheckDigit)
            {
                int max = result.Length - 1;
                int total = 0;
                for (int i = 0; i < max; i++)
                {
                    total += ALPHABET_STRING.IndexOf((System.Char) result[i]);
                }
                if (total % 43 != ALPHABET_STRING.IndexOf((System.Char) result[max]))
                {
                    throw ReaderException.Instance;
                }
                result.Remove(max, 1);
            }

            System.String resultString = result.ToString();
            if (extendedMode)
            {
                resultString = decodeExtended(resultString);
            }

            if (resultString.Length == 0)
            {
                // Almost surely a false positive
                throw ReaderException.Instance;
            }

            //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
            float left = (float) (start[1] + start[0]) / 2.0f;
            //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
            float right = (float) (nextStart + lastStart) / 2.0f;
            //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
            return new Result(resultString, null, new ResultPoint[]{new ResultPoint(left, (float) rowNumber), new ResultPoint(right, (float) rowNumber)}, BarcodeFormat.CODE_39);
        }
Esempio n. 2
0
        private static int[] findAsteriskPattern(BitArray row)
        {
            int width = row.Size;
            int rowOffset = 0;
            while (rowOffset < width)
            {
                if (row.get_Renamed(rowOffset))
                {
                    break;
                }
                rowOffset++;
            }

            int counterPosition = 0;
            int[] counters = new int[9];
            int patternStart = rowOffset;
            bool isWhite = false;
            int patternLength = counters.Length;

            for (int i = rowOffset; i < width; i++)
            {
                bool pixel = row.get_Renamed(i);
                if (pixel ^ isWhite)
                {
                    counters[counterPosition]++;
                }
                else
                {
                    if (counterPosition == patternLength - 1)
                    {
                        if (toNarrowWidePattern(counters) == ASTERISK_ENCODING)
                        {
                            // Look for whitespace before start pattern, >= 50% of width of start pattern
                            if (row.isRange(System.Math.Max(0, patternStart - (i - patternStart) / 2), patternStart, false))
                            {
                                return new int[]{patternStart, i};
                            }
                        }
                        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 ReaderException.Instance;
        }
Esempio n. 3
0
        /// <param name="row">row of black/white values to search
        /// </param>
        /// <param name="rowOffset">position to start search
        /// </param>
        /// <param name="whiteFirst">if true, indicates that the pattern specifies white/black/white/...
        /// pixel counts, otherwise, it is interpreted as black/white/black/...
        /// </param>
        /// <param name="pattern">pattern of counts of number of black and white pixels that are being
        /// searched for as a pattern
        /// </param>
        /// <returns> start/end horizontal offset of guard pattern, as an array of two ints
        /// </returns>
        /// <throws>  ReaderException if pattern is not found </throws>
        internal static int[] findGuardPattern(BitArray row, int rowOffset, bool whiteFirst, int[] pattern)
        {
            int patternLength = pattern.Length;
            int[] counters = new int[patternLength];
            int width = row.Size;
            bool isWhite = false;
            while (rowOffset < width)
            {
                isWhite = !row.get_Renamed(rowOffset);
                if (whiteFirst == isWhite)
                {
                    break;
                }
                rowOffset++;
            }

            int counterPosition = 0;
            int patternStart = rowOffset;
            for (int x = rowOffset; x < width; x++)
            {
                bool pixel = row.get_Renamed(x);
                if (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 ReaderException.Instance;
        }
Esempio n. 4
0
        /// <summary> 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
        /// 
        /// </summary>
        /// <param name="row">bit array representing the scanned barcode.
        /// </param>
        /// <param name="startPattern">index into row of the start or end pattern.
        /// </param>
        /// <throws>  ReaderException if the quiet zone cannot be found, a ReaderException is thrown. </throws>
        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_Renamed(i))
                {
                    break;
                }
                quietCount--;
            }
            if (quietCount != 0)
            {
                // Unable to find the necessary number of quiet zone pixels.
                throw ReaderException.Instance;
            }
        }
Esempio n. 5
0
        /// <summary> Skip all whitespace until we get to the first black line.
        /// 
        /// </summary>
        /// <param name="row">row of black/white values to search
        /// </param>
        /// <returns> index of the first black line.
        /// </returns>
        /// <throws>  ReaderException Throws exception if no black lines are found in the row </throws>
        private static int skipWhiteSpace(BitArray row)
        {
            int width = row.Size;
            int endStart = 0;
            while (endStart < width)
            {
                if (row.get_Renamed(endStart))
                {
                    break;
                }
                endStart++;
            }
            if (endStart == width)
            {
                throw ReaderException.Instance;
            }

            return endStart;
        }
Esempio n. 6
0
        /// <param name="row">      row of black/white values to search
        /// </param>
        /// <param name="rowOffset">position to start search
        /// </param>
        /// <param name="pattern">  pattern of counts of number of black and white pixels that are
        /// being searched for as a pattern
        /// </param>
        /// <returns> start/end horizontal offset of guard pattern, as an array of two
        /// ints
        /// </returns>
        /// <throws>  ReaderException if pattern is not found </throws>
        private static int[] findGuardPattern(BitArray row, int rowOffset, int[] pattern)
        {
            // TODO: This is very similar to implementation in UPCEANReader. Consider if they can be
            // merged to a single method.
            int patternLength = pattern.Length;
            int[] counters = new int[patternLength];
            int width = row.Size;
            bool isWhite = false;

            int counterPosition = 0;
            int patternStart = rowOffset;
            for (int x = rowOffset; x < width; x++)
            {
                bool pixel = row.get_Renamed(x);
                if (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 ReaderException.Instance;
        }
Esempio n. 7
0
 /// <summary> Records the size of successive runs of white and black pixels in a row, starting at a given point.
 /// The values are recorded in the given array, and the number of runs recorded is equal to the size
 /// of the array. If the row starts on a white pixel at the given start point, then the first count
 /// recorded is the run of white pixels starting from that point; likewise it is the count of a run
 /// of black pixels if the row begin on a black pixels at that point.
 /// 
 /// </summary>
 /// <param name="row">row to count from
 /// </param>
 /// <param name="start">offset into row to start at
 /// </param>
 /// <param name="counters">array into which to record counts
 /// </param>
 /// <throws>  ReaderException if counters cannot be filled entirely from row before running out </throws>
 /// <summary>  of pixels
 /// </summary>
 internal static void recordPattern(BitArray row, int start, int[] counters)
 {
     int numCounters = counters.Length;
     for (int i = 0; i < numCounters; i++)
     {
         counters[i] = 0;
     }
     int end = row.Size;
     if (start >= end)
     {
         throw ReaderException.Instance;
     }
     bool isWhite = !row.get_Renamed(start);
     int counterPosition = 0;
     int i2 = start;
     while (i2 < end)
     {
         bool pixel = row.get_Renamed(i2);
         if (pixel ^ isWhite)
         {
             // that is, exactly one is true
             counters[counterPosition]++;
         }
         else
         {
             counterPosition++;
             if (counterPosition == numCounters)
             {
                 break;
             }
             else
             {
                 counters[counterPosition] = 1;
                 isWhite ^= true; // isWhite = !isWhite;
             }
         }
         i2++;
     }
     // If we read fully the last section of pixels and filled up our counters -- or filled
     // the last counter but ran off the side of the image, OK. Otherwise, a problem.
     if (!(counterPosition == numCounters || (counterPosition == numCounters - 1 && i2 == end)))
     {
         throw ReaderException.Instance;
     }
 }