Example #1
0
 private static void EmbedTimingPatterns(ByteMatrix matrix)
 {
     // -8 is for skipping position detection patterns (size 7), and two horizontal/vertical
     // separation patterns (size 1). Thus, 8 = 7 + 1.
     for (int i = 8; i < matrix.Width - 8; ++i)
     {
         int bit = (i + 1) % 2;
         // Horizontal line.
         if (IsEmpty(matrix[i, 6]))
         {
             matrix[i, 6] = bit;
         }
         // Vertical line.
         if (IsEmpty(matrix[6, i]))
         {
             matrix[6, i] = bit;
         }
     }
 }
Example #2
0
        /// <summary>
        /// Apply mask penalty rule 3 and return the penalty. Find consecutive cells of 00001011101 or
        /// 10111010000, and give penalty to them.  If we find patterns like 000010111010000, we give
        /// penalties twice (i.e. 40 * 2).
        /// </summary>
        /// <param name="matrix">The matrix.</param>
        /// <returns></returns>
        public static int ApplyMaskPenaltyRule3(ByteMatrix matrix)
        {
            int numPenalties = 0;

            byte[][] array  = matrix.Array;
            int      width  = matrix.Width;
            int      height = matrix.Height;

            for (int y = 0; y < height; y++)
            {
                for (int x = 0; x < width; x++)
                {
                    byte[] arrayY = array[y];  // We can at least optimize this access
                    if (x + 6 < width &&
                        arrayY[x] == 1 &&
                        arrayY[x + 1] == 0 &&
                        arrayY[x + 2] == 1 &&
                        arrayY[x + 3] == 1 &&
                        arrayY[x + 4] == 1 &&
                        arrayY[x + 5] == 0 &&
                        arrayY[x + 6] == 1 &&
                        (IsWhiteHorizontal(arrayY, x - 4, x) || IsWhiteHorizontal(arrayY, x + 7, x + 11)))
                    {
                        numPenalties++;
                    }
                    if (y + 6 < height &&
                        array[y][x] == 1 &&
                        array[y + 1][x] == 0 &&
                        array[y + 2][x] == 1 &&
                        array[y + 3][x] == 1 &&
                        array[y + 4][x] == 1 &&
                        array[y + 5][x] == 0 &&
                        array[y + 6][x] == 1 &&
                        (IsWhiteVertical(array, x, y - 4, y) || IsWhiteVertical(array, x, y + 7, y + 11)))
                    {
                        numPenalties++;
                    }
                }
            }
            return(numPenalties * N3);
        }
Example #3
0
        /// <summary>
        /// Apply mask penalty rule 2 and return the penalty. Find 2x2 blocks with the same color and give
        /// penalty to them. This is actually equivalent to the spec's rule, which is to find MxN blocks and give a
        /// penalty proportional to (M-1)x(N-1), because this is the number of 2x2 blocks inside such a block.
        /// </summary>
        /// <param name="matrix">The matrix.</param>
        /// <returns></returns>
        public static int ApplyMaskPenaltyRule2(ByteMatrix matrix)
        {
            int penalty = 0;
            var array   = matrix.Array;
            int width   = matrix.Width;
            int height  = matrix.Height;

            for (int y = 0; y < height - 1; y++)
            {
                var arrayY  = array[y];
                var arrayY1 = array[y + 1];
                for (int x = 0; x < width - 1; x++)
                {
                    int value = arrayY[x];
                    if (value == arrayY[x + 1] && value == arrayY1[x] && value == arrayY1[x + 1])
                    {
                        penalty++;
                    }
                }
            }
            return(N2 * penalty);
        }
Example #4
0
        /// <summary>
        /// Apply mask penalty rule 4 and return the penalty. Calculate the ratio of dark cells and give
        /// penalty if the ratio is far from 50%. It gives 10 penalty for 5% distance.
        /// </summary>
        /// <param name="matrix">The matrix.</param>
        /// <returns></returns>
        public static int ApplyMaskPenaltyRule4(ByteMatrix matrix)
        {
            int numDarkCells = 0;
            var array        = matrix.Array;
            int width        = matrix.Width;
            int height       = matrix.Height;

            for (int y = 0; y < height; y++)
            {
                var arrayY = array[y];
                for (int x = 0; x < width; x++)
                {
                    if (arrayY[x] == 1)
                    {
                        numDarkCells++;
                    }
                }
            }
            var numTotalCells        = matrix.Height * matrix.Width;
            var darkRatio            = (double)numDarkCells / numTotalCells;
            var fivePercentVariances = (int)(Math.Abs(darkRatio - 0.5) * 20.0); // * 100.0 / 5.0

            return(fivePercentVariances * N4);
        }
Example #5
0
 /// <summary>
 /// Apply mask penalty rule 1 and return the penalty. Find repetitive cells with the same color and
 /// give penalty to them. Example: 00000 or 11111.
 /// </summary>
 /// <param name="matrix">The matrix.</param>
 /// <returns></returns>
 public static int ApplyMaskPenaltyRule1(ByteMatrix matrix)
 {
     return(ApplyMaskPenaltyRule1Internal(matrix, true) + ApplyMaskPenaltyRule1Internal(matrix, false));
 }
Example #6
0
        /// <summary>
        /// Embed type information. On success, modify the matrix.
        /// </summary>
        /// <param name="ecLevel">The ec level.</param>
        /// <param name="maskPattern">The mask pattern.</param>
        /// <param name="matrix">The matrix.</param>
        public static void EmbedTypeInfo(ErrorCorrectionLevel ecLevel, int maskPattern, ByteMatrix matrix)
        {
            BitArray typeInfoBits = new BitArray();

            MakeTypeInfoBits(ecLevel, maskPattern, typeInfoBits);

            for (int i = 0; i < typeInfoBits.Size; ++i)
            {
                // Place bits in LSB to MSB order.  LSB (least significant bit) is the last value in
                // "typeInfoBits".
                int bit = typeInfoBits[typeInfoBits.Size - 1 - i] ? 1 : 0;

                // Type info bits at the left top corner. See 8.9 of JISX0510:2004 (p.46).
                int[] coordinates = TYPE_INFO_COORDINATES[i];
                int   x1          = coordinates[0];
                int   y1          = coordinates[1];
                matrix[x1, y1] = bit;

                if (i < 8)
                {
                    // Right top corner.
                    int x2 = matrix.Width - i - 1;
                    int y2 = 8;
                    matrix[x2, y2] = bit;
                }
                else
                {
                    // Left bottom corner.
                    int x2 = 8;
                    int y2 = matrix.Height - 7 + (i - 8);
                    matrix[x2, y2] = bit;
                }
            }
        }
Example #7
0
 /// <summary>
 /// Set all cells to 2.  2 means that the cell is empty (not set yet).
 ///
 /// JAVAPORT: We shouldn't need to do this at all. The code should be rewritten to begin encoding
 /// with the ByteMatrix initialized all to zero.
 /// </summary>
 /// <param name="matrix">The matrix.</param>
 public static void ClearMatrix(ByteMatrix matrix)
 {
     matrix.Clear(2);
 }
Example #8
0
        /// <summary>
        /// Encodes the specified content.
        /// </summary>
        /// <param name="content">The content.</param>
        /// <param name="ecLevel">The ec level.</param>
        /// <param name="hints">The hints.</param>
        /// <returns></returns>
        public static QRCode Encode(String content, ErrorCorrectionLevel ecLevel)
        {
            var encoding = DEFAULT_BYTE_MODE_ENCODING;
            var generateECI = !DEFAULT_BYTE_MODE_ENCODING.Equals(encoding);

            // Pick an encoding mode appropriate for the content. Note that this will not attempt to use
            // multiple modes / segments even if that were more efficient. Twould be nice.
            var mode = ChooseMode(content, encoding);

            // This will store the header information, like mode and
            // length, as well as "header" segments like an ECI segment.
            var headerBits = new BitArray();

            // Append ECI segment if applicable
            if (mode == Mode.BYTE && generateECI)
            {
                var eci = CharacterSetECI.GetCharacterSetECIByName(encoding);
                if (eci != null)
                {
                    AppendECI(eci, headerBits);
                }
            }

            // (With ECI in place,) Write the mode marker
            AppendModeInfo(mode, headerBits);

            // Collect data within the main segment, separately, to count its size if needed. Don't add it to
            // main payload yet.
            var dataBits = new BitArray();
            AppendBytes(content, mode, dataBits, encoding);

            Version version = RecommendVersion(ecLevel, mode, headerBits, dataBits);

            var headerAndDataBits = new BitArray();
            headerAndDataBits.AppendBitArray(headerBits);
            // Find "length" of main segment and write it
            var numLetters = mode == Mode.BYTE ? dataBits.SizeInBytes : content.Length;
            AppendLengthInfo(numLetters, version, mode, headerAndDataBits);
            // Put data together into the overall payload
            headerAndDataBits.AppendBitArray(dataBits);

            var ecBlocks = version.GetECBlocksForLevel(ecLevel);
            var numDataBytes = version.TotalCodewords - ecBlocks.TotalECCodewords;

            // Terminate the bits properly.
            TerminateBits(numDataBytes, headerAndDataBits);

            // Interleave data bits with error correction code.
            var finalBits = InterleaveWithECBytes(headerAndDataBits,
                                                       version.TotalCodewords,
                                                       numDataBytes,
                                                       ecBlocks.NumBlocks);

            var qrCode = new QRCode
            {
                ECLevel = ecLevel,
                Mode = mode,
                Version = version
            };

            //  Choose the mask pattern and set to "qrCode".
            var dimension = version.DimensionForVersion;
            var matrix = new ByteMatrix(dimension, dimension);
            var maskPattern = ChooseMaskPattern(finalBits, ecLevel, version, matrix);
            qrCode.MaskPattern = maskPattern;

            // Build the matrix and set it to "qrCode".
            MatrixUtil.BuildMatrix(finalBits, ecLevel, version, maskPattern, matrix);
            qrCode.Matrix = matrix;

            return qrCode;
        }
Example #9
0
        static int ChooseMaskPattern(BitArray bits, ErrorCorrectionLevel ecLevel, Version version, ByteMatrix matrix)
        {
            int minPenalty = Int32.MaxValue;  // Lower penalty is better.
            int bestMaskPattern = -1;
            // We try all mask patterns to choose the best one.
            for (int maskPattern = 0; maskPattern < QRCode.NUM_MASK_PATTERNS; maskPattern++)
            {

                MatrixUtil.BuildMatrix(bits, ecLevel, version, maskPattern, matrix);
                int penalty = CalculateMaskPenalty(matrix);
                if (penalty < minPenalty)
                {

                    minPenalty = penalty;
                    bestMaskPattern = maskPattern;
                }
            }
            return bestMaskPattern;
        }