JAVAPORT: The original code was a 2D array of ints, but since it only ever gets assigned 0, 1 and 2 I'm going to use less memory and go with bytes.
Beispiel #1
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 penalty = 0;
    var 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++)
       {
          // Tried to simplify following conditions but failed.
          if (x + 6 < width &&
              array[y][x] == 1 &&
              array[y][x + 1] == 0 &&
              array[y][x + 2] == 1 &&
              array[y][x + 3] == 1 &&
              array[y][x + 4] == 1 &&
              array[y][x + 5] == 0 &&
              array[y][x + 6] == 1 &&
              ((x + 10 < width &&
                  array[y][x + 7] == 0 &&
                  array[y][x + 8] == 0 &&
                  array[y][x + 9] == 0 &&
                  array[y][x + 10] == 0) ||
               (x - 4 >= 0 &&
                  array[y][x - 1] == 0 &&
                  array[y][x - 2] == 0 &&
                  array[y][x - 3] == 0 &&
                  array[y][x - 4] == 0)))
          {
             penalty += N3;
          }
          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 &&
              ((y + 10 < height &&
                  array[y + 7][x] == 0 &&
                  array[y + 8][x] == 0 &&
                  array[y + 9][x] == 0 &&
                  array[y + 10][x] == 0) ||
               (y - 4 >= 0 &&
                  array[y - 1][x] == 0 &&
                  array[y - 2][x] == 0 &&
                  array[y - 3][x] == 0 &&
                  array[y - 4][x] == 0)))
          {
             penalty += N3;
          }
       }
    }
    return penalty;
 }
Beispiel #2
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;
         }
     }
 }
Beispiel #3
0
 // Apply mask penalty rule 2 and return the penalty. Find 2x2 blocks with the same color and give
 // penalty to them.
 public static int applyMaskPenaltyRule2(ByteMatrix matrix)
 {
     int penalty = 0;
      sbyte[][] array = matrix.Array;
      int width = matrix.Width;
      int height = matrix.Height;
      for (int y = 0; y < height - 1; ++y)
      {
     for (int x = 0; x < width - 1; ++x)
     {
        int value_Renamed = array[y][x];
        if (value_Renamed == array[y][x + 1] && value_Renamed == array[y + 1][x] && value_Renamed == array[y + 1][x + 1])
        {
           penalty += 3;
        }
     }
      }
      return penalty;
 }
Beispiel #4
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++)
    {
       for (int x = 0; x < width - 1; x++)
       {
          int value = array[y][x];
          if (value == array[y][x + 1] && value == array[y + 1][x] && value == array[y + 1][x + 1])
          {
             penalty++;
          }
       }
    }
    return N2 * penalty;
 }
Beispiel #5
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++)
            {
                for (int x = 0; x < width - 1; x++)
                {
                    int value = array[y][x];
                    if (value == array[y][x + 1] && value == array[y + 1][x] && value == array[y + 1][x + 1])
                    {
                        penalty++;
                    }
                }
            }
            return(N2 * penalty);
        }
Beispiel #6
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);
        }
Beispiel #7
0
        // Apply mask penalty rule 2 and return the penalty. Find 2x2 blocks with the same color and give
        // penalty to them.
        public static int applyMaskPenaltyRule2(ByteMatrix matrix)
        {
            int penalty = 0;

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

            for (int y = 0; y < height - 1; ++y)
            {
                for (int x = 0; x < width - 1; ++x)
                {
                    int value_Renamed = array[y][x];
                    if (value_Renamed == array[y][x + 1] && value_Renamed == array[y + 1][x] && value_Renamed == array[y + 1][x + 1])
                    {
                        penalty += 3;
                    }
                }
            }
            return(penalty);
        }
Beispiel #8
0
        private 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);
        }
Beispiel #9
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;
 }
Beispiel #10
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);
        }
Beispiel #11
0
        // 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. Examples:
        // -   0% => 100
        // -  40% =>  20
        // -  45% =>  10
        // -  50% =>   0
        // -  55% =>  10
        // -  55% =>  20
        // - 100% => 100
        public static int applyMaskPenaltyRule4(ByteMatrix matrix)
        {
            int numDarkCells = 0;

            sbyte[][] 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)
                {
                    if (array[y][x] == 1)
                    {
                        numDarkCells += 1;
                    }
                }
            }
            int    numTotalCells = matrix.Height * matrix.Width;
            double darkRatio     = (double)numDarkCells / numTotalCells;

            //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(System.Math.Abs((int)(darkRatio * 100 - 50)) / 5 * 10);
        }
Beispiel #12
0
        public static QRCode encode(String content,
                                    ErrorCorrectionLevel ecLevel,
                                    IDictionary hints)
        {
            // Determine what character encoding has been specified by the caller, if any
            String encoding = hints == null || !hints.Contains(EncodeHintType.CHARACTER_SET) ? null : (String)hints[EncodeHintType.CHARACTER_SET];

            if (encoding == null)
            {
                encoding = DEFAULT_BYTE_MODE_ENCODING;
            }
            bool doSelectMask = hints == null || !hints.Contains(EncodeHintType.QR_DO_MASK_SELECTION) ? false : (bool)hints[EncodeHintType.QR_DO_MASK_SELECTION];

            // 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.
            Mode mode = chooseMode(content, encoding);

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

            // Append ECI segment if applicable
            if (mode == Mode.BYTE && !DEFAULT_BYTE_MODE_ENCODING.Equals(encoding))
            {
                CharacterSetECI 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.
            BitArray dataBits = new BitArray();

            appendBytes(content, mode, dataBits, encoding);

            // Hard part: need to know version to know how many bits length takes. But need to know how many
            // bits it takes to know version. To pick version size assume length takes maximum bits
            int bitsNeeded = headerBits.Size
                             + mode.getCharacterCountBits(Version.getVersionForNumber(40))
                             + dataBits.Size;
            Version version = chooseVersion(bitsNeeded, ecLevel);

            BitArray headerAndDataBits = new BitArray();

            headerAndDataBits.appendBitArray(headerBits);
            // Find "length" of main segment and write it
            int numLetters = mode == Mode.BYTE ? dataBits.SizeInBytes : content.Length;

            appendLengthInfo(numLetters, version, mode, headerAndDataBits);
            // Put data together into the overall payload
            headerAndDataBits.appendBitArray(dataBits);

            Version.ECBlocks ecBlocks = version.getECBlocksForLevel(ecLevel);
            int numDataBytes          = version.TotalCodewords - ecBlocks.TotalECCodewords;

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

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

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

            //  Choose the mask pattern and set to "qrCode".
            int        dimension   = version.DimensionForVersion;
            ByteMatrix matrix      = new ByteMatrix(dimension, dimension);
            int        maskPattern = 3;

            if (doSelectMask)
            {
                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);
        }
Beispiel #13
0
 // Helper function for applyMaskPenaltyRule1. We need this for doing this calculation in both
 // vertical and horizontal orders respectively.
 private static int applyMaskPenaltyRule1Internal(ByteMatrix matrix, bool isHorizontal)
 {
     int penalty = 0;
      int numSameBitCells = 0;
      int prevBit = -1;
      // Horizontal mode:
      //   for (int i = 0; i < matrix.height(); ++i) {
      //     for (int j = 0; j < matrix.width(); ++j) {
      //       int bit = matrix.get(i, j);
      // Vertical mode:
      //   for (int i = 0; i < matrix.width(); ++i) {
      //     for (int j = 0; j < matrix.height(); ++j) {
      //       int bit = matrix.get(j, i);
      int iLimit = isHorizontal ? matrix.Height : matrix.Width;
      int jLimit = isHorizontal ? matrix.Width : matrix.Height;
      sbyte[][] array = matrix.Array;
      for (int i = 0; i < iLimit; ++i)
      {
     for (int j = 0; j < jLimit; ++j)
     {
        int bit = isHorizontal ? array[i][j] : array[j][i];
        if (bit == prevBit)
        {
           numSameBitCells += 1;
           // Found five repetitive cells with the same color (bit).
           // We'll give penalty of 3.
           if (numSameBitCells == 5)
           {
              penalty += 3;
           }
           else if (numSameBitCells > 5)
           {
              // After five repetitive cells, we'll add the penalty one
              // by one.
              penalty += 1;
           }
        }
        else
        {
           numSameBitCells = 1; // Include the cell itself.
           prevBit = bit;
        }
     }
     numSameBitCells = 0; // Clear at each row/column.
      }
      return penalty;
 }
Beispiel #14
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));
 }
Beispiel #15
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,
                                    IDictionary <EncodeHintType, object> hints)
        {
            // Determine what character encoding has been specified by the caller, if any
#if !SILVERLIGHT || WINDOWS_PHONE
            String encoding = hints == null || !hints.ContainsKey(EncodeHintType.CHARACTER_SET) ? null : (String)hints[EncodeHintType.CHARACTER_SET];
            if (encoding == null)
            {
                encoding = DEFAULT_BYTE_MODE_ENCODING;
            }
            bool generateECI = !DEFAULT_BYTE_MODE_ENCODING.Equals(encoding);
#else
            // Silverlight supports only UTF-8 and UTF-16 out-of-the-box
            const string encoding = "UTF-8";
            // caller of the method can only control if the ECI segment should be written
            // character set is fixed to UTF-8; but some scanners doesn't like the ECI segment
            bool generateECI = (hints != null && hints.ContainsKey(EncodeHintType.CHARACTER_SET));
#endif
            // http://zxingnet.codeplex.com/discussions/399045
            if (hints != null && hints.ContainsKey(EncodeHintType.DISABLE_ECI) && (bool)hints[EncodeHintType.DISABLE_ECI])
            {
                generateECI = false;
            }

            // 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.
            Mode mode = chooseMode(content, encoding);

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

            // Append ECI segment if applicable
            if (mode == Mode.BYTE && generateECI)
            {
                CharacterSetECI 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.
            BitArray dataBits = new BitArray();
            appendBytes(content, mode, dataBits, encoding);

            // Hard part: need to know version to know how many bits length takes. But need to know how many
            // bits it takes to know version. First we take a guess at version by assuming version will be
            // the minimum, 1:

            int provisionalBitsNeeded = headerBits.Size
                                        + mode.getCharacterCountBits(Version.getVersionForNumber(1))
                                        + dataBits.Size;
            Version provisionalVersion = chooseVersion(provisionalBitsNeeded, ecLevel);

            // Use that guess to calculate the right version. I am still not sure this works in 100% of cases.
            int bitsNeeded = headerBits.Size
                             + mode.getCharacterCountBits(provisionalVersion)
                             + dataBits.Size;
            Version version = chooseVersion(bitsNeeded, ecLevel);

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

            Version.ECBlocks ecBlocks = version.getECBlocksForLevel(ecLevel);
            int numDataBytes          = version.TotalCodewords - ecBlocks.TotalECCodewords;

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

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

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

            //  Choose the mask pattern and set to "qrCode".
            int        dimension   = version.DimensionForVersion;
            ByteMatrix matrix      = new ByteMatrix(dimension, dimension);
            int        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);
        }
Beispiel #16
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;
 }
Beispiel #17
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 x1 = TYPE_INFO_COORDINATES[i][0];
                int y1 = TYPE_INFO_COORDINATES[i][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;
                }
            }
        }
Beispiel #18
0
 /// <summary>
 /// Build 2D matrix of QR Code from "dataBits" with "ecLevel", "version" and "getMaskPattern". On
 /// success, store the result in "matrix" and return true.
 /// </summary>
 /// <param name="dataBits">The data bits.</param>
 /// <param name="ecLevel">The ec level.</param>
 /// <param name="version">The version.</param>
 /// <param name="maskPattern">The mask pattern.</param>
 /// <param name="matrix">The matrix.</param>
 public static void buildMatrix(BitArray dataBits, ErrorCorrectionLevel ecLevel, Version version, int maskPattern, ByteMatrix matrix)
 {
     clearMatrix(matrix);
     embedBasicPatterns(version, matrix);
     // Type information appear with any version.
     embedTypeInfo(ecLevel, maskPattern, matrix);
     // Version info appear if version >= 7.
     maybeEmbedVersionInfo(version, matrix);
     // Data should be embedded at end.
     embedDataBits(dataBits, maskPattern, matrix);
 }
Beispiel #19
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);
 }
Beispiel #20
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,
                                    IDictionary <EncodeHintType, object> hints)
        {
            // Determine what character encoding has been specified by the caller, if any
            bool hasEncodingHint = hints != null && hints.ContainsKey(EncodeHintType.CHARACTER_SET);

#if !SILVERLIGHT || WINDOWS_PHONE
            var encoding = hints == null || !hints.ContainsKey(EncodeHintType.CHARACTER_SET) ? null : (String)hints[EncodeHintType.CHARACTER_SET];
            if (encoding == null)
            {
                encoding = DEFAULT_BYTE_MODE_ENCODING;
            }
            var generateECI = hasEncodingHint || !DEFAULT_BYTE_MODE_ENCODING.Equals(encoding);
#else
            // Silverlight supports only UTF-8 and UTF-16 out-of-the-box
            const string encoding = "UTF-8";
            // caller of the method can only control if the ECI segment should be written
            // character set is fixed to UTF-8; but some scanners doesn't like the ECI segment
            var generateECI = hasEncodingHint;
#endif

            // 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)
                {
                    var eciIsExplicitDisabled = (hints != null && hints.ContainsKey(EncodeHintType.DISABLE_ECI) && hints[EncodeHintType.DISABLE_ECI] != null && Convert.ToBoolean(hints[EncodeHintType.DISABLE_ECI].ToString()));
                    if (!eciIsExplicitDisabled)
                    {
                        appendECI(eci, headerBits);
                    }
                }
            }

            // Append the FNC1 mode header for GS1 formatted data if applicable
            var hasGS1FormatHint = hints != null && hints.ContainsKey(EncodeHintType.GS1_FORMAT);
            if (hasGS1FormatHint && hints[EncodeHintType.GS1_FORMAT] != null && Convert.ToBoolean(hints[EncodeHintType.GS1_FORMAT].ToString()))
            {
                // GS1 formatted codes are prefixed with a FNC1 in first position mode header
                appendModeInfo(Mode.FNC1_FIRST_POSITION, 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;
            if (hints != null && hints.ContainsKey(EncodeHintType.QR_VERSION))
            {
                int versionNumber = Int32.Parse(hints[EncodeHintType.QR_VERSION].ToString());
                version = Version.getVersionForNumber(versionNumber);
                int bitsNeeded = calculateBitsNeeded(mode, headerBits, dataBits, version);
                if (!willFit(bitsNeeded, version, ecLevel))
                {
                    throw new WriterException("Data too big for requested version");
                }
            }
            else
            {
                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);
        }
Beispiel #21
0
 // 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. Examples:
 // -   0% => 100
 // -  40% =>  20
 // -  45% =>  10
 // -  50% =>   0
 // -  55% =>  10
 // -  55% =>  20
 // - 100% => 100
 public static int applyMaskPenaltyRule4(ByteMatrix matrix)
 {
     int numDarkCells = 0;
      sbyte[][] 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)
     {
        if (array[y][x] == 1)
        {
           numDarkCells += 1;
        }
     }
      }
      int numTotalCells = matrix.Height * matrix.Width;
      double darkRatio = (double)numDarkCells / numTotalCells;
      //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 System.Math.Abs((int)(darkRatio * 100 - 50)) / 5 * 10;
 }
Beispiel #22
0
 /// <summary>
 /// Helper function for applyMaskPenaltyRule1. We need this for doing this calculation in both
 /// vertical and horizontal orders respectively.
 /// </summary>
 /// <param name="matrix">The matrix.</param>
 /// <param name="isHorizontal">if set to <c>true</c> [is horizontal].</param>
 /// <returns></returns>
 private static int applyMaskPenaltyRule1Internal(ByteMatrix matrix, bool isHorizontal)
 {
    int penalty = 0;
    int iLimit = isHorizontal ? matrix.Height : matrix.Width;
    int jLimit = isHorizontal ? matrix.Width : matrix.Height;
    var array = matrix.Array;
    for (int i = 0; i < iLimit; i++)
    {
       int numSameBitCells = 0;
       int prevBit = -1;
       for (int j = 0; j < jLimit; j++)
       {
          int bit = isHorizontal ? array[i][j] : array[j][i];
          if (bit == prevBit)
          {
             numSameBitCells++;
          }
          else
          {
             if (numSameBitCells >= 5)
             {
                penalty += N1 + (numSameBitCells - 5);
             }
             numSameBitCells = 1;  // Include the cell itself.
             prevBit = bit;
          }
       }
       if (numSameBitCells >= 5)
       {
          penalty += N1 + (numSameBitCells - 5);
       }
    }
    return penalty;
 }
Beispiel #23
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);
 }