示例#1
0
 /// <summary>
 /// Main constructor
 /// </summary>
 /// <param name="codewords">the codewords to place</param>
 /// <param name="numcols">the number of columns</param>
 /// <param name="numrows">the number of rows</param>
 public DefaultPlacement(String codewords, int numcols, int numrows)
 {
     this.codewords = codewords;
     this.numcols   = numcols;
     this.numrows   = numrows;
     this.bits      = new byte[numcols * numrows];
     SupportClass.Fill(this.bits, (byte)2); //Initialize with "not set" value
 }
示例#2
0
        /// <summary>
        /// Finds the guard pattern.  Uses System.Linq.Enumerable.Repeat to fill in counters.  This might be a performance issue?
        /// </summary>
        /// <returns>start/end horizontal offset of guard pattern, as an array of two ints.</returns>
        /// <param name="matrix">matrix row of black/white values to search</param>
        /// <param name="column">column x position to start search.</param>
        /// <param name="row">row y position to start search.</param>
        /// <param name="width">width the number of pixels to search on this row.</param>
        /// <param name="whiteFirst">If set to <c>true</c> search the white patterns first.</param>
        /// <param name="pattern">pattern of counts of number of black and white pixels that are being searched for as a pattern.</param>
        /// <param name="counters">counters array of counters, as long as pattern, to re-use .</param>
        private static int[] findGuardPattern(
            BitMatrix matrix,
            int column,
            int row,
            int width,
            bool whiteFirst,
            int[] pattern,
            int[] counters)
        {
            SupportClass.Fill(counters, 0);
            var patternStart = column;
            var pixelDrift   = 0;

            // if there are black pixels left of the current pixel shift to the left, but only for MAX_PIXEL_DRIFT pixels
            while (matrix[patternStart, row] && patternStart > 0 && pixelDrift++ < MAX_PIXEL_DRIFT)
            {
                patternStart--;
            }
            var x = patternStart;
            var counterPosition = 0;
            var patternLength   = pattern.Length;

            for (var isWhite = whiteFirst; x < width; x++)
            {
                var pixel = matrix[x, row];
                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];
                        Array.Copy(counters, 2, counters, 0, counterPosition - 1);
                        counters[counterPosition - 1] = 0;
                        counters[counterPosition]     = 0;
                        counterPosition--;
                    }
                    else
                    {
                        counterPosition++;
                    }
                    counters[counterPosition] = 1;
                    isWhite = !isWhite;
                }
            }
            if (counterPosition == patternLength - 1 &&
                patternMatchVariance(counters, pattern, MAX_INDIVIDUAL_VARIANCE) < MAX_AVG_VARIANCE)
            {
                return(new int[] { patternStart, x - 1 });
            }
            return(null);
        }
示例#3
0
 private static int findMinimums(float[] charCounts, int[] intCharCounts, int min, byte[] mins)
 {
     SupportClass.Fill(mins, (byte)0);
     for (int i = 0; i < 6; i++)
     {
         intCharCounts[i] = (int)Math.Ceiling(charCounts[i]);
         int current = intCharCounts[i];
         if (min > current)
         {
             min = current;
             SupportClass.Fill(mins, (byte)0);
         }
         if (min == current)
         {
             mins[i]++;
         }
     }
     return(min);
 }
示例#4
0
        /// <summary>
        ///Performs RS error correction on an array of bits.
        /// </summary>
        /// <param name="rawbits">The rawbits.</param>
        /// <returns>the corrected array</returns>
        private CorrectedBitsResult correctBits(bool[] rawbits)
        {
            GenericGF gf;
            int       codewordSize;

            if (ddata.NbLayers <= 2)
            {
                codewordSize = 6;
                gf           = GenericGF.AZTEC_DATA_6;
            }
            else if (ddata.NbLayers <= 8)
            {
                codewordSize = 8;
                gf           = GenericGF.AZTEC_DATA_8;
            }
            else if (ddata.NbLayers <= 22)
            {
                codewordSize = 10;
                gf           = GenericGF.AZTEC_DATA_10;
            }
            else
            {
                codewordSize = 12;
                gf           = GenericGF.AZTEC_DATA_12;
            }

            int numDataCodewords = ddata.NbDatablocks;
            int numCodewords     = rawbits.Length / codewordSize;

            if (numCodewords < numDataCodewords)
            {
                return(null);
            }

            int offset         = rawbits.Length % codewordSize;
            int numECCodewords = numCodewords - numDataCodewords;

            int[] dataWords = new int[numCodewords];
            for (int i = 0; i < numCodewords; i++, offset += codewordSize)
            {
                dataWords[i] = readCode(rawbits, offset, codewordSize);
            }

            var rsDecoder = new ReedSolomonDecoder(gf);

            if (!rsDecoder.decode(dataWords, numECCodewords))
            {
                return(null);
            }

            // Now perform the unstuffing operation.
            // First, count how many bits are going to be thrown out as stuffing
            int mask        = (1 << codewordSize) - 1;
            int stuffedBits = 0;

            for (int i = 0; i < numDataCodewords; i++)
            {
                int dataWord = dataWords[i];
                if (dataWord == 0 || dataWord == mask)
                {
                    return(null);
                }
                else if (dataWord == 1 || dataWord == mask - 1)
                {
                    stuffedBits++;
                }
            }
            // Now, actually unpack the bits and remove the stuffing
            bool[] correctedBits = new bool[numDataCodewords * codewordSize - stuffedBits];
            int    index         = 0;

            for (int i = 0; i < numDataCodewords; i++)
            {
                int dataWord = dataWords[i];
                if (dataWord == 1 || dataWord == mask - 1)
                {
                    // next codewordSize-1 bits are all zeros or all ones
                    SupportClass.Fill(correctedBits, index, index + codewordSize - 1, dataWord > 1);
                    index += codewordSize - 1;
                }
                else
                {
                    for (int bit = codewordSize - 1; bit >= 0; --bit)
                    {
                        correctedBits[index++] = (dataWord & (1 << bit)) != 0;
                    }
                }
            }

            if (index != correctedBits.Length)
            {
                return(null);
            }

            return(new CorrectedBitsResult(correctedBits, 100 * (numCodewords - numDataCodewords) / numCodewords));
        }
示例#5
0
        static HighLevelEncoder()
        {
            CHAR_MAP[0] = new int[256];
            CHAR_MAP[1] = new int[256];
            CHAR_MAP[2] = new int[256];
            CHAR_MAP[3] = new int[256];
            CHAR_MAP[4] = new int[256];

            SHIFT_TABLE[0] = new int[6];
            SHIFT_TABLE[1] = new int[6];
            SHIFT_TABLE[2] = new int[6];
            SHIFT_TABLE[3] = new int[6];
            SHIFT_TABLE[4] = new int[6];
            SHIFT_TABLE[5] = new int[6];

            CHAR_MAP[MODE_UPPER][' '] = 1;
            for (int c = 'A'; c <= 'Z'; c++)
            {
                CHAR_MAP[MODE_UPPER][c] = c - 'A' + 2;
            }
            CHAR_MAP[MODE_LOWER][' '] = 1;
            for (int c = 'a'; c <= 'z'; c++)
            {
                CHAR_MAP[MODE_LOWER][c] = c - 'a' + 2;
            }
            CHAR_MAP[MODE_DIGIT][' '] = 1;
            for (int c = '0'; c <= '9'; c++)
            {
                CHAR_MAP[MODE_DIGIT][c] = c - '0' + 2;
            }
            CHAR_MAP[MODE_DIGIT][','] = 12;
            CHAR_MAP[MODE_DIGIT]['.'] = 13;
            int[] mixedTable =
            {
                '\0', ' ',  1,  2,  3,   4,    5,   6,   7, '\b', '\t', '\n', 11, '\f', '\r',
                27,    28, 29, 30, 31, '@', '\\', '^', '_', '`',  '|',  '~', 127
            };
            for (int i = 0; i < mixedTable.Length; i++)
            {
                CHAR_MAP[MODE_MIXED][mixedTable[i]] = i;
            }
            int[] punctTable =
            {
                '\0', '\r', '\0', '\0', '\0', '\0', '!', '\'', '#', '$', '%', '&', '\'',
                '(',  ')',  '*',  '+',  ',',  '-',  '.', '/',  ':', ';', '<', '=', '>', '?',
                '[',  ']',  '{',  '}'
            };
            for (int i = 0; i < punctTable.Length; i++)
            {
                if (punctTable[i] > 0)
                {
                    CHAR_MAP[MODE_PUNCT][punctTable[i]] = i;
                }
            }
            foreach (int[] table in SHIFT_TABLE)
            {
                SupportClass.Fill(table, -1);
            }
            SHIFT_TABLE[MODE_UPPER][MODE_PUNCT] = 0;

            SHIFT_TABLE[MODE_LOWER][MODE_PUNCT] = 0;
            SHIFT_TABLE[MODE_LOWER][MODE_UPPER] = 28;

            SHIFT_TABLE[MODE_MIXED][MODE_PUNCT] = 0;

            SHIFT_TABLE[MODE_DIGIT][MODE_PUNCT] = 0;
            SHIFT_TABLE[MODE_DIGIT][MODE_UPPER] = 15;
        }
示例#6
0
        internal DataCharacter decodeDataCharacter(BitArray row,
                                                   FinderPattern pattern,
                                                   bool isOddPattern,
                                                   bool leftChar)
        {
            int[] counters = getDataCharacterCounters();
            SupportClass.Fill(counters, 0);

            if (leftChar)
            {
                if (!recordPatternInReverse(row, pattern.StartEnd[0], counters))
                {
                    return(null);
                }
            }
            else
            {
                if (!recordPattern(row, pattern.StartEnd[1], counters))
                {
                    return(null);
                }
                // reverse it
                for (int i = 0, j = counters.Length - 1; i < j; i++, j--)
                {
                    int temp = counters[i];
                    counters[i] = counters[j];
                    counters[j] = temp;
                }
            } //counters[] has the pixels of the module

            const int numModules   = 17; //left and right data characters have all the same length
            float     elementWidth = (float)ZXing.Common.Detector.MathUtils.sum(counters) / (float)numModules;

            // Sanity check: element width for pattern and the character should match
            float expectedElementWidth = (pattern.StartEnd[1] - pattern.StartEnd[0]) / 15.0f;

            if (Math.Abs(elementWidth - expectedElementWidth) / expectedElementWidth > 0.3f)
            {
                return(null);
            }

            int[]   oddCounts          = getOddCounts();
            int[]   evenCounts         = getEvenCounts();
            float[] oddRoundingErrors  = getOddRoundingErrors();
            float[] evenRoundingErrors = getEvenRoundingErrors();

            for (int i = 0; i < counters.Length; i++)
            {
                float divided = 1.0f * counters[i] / elementWidth;
                int   rounded = (int)(divided + 0.5f); // Round
                if (rounded < 1)
                {
                    if (divided < 0.3f)
                    {
                        return(null);
                    }
                    rounded = 1;
                }
                else if (rounded > 8)
                {
                    if (divided > 8.7f)
                    {
                        return(null);
                    }
                    rounded = 8;
                }
                int offset = i >> 1;
                if ((i & 0x01) == 0)
                {
                    oddCounts[offset]         = rounded;
                    oddRoundingErrors[offset] = divided - rounded;
                }
                else
                {
                    evenCounts[offset]         = rounded;
                    evenRoundingErrors[offset] = divided - rounded;
                }
            }

            if (!adjustOddEvenCounts(numModules))
            {
                return(null);
            }

            int weightRowNumber = 4 * pattern.Value + (isOddPattern ? 0 : 2) + (leftChar ? 0 : 1) - 1;

            int oddSum             = 0;
            int oddChecksumPortion = 0;

            for (int i = oddCounts.Length - 1; i >= 0; i--)
            {
                if (isNotA1left(pattern, isOddPattern, leftChar))
                {
                    int weight = WEIGHTS[weightRowNumber][2 * i];
                    oddChecksumPortion += oddCounts[i] * weight;
                }
                oddSum += oddCounts[i];
            }
            int evenChecksumPortion = 0;

            for (int i = evenCounts.Length - 1; i >= 0; i--)
            {
                if (isNotA1left(pattern, isOddPattern, leftChar))
                {
                    int weight = WEIGHTS[weightRowNumber][2 * i + 1];
                    evenChecksumPortion += evenCounts[i] * weight;
                }
            }
            int checksumPortion = oddChecksumPortion + evenChecksumPortion;

            if ((oddSum & 0x01) != 0 || oddSum > 13 || oddSum < 4)
            {
                return(null);
            }

            int group      = (13 - oddSum) / 2;
            int oddWidest  = SYMBOL_WIDEST[group];
            int evenWidest = 9 - oddWidest;
            int vOdd       = RSSUtils.getRSSvalue(oddCounts, oddWidest, true);
            int vEven      = RSSUtils.getRSSvalue(evenCounts, evenWidest, false);
            int tEven      = EVEN_TOTAL_SUBSET[group];
            int gSum       = GSUM[group];
            int value      = vOdd * tEven + vEven + gSum;

            return(new DataCharacter(value, checksumPortion));
        }
示例#7
0
        private static readonly int[] NB_BITS_COMPACT;                                                                                  // total bits per full symbol for a given number of layers

        static Encoder()
        {
            CHAR_MAP[TABLE_UPPER][' '] = 1;
            for (int c = 'A'; c <= 'Z'; c++)
            {
                CHAR_MAP[TABLE_UPPER][c] = c - 'A' + 2;
            }
            CHAR_MAP[TABLE_LOWER][' '] = 1;
            for (int c = 'a'; c <= 'z'; c++)
            {
                CHAR_MAP[TABLE_LOWER][c] = c - 'a' + 2;
            }
            CHAR_MAP[TABLE_DIGIT][' '] = 1;
            for (int c = '0'; c <= '9'; c++)
            {
                CHAR_MAP[TABLE_DIGIT][c] = c - '0' + 2;
            }
            CHAR_MAP[TABLE_DIGIT][','] = 12;
            CHAR_MAP[TABLE_DIGIT]['.'] = 13;
            int[] mixedTable =
            {
                '\0', ' ',  1,  2,  3,   4,    5,   6,   7, '\b', '\t', '\n', 11, '\f', '\r',
                27,    28, 29, 30, 31, '@', '\\', '^', '_', '`',  '|',  '~', 127
            };
            for (int i = 0; i < mixedTable.Length; i++)
            {
                CHAR_MAP[TABLE_MIXED][mixedTable[i]] = i;
            }
            int[] punctTable =
            {
                '\0', '\r', '\0', '\0', '\0', '\0', '!', '\'', '#', '$', '%', '&', '\'', '(', ')', '*', '+',
                ',',  '-',  '.',  '/',  ':',  ';',  '<', '=',  '>', '?', '[', ']', '{',  '}'
            };
            for (int i = 0; i < punctTable.Length; i++)
            {
                if (punctTable[i] > 0)
                {
                    CHAR_MAP[TABLE_PUNCT][punctTable[i]] = i;
                }
            }
            foreach (int[] table in SHIFT_TABLE)
            {
                SupportClass.Fill(table, -1);
            }
            foreach (int[] table in LATCH_TABLE)
            {
                SupportClass.Fill(table, -1);
            }
            SHIFT_TABLE[TABLE_UPPER][TABLE_PUNCT]  = 0;
            LATCH_TABLE[TABLE_UPPER][TABLE_LOWER]  = 28;
            LATCH_TABLE[TABLE_UPPER][TABLE_MIXED]  = 29;
            LATCH_TABLE[TABLE_UPPER][TABLE_DIGIT]  = 30;
            SHIFT_TABLE[TABLE_UPPER][TABLE_BINARY] = 31;
            SHIFT_TABLE[TABLE_LOWER][TABLE_PUNCT]  = 0;
            SHIFT_TABLE[TABLE_LOWER][TABLE_UPPER]  = 28;
            LATCH_TABLE[TABLE_LOWER][TABLE_MIXED]  = 29;
            LATCH_TABLE[TABLE_LOWER][TABLE_DIGIT]  = 30;
            SHIFT_TABLE[TABLE_LOWER][TABLE_BINARY] = 31;
            SHIFT_TABLE[TABLE_MIXED][TABLE_PUNCT]  = 0;
            LATCH_TABLE[TABLE_MIXED][TABLE_LOWER]  = 28;
            LATCH_TABLE[TABLE_MIXED][TABLE_UPPER]  = 29;
            LATCH_TABLE[TABLE_MIXED][TABLE_PUNCT]  = 30;
            SHIFT_TABLE[TABLE_MIXED][TABLE_BINARY] = 31;
            LATCH_TABLE[TABLE_PUNCT][TABLE_UPPER]  = 31;
            SHIFT_TABLE[TABLE_DIGIT][TABLE_PUNCT]  = 0;
            LATCH_TABLE[TABLE_DIGIT][TABLE_UPPER]  = 30;
            SHIFT_TABLE[TABLE_DIGIT][TABLE_UPPER]  = 31;
            NB_BITS_COMPACT = new int[5];
            for (int i = 1; i < NB_BITS_COMPACT.Length; i++)
            {
                NB_BITS_COMPACT[i] = (88 + 16 * i) * i;
            }
            NB_BITS = new int[33];
            for (int i = 1; i < NB_BITS.Length; i++)
            {
                NB_BITS[i] = (112 + 16 * i) * i;
            }
        }
示例#8
0
        private DataCharacter decodeDataCharacter(BitArray row, FinderPattern pattern, bool outsideChar)
        {
            int[] counters = getDataCharacterCounters();
            SupportClass.Fill(counters, 0);

            if (outsideChar)
            {
                if (!recordPatternInReverse(row, pattern.StartEnd[0], counters))
                {
                    return(null);
                }
            }
            else
            {
                if (!recordPattern(row, pattern.StartEnd[1], counters))
                {
                    return(null);
                }

                // reverse it
                for (int i = 0, j = counters.Length - 1; i < j; i++, j--)
                {
                    int temp = counters[i];
                    counters[i] = counters[j];
                    counters[j] = temp;
                }
            }

            int   numModules   = outsideChar ? 16 : 15;
            float elementWidth = (float)ZXing.Common.Detector.MathUtils.sum(counters) / (float)numModules;

            int[]   oddCounts          = this.getOddCounts();
            int[]   evenCounts         = this.getEvenCounts();
            float[] oddRoundingErrors  = this.getOddRoundingErrors();
            float[] evenRoundingErrors = this.getEvenRoundingErrors();

            for (int i = 0; i < counters.Length; i++)
            {
                float value   = (float)counters[i] / elementWidth;
                int   rounded = (int)(value + 0.5f); // Round
                if (rounded < 1)
                {
                    rounded = 1;
                }
                else if (rounded > 8)
                {
                    rounded = 8;
                }
                int offset = i >> 1;
                if ((i & 0x01) == 0)
                {
                    oddCounts[offset]         = rounded;
                    oddRoundingErrors[offset] = value - rounded;
                }
                else
                {
                    evenCounts[offset]         = rounded;
                    evenRoundingErrors[offset] = value - rounded;
                }
            }

            if (!adjustOddEvenCounts(outsideChar, numModules))
            {
                return(null);
            }

            int oddSum             = 0;
            int oddChecksumPortion = 0;

            for (int i = oddCounts.Length - 1; i >= 0; i--)
            {
                oddChecksumPortion *= 9;
                oddChecksumPortion += oddCounts[i];
                oddSum             += oddCounts[i];
            }
            int evenChecksumPortion = 0;
            int evenSum             = 0;

            for (int i = evenCounts.Length - 1; i >= 0; i--)
            {
                evenChecksumPortion *= 9;
                evenChecksumPortion += evenCounts[i];
                evenSum             += evenCounts[i];
            }
            int checksumPortion = oddChecksumPortion + 3 * evenChecksumPortion;

            if (outsideChar)
            {
                if ((oddSum & 0x01) != 0 || oddSum > 12 || oddSum < 4)
                {
                    return(null);
                }
                int group      = (12 - oddSum) / 2;
                int oddWidest  = OUTSIDE_ODD_WIDEST[group];
                int evenWidest = 9 - oddWidest;
                int vOdd       = RSSUtils.getRSSvalue(oddCounts, oddWidest, false);
                int vEven      = RSSUtils.getRSSvalue(evenCounts, evenWidest, true);
                int tEven      = OUTSIDE_EVEN_TOTAL_SUBSET[group];
                int gSum       = OUTSIDE_GSUM[group];
                return(new DataCharacter(vOdd * tEven + vEven + gSum, checksumPortion));
            }
            else
            {
                if ((evenSum & 0x01) != 0 || evenSum > 10 || evenSum < 4)
                {
                    return(null);
                }
                int group      = (10 - evenSum) / 2;
                int oddWidest  = INSIDE_ODD_WIDEST[group];
                int evenWidest = 9 - oddWidest;
                int vOdd       = RSSUtils.getRSSvalue(oddCounts, oddWidest, true);
                int vEven      = RSSUtils.getRSSvalue(evenCounts, evenWidest, false);
                int tOdd       = INSIDE_ODD_TOTAL_SUBSET[group];
                int gSum       = INSIDE_GSUM[group];
                return(new DataCharacter(vEven * tOdd + vOdd + gSum, checksumPortion));
            }
        }
示例#9
0
 /// <summary>
 /// sets everything to 0
 /// </summary>
 /// <param name="counts"></param>
 protected static void doClearCounts(int[] counts)
 {
     SupportClass.Fill(counts, 0);
 }