See ISO 18004:2006, 6.5.1. This enum encapsulates the four error correction levels defined by the QR code standard.

 private FormatInformation(int formatInfo)
 {
    // Bits 3,4
    errorCorrectionLevel = ErrorCorrectionLevel.forBits((formatInfo >> 3) & 0x03);
    // Bottom 3 bits
    dataMask = (byte)(formatInfo & 0x07);
 }
        private static ZXing.QrCode.Internal.Version ChooseVersion(int RequiredBits, out ErrorCorrectionLevel ECLevel)
        {
            var ecls = new ErrorCorrectionLevel[] { ErrorCorrectionLevel.H, ErrorCorrectionLevel.Q, ErrorCorrectionLevel.M, ErrorCorrectionLevel.L };
            int totalInputBytes = (RequiredBits + 7) / 8;

            // In the following comments, we use numbers of Version 7-H.
            for (int versionNum = 1; versionNum <= 40; versionNum++)
            {
                var version = ZXing.QrCode.Internal.Version.getVersionForNumber(versionNum);
                // numBytes = 196
                int numBytes = version.TotalCodewords;
                // getNumECBytes = 130

                if (numBytes >= totalInputBytes)
                {
                    for (int ecl = 0; ecl < ecls.Length; ecl++)
                    {
                        var ecBlocks = version.getECBlocksForLevel(ecls[ecl]);
                        int numEcBytes = ecBlocks.TotalECCodewords;
                        // getNumDataBytes = 196 - 130 = 66
                        int numDataBytes = numBytes - numEcBytes;
                        if (numDataBytes >= totalInputBytes)
                        {
                            ECLevel = ecls[ecl];
                            return version;
                        }
                    }
                }
            }
            throw new ArgumentException("Data too big", nameof(RequiredBits));
        }
Exemple #3
0
 private static Version chooseVersion(int numInputBits, ErrorCorrectionLevel ecLevel)
 {
     for (int versionNum = 1; versionNum <= 40; versionNum++)
     {
         var version = Version.getVersionForNumber(versionNum);
         if (willFit(numInputBits, version, ecLevel))
         {
             return(version);
         }
     }
     throw new WriterException("Data too big");
 }
Exemple #4
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);
 }
Exemple #5
0
        private DecoderResult decode(BitMatrixParser parser, IDictionary <DecodeHintType, object> hints)
        {
            Version version = parser.readVersion();

            if (version == null)
            {
                return(null);
            }
            var formatinfo = parser.readFormatInformation();

            if (formatinfo == null)
            {
                return(null);
            }
            ErrorCorrectionLevel ecLevel = formatinfo.ErrorCorrectionLevel;

            // Read codewords
            byte[] codewords = parser.readCodewords();
            if (codewords == null)
            {
                return(null);
            }
            // Separate into data blocks
            DataBlock[] dataBlocks = DataBlock.getDataBlocks(codewords, version, ecLevel);

            // Count total number of data bytes
            int totalBytes = 0;

            foreach (var dataBlock in dataBlocks)
            {
                totalBytes += dataBlock.NumDataCodewords;
            }
            byte[] resultBytes  = new byte[totalBytes];
            int    resultOffset = 0;

            // Error-correct and copy data blocks together into a stream of bytes
            foreach (var dataBlock in dataBlocks)
            {
                byte[] codewordBytes    = dataBlock.Codewords;
                int    numDataCodewords = dataBlock.NumDataCodewords;
                if (!correctErrors(codewordBytes, numDataCodewords))
                {
                    return(null);
                }
                for (int i = 0; i < numDataCodewords; i++)
                {
                    resultBytes[resultOffset++] = codewordBytes[i];
                }
            }

            // Decode the contents of that stream of bytes
            return(DecodedBitStreamParser.decode(resultBytes, version, ecLevel, hints));
        }
Exemple #6
0
        /// <summary>
        /// Decides the smallest version of QR code that will contain all of the provided data.
        /// </summary>
        /// <exception cref="WriterException">if the data cannot fit in any version</exception>
        private static Version recommendVersion(ErrorCorrectionLevel ecLevel, Mode mode, BitArray headerBits, BitArray dataBits)
        {
            // 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:
            var provisionalBitsNeeded = calculateBitsNeeded(mode, headerBits, dataBits, Version.getVersionForNumber(1));
            var provisionalVersion    = chooseVersion(provisionalBitsNeeded, ecLevel);

            // Use that guess to calculate the right version. I am still not sure this works in 100% of cases.
            var bitsNeeded = calculateBitsNeeded(mode, headerBits, dataBits, provisionalVersion);

            return(chooseVersion(bitsNeeded, ecLevel));
        }
Exemple #7
0
        /// <summary></summary>
        /// <returns>true if the number of input bits will fit in a code with the specified version and error correction level.</returns>
        private static bool willFit(int numInputBits, Version version, ErrorCorrectionLevel ecLevel)
        {
            // In the following comments, we use numbers of Version 7-H.
            // numBytes = 196
            var numBytes = version.TotalCodewords;
            // getNumECBytes = 130
            var ecBlocks   = version.getECBlocksForLevel(ecLevel);
            var numEcBytes = ecBlocks.TotalECCodewords;
            // getNumDataBytes = 196 - 130 = 66
            var numDataBytes    = numBytes - numEcBytes;
            var totalInputBytes = (numInputBits + 7) / 8;

            return(numDataBytes >= totalInputBytes);
        }
        public static ByteMatrix CreateRawQR(byte[] rawData, ErrorCorrectionLevel errorCorrectionLevel)
        {
            int versionNumber = GetSmallestVersion(rawData.Length, errorCorrectionLevel);
            ZXing.QrCode.Internal.Version version = ZXing.QrCode.Internal.Version.getVersionForNumber(versionNumber);

            BitArray dataBits = new BitArray();
            foreach (byte b in rawData)
                dataBits.appendBits(b, 8);

            ZXing.QrCode.Internal.Version.ECBlocks ecBlocks = version.getECBlocksForLevel(errorCorrectionLevel);
            int bytesLength = version.TotalCodewords - ecBlocks.TotalECCodewords;
            terminateBits(bytesLength, dataBits);

            BitArray resultBits = interleaveWithECBytes(dataBits, version.TotalCodewords, bytesLength, ecBlocks.NumBlocks);

            ByteMatrix matrix = new ByteMatrix(version.DimensionForVersion, version.DimensionForVersion);
            int maskPattern = chooseMaskPattern(resultBits, errorCorrectionLevel, version, matrix);

            MatrixUtil.buildMatrix(resultBits, errorCorrectionLevel, version, maskPattern, matrix);
            return matrix;
        }
Exemple #9
0
 private static Version chooseVersion(int numInputBits, ErrorCorrectionLevel ecLevel)
 {
     // In the following comments, we use numbers of Version 7-H.
     for (int versionNum = 1; versionNum <= 40; versionNum++)
     {
         Version version = Version.getVersionForNumber(versionNum);
         // numBytes = 196
         int numBytes = version.TotalCodewords;
         // getNumECBytes = 130
         Version.ECBlocks ecBlocks = version.getECBlocksForLevel(ecLevel);
         int numEcBytes            = ecBlocks.TotalECCodewords;
         // getNumDataBytes = 196 - 130 = 66
         int numDataBytes    = numBytes - numEcBytes;
         int totalInputBytes = (numInputBits + 7) / 8;
         if (numDataBytes >= totalInputBytes)
         {
             return(version);
         }
     }
     throw new WriterException("Data too big");
 }
Exemple #10
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);
        }
Exemple #11
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;
      }
Exemple #12
0
      /// <summary>
      /// Make bit vector of type information. On success, store the result in "bits" and return true.
      /// Encode error correction level and mask pattern. See 8.9 of
      /// JISX0510:2004 (p.45) for details.
      /// </summary>
      /// <param name="ecLevel">The ec level.</param>
      /// <param name="maskPattern">The mask pattern.</param>
      /// <param name="bits">The bits.</param>
      public static void makeTypeInfoBits(ErrorCorrectionLevel ecLevel, int maskPattern, BitArray bits)
      {
         if (!QRCode.isValidMaskPattern(maskPattern))
         {
            throw new WriterException("Invalid mask pattern");
         }
         int typeInfo = (ecLevel.Bits << 3) | maskPattern;
         bits.appendBits(typeInfo, 5);

         int bchCode = calculateBCHCode(typeInfo, TYPE_INFO_POLY);
         bits.appendBits(bchCode, 10);

         BitArray maskBits = new BitArray();
         maskBits.appendBits(TYPE_INFO_MASK_PATTERN, 15);
         bits.xor(maskBits);

         if (bits.Size != 15)
         {
            // Just in case.
            throw new WriterException("should not happen but we got: " + bits.Size);
         }
      }
Exemple #13
0
 /// <summary>
 /// Gets the EC blocks for level.
 /// </summary>
 /// <param name="ecLevel">The ec level.</param>
 /// <returns></returns>
 public ECBlocks getECBlocksForLevel(ErrorCorrectionLevel ecLevel)
 {
    return ecBlocks[ecLevel.ordinal()];
 }
Exemple #14
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);
 }
Exemple #15
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;
            }
         }
      }
Exemple #16
0
        private void loadSettings()
        {
            bool update = false;
            ///
            /// QR Detect indicator mask color
            ///
            try
            {
                maskColor = ColorTranslator.FromHtml( appSection.Settings["MaskColor"].Value );
            }
            catch
            {
                appSection.Settings.Add( "MaskColor", ColorTranslator.ToHtml( maskColor ) );
                update = true;
            }
            colorDlg.Color = maskColor;
            picMaskColor.BackColor = maskColor;

            ///
            /// Overlay Logo Icon
            ///
            try
            {
                overlayLogo = Convert.ToBoolean( appSection.Settings["OverlayLogo"].Value );
            }
            catch
            {
                appSection.Settings.Add( "OverlayLogo", overlayLogo.ToString() );
                update = true;
            }
            chkOverLogo.Checked = overlayLogo;

            try
            {
                overlayBGColor = ColorTranslator.FromHtml( appSection.Settings["OverlayBGColor"].Value );
            }
            catch
            {
                appSection.Settings.Add( "OverlayBGColor", ColorTranslator.ToHtml( overlayBGColor ) );
                update = true;
            }

            try
            {
                overlayLogoImage = appSection.Settings["OverlayLogoImage"].Value;
            }
            catch
            {
                appSection.Settings.Add( "OverlayLogoImage", overlayLogoImage );
                update = true;
            }

            ///
            /// QR Encode Error Level
            ///
            string errorString = "M";
            try
            {
                errorString = appSection.Settings["ErrorCorrectionLevel"].Value;
            }
            catch
            {
                appSection.Settings.Add( "ErrorCorrectionLevel", errorString );
                update = true;
            }

            if ( string.Equals( errorString, I18N._( "L" ), StringComparison.CurrentCultureIgnoreCase ) )
            {
                errorLevel = ErrorCorrectionLevel.L;
            }
            else if ( string.Equals( errorString, I18N._( "M" ), StringComparison.CurrentCultureIgnoreCase ) )
            {
                errorLevel = ErrorCorrectionLevel.M;
            }
            else if ( string.Equals( errorString, I18N._( "Q" ), StringComparison.CurrentCultureIgnoreCase ) )
            {
                errorLevel = ErrorCorrectionLevel.Q;
            }
            else if ( string.Equals( errorString, I18N._( "H" ), StringComparison.CurrentCultureIgnoreCase ) )
            {
                errorLevel = ErrorCorrectionLevel.H;
            }
            else
            {
                errorLevel = ErrorCorrectionLevel.M;
            }
            cbErrorLevel.SelectedIndex = cbErrorLevel.Items.IndexOf( I18N._( errorString ) );

            ///
            /// QR Decode Options
            ///
            try
            {
                chkDecodeFormat1D.Checked = Convert.ToBoolean( appSection.Settings["DecodeFormat1D"].Value );
            }
            catch
            {
                appSection.Settings.Add( "DecodeFormat1D", chkDecodeFormat1D.Checked.ToString() );
                update = true;
            }

            try
            {
                chkDecodeFormatDM.Checked = Convert.ToBoolean( appSection.Settings["DecodeFormatDM"].Value );
            }
            catch
            {
                appSection.Settings.Add( "DecodeFormatDM", chkDecodeFormatDM.Checked.ToString() );
                update = true;
            }

            try
            {
                chkDecodeFormatQR.Checked = Convert.ToBoolean( appSection.Settings["DecodeFormatQR"].Value );
            }
            catch
            {
                appSection.Settings.Add( "DecodeFormatQR", chkDecodeFormatQR.Checked.ToString() );
                update = true;
            }

            if(update) config.Save();
        }
      internal static DecoderResult decode(byte[] bytes,
                                           Version version,
                                           ErrorCorrectionLevel ecLevel,
                                           IDictionary<DecodeHintType, object> hints)
      {
         var bits = new BitSource(bytes);
         var result = new StringBuilder(50);
         var byteSegments = new List<byte[]>(1);
         var symbolSequence = -1;
         var parityData = -1;

         try
         {
            // CharacterSetECI currentCharacterSetECI = null;
            bool fc1InEffect = false;
            Mode mode;
            do
            {
               // While still another segment to read...
               if (bits.available() < 4)
               {
                  // OK, assume we're done. Really, a TERMINATOR mode should have been recorded here
                  mode = Mode.TERMINATOR;
               }
               else
               {
                  try
                  {
                     mode = Mode.forBits(bits.readBits(4)); // mode is encoded by 4 bits
                  }
                  catch (ArgumentException)
                  {
                     return null;
                  }
               }
               if (mode != Mode.TERMINATOR)
               {
                  if (mode == Mode.FNC1_FIRST_POSITION || mode == Mode.FNC1_SECOND_POSITION)
                  {
                     // We do little with FNC1 except alter the parsed result a bit according to the spec
                     fc1InEffect = true;
                  }
                  else if (mode == Mode.STRUCTURED_APPEND)
                  {
                     if (bits.available() < 16)
                     {
                        return null;
                     }
                     // not really supported; but sequence number and parity is added later to the result metadata
                     // Read next 8 bits (symbol sequence #) and 8 bits (parity data), then continue
                     symbolSequence = bits.readBits(8);
                     parityData = bits.readBits(8);
                  }
                  else if (mode == Mode.ECI)
                  {
                      /*
                     // Count doesn't apply to ECI
                     int value = parseECIValue(bits);
                     currentCharacterSetECI = CharacterSetECI.getCharacterSetECIByValue(value);
                     if (currentCharacterSetECI == null)
                     {
                        return null;
                     }
                       * */
                  }
                  else
                  {
                     // First handle Hanzi mode which does not start with character count
                     if (mode == Mode.HANZI)
                     {
                        //chinese mode contains a sub set indicator right after mode indicator
                        int subset = bits.readBits(4);
                        int countHanzi = bits.readBits(mode.getCharacterCountBits(version));
                        if (subset == GB2312_SUBSET)
                        {
                           if (!decodeHanziSegment(bits, result, countHanzi))
                              return null;
                        }
                     }
                     else
                     {
                        // "Normal" QR code modes:
                        // How many characters will follow, encoded in this mode?
                        int count = bits.readBits(mode.getCharacterCountBits(version));
                        if (mode == Mode.NUMERIC)
                        {
                           if (!decodeNumericSegment(bits, result, count))
                              return null;
                        }
                        else if (mode == Mode.ALPHANUMERIC)
                        {
                           if (!decodeAlphanumericSegment(bits, result, count, fc1InEffect))
                              return null;
                        }
                        else if (mode == Mode.BYTE)
                        {
                           if (!decodeByteSegment(bits, result, count, byteSegments, hints))
                              return null;
                        }
                        else if (mode == Mode.KANJI)
                        {
                           if (!decodeKanjiSegment(bits, result, count))
                              return null;
                        }
                        else
                        {
                           return null;
                        }
                     }
                  }
               }
            } while (mode != Mode.TERMINATOR);
         }
         catch (ArgumentException)
         {
            // from readBits() calls
            return null;
         }

#if WindowsCE
         var resultString = result.ToString().Replace("\n", "\r\n");
#else
         var resultString = result.ToString().Replace("\r\n", "\n").Replace("\n", Environment.NewLine);
#endif
         return new DecoderResult(bytes,
                                  resultString,
                                  byteSegments.Count == 0 ? null : byteSegments,
                                  ecLevel == null ? null : ecLevel.ToString(),
                                  symbolSequence, parityData);
      }
Exemple #18
0
 /// <summary>
 /// Encode "bytes" with the error correction level "ecLevel". The encoding mode will be chosen
 /// internally by chooseMode(). On success, store the result in "qrCode".
 /// We recommend you to use QRCode.EC_LEVEL_L (the lowest level) for
 /// "getECLevel" since our primary use is to show QR code on desktop screens. We don't need very
 /// strong error correction for this purpose.
 /// Note that there is no way to encode bytes in MODE_KANJI. We might want to add EncodeWithMode()
 /// with which clients can specify the encoding mode. For now, we don't need the functionality.
 /// </summary>
 /// <param name="content">The content.</param>
 /// <param name="ecLevel">The ec level.</param>
 public static QRCode encode(String content, ErrorCorrectionLevel ecLevel)
 {
     return(encode(content, ecLevel, null));
 }
        internal static DecoderResult decode(byte[] bytes,
                                             Version version,
                                             ErrorCorrectionLevel ecLevel,
                                             IDictionary <DecodeHintType, object> hints)
        {
            var bits           = new BitSource(bytes);
            var result         = new StringBuilder(50);
            var byteSegments   = new List <byte[]> (1);
            var symbolSequence = -1;
            var parityData     = -1;

            try {
                CharacterSetECI currentCharacterSetECI = null;
                bool            fc1InEffect            = false;
                Mode            mode;
                do
                {
                    // While still another segment to read...
                    if (bits.available() < 4)
                    {
                        // OK, assume we're done. Really, a TERMINATOR mode should have been recorded here
                        mode = Mode.TERMINATOR;
                    }
                    else
                    {
                        try {
                            mode = Mode.forBits(bits.readBits(4));                               // mode is encoded by 4 bits
                        } catch (ArgumentException) {
                            return(null);
                        }
                    }
                    if (mode != Mode.TERMINATOR)
                    {
                        if (mode == Mode.FNC1_FIRST_POSITION || mode == Mode.FNC1_SECOND_POSITION)
                        {
                            // We do little with FNC1 except alter the parsed result a bit according to the spec
                            fc1InEffect = true;
                        }
                        else if (mode == Mode.STRUCTURED_APPEND)
                        {
                            if (bits.available() < 16)
                            {
                                return(null);
                            }
                            // not really supported; but sequence number and parity is added later to the result metadata
                            // Read next 8 bits (symbol sequence #) and 8 bits (parity data), then continue
                            symbolSequence = bits.readBits(8);
                            parityData     = bits.readBits(8);
                        }
                        else if (mode == Mode.ECI)
                        {
                            // Count doesn't apply to ECI
                            int value = parseECIValue(bits);
                            currentCharacterSetECI = CharacterSetECI.getCharacterSetECIByValue(value);
                            if (currentCharacterSetECI == null)
                            {
                                return(null);
                            }
                        }
                        else
                        {
                            // First handle Hanzi mode which does not start with character count
                            if (mode == Mode.HANZI)
                            {
                                //chinese mode contains a sub set indicator right after mode indicator
                                int subset     = bits.readBits(4);
                                int countHanzi = bits.readBits(mode.getCharacterCountBits(version));
                                if (subset == GB2312_SUBSET)
                                {
                                    if (!decodeHanziSegment(bits, result, countHanzi))
                                    {
                                        return(null);
                                    }
                                }
                            }
                            else
                            {
                                // "Normal" QR code modes:
                                // How many characters will follow, encoded in this mode?
                                int count = bits.readBits(mode.getCharacterCountBits(version));
                                if (mode == Mode.NUMERIC)
                                {
                                    if (!decodeNumericSegment(bits, result, count))
                                    {
                                        return(null);
                                    }
                                }
                                else if (mode == Mode.ALPHANUMERIC)
                                {
                                    if (!decodeAlphanumericSegment(bits, result, count, fc1InEffect))
                                    {
                                        return(null);
                                    }
                                }
                                else if (mode == Mode.BYTE)
                                {
                                    if (!decodeByteSegment(bits, result, count, currentCharacterSetECI, byteSegments, hints))
                                    {
                                        return(null);
                                    }
                                }
                                else if (mode == Mode.KANJI)
                                {
                                    if (!decodeKanjiSegment(bits, result, count))
                                    {
                                        return(null);
                                    }
                                }
                                else
                                {
                                    return(null);
                                }
                            }
                        }
                    }
                } while (mode != Mode.TERMINATOR);
            } catch (ArgumentException) {
                // from readBits() calls
                return(null);
            }

#if WindowsCE
            var resultString = result.ToString().Replace("\n", "\r\n");
#else
            var resultString = result.ToString().Replace("\r\n", "\n").Replace("\n", Environment.NewLine);
#endif
            return(new DecoderResult(bytes,
                                     resultString,
                                     byteSegments.Count == 0 ? null : byteSegments,
                                     ecLevel == null ? null : ecLevel.ToString(),
                                     symbolSequence, parityData));
        }
Exemple #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);
        }
Exemple #21
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;
        }
Exemple #22
0
 /// <summary>
 /// Gets the EC blocks for level.
 /// </summary>
 /// <param name="ecLevel">The ec level.</param>
 /// <returns></returns>
 public ECBlocks getECBlocksForLevel(ErrorCorrectionLevel ecLevel)
 {
     return(ecBlocks[ecLevel.ordinal()]);
 }
Exemple #23
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);
        }
 private static int GetSmallestVersion(int size, ErrorCorrectionLevel errorCorrectionLevel)
 {
     return Array.FindIndex(MaxQRSize[errorCorrectionLevel.ordinal()], i => i >= size) + 1;
 }
Exemple #25
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);
        }
Exemple #26
0
 /// <summary>
 /// Encode "bytes" with the error correction level "ecLevel". The encoding mode will be chosen
 /// internally by chooseMode(). On success, store the result in "qrCode".
 /// We recommend you to use QRCode.EC_LEVEL_L (the lowest level) for
 /// "getECLevel" since our primary use is to show QR code on desktop screens. We don't need very
 /// strong error correction for this purpose.
 /// Note that there is no way to encode bytes in MODE_KANJI. We might want to add EncodeWithMode()
 /// with which clients can specify the encoding mode. For now, we don't need the functionality.
 /// </summary>
 /// <param name="content">text to encode</param>
 /// <param name="ecLevel">error correction level to use</param>
 /// <returns><see cref="QRCode"/> representing the encoded QR code</returns>
 public static QRCode encode(String content, ErrorCorrectionLevel ecLevel)
 {
    return encode(content, ecLevel, null);
 }
      private static void compareToGoldenFile(String contents,
                                              ErrorCorrectionLevel ecLevel,
                                              int resolution,
                                              String fileName)
      {
         var image = loadImage(fileName);
         Assert.NotNull(image);
         BitMatrix goldenResult = createMatrixFromImage(image);
         Assert.NotNull(goldenResult);

         QRCodeWriter writer = new QRCodeWriter();
         IDictionary<EncodeHintType, Object> hints = new Dictionary<EncodeHintType, Object>();
         hints[EncodeHintType.ERROR_CORRECTION] = ecLevel;
         BitMatrix generatedResult = writer.encode(contents, BarcodeFormat.QR_CODE, resolution,
             resolution, hints);

         Assert.AreEqual(resolution, generatedResult.Width);
         Assert.AreEqual(resolution, generatedResult.Height);
         Assert.AreEqual(goldenResult, generatedResult);
      }
Exemple #28
0
        private void cbErrorLevel_SelectedIndexChanged( object sender, EventArgs e )
        {
            if ( !this.Visible ) return;

            string errorString = cbErrorLevel.SelectedItem.ToString();
            if ( string.Equals( errorString, I18N._( "L" ), StringComparison.CurrentCultureIgnoreCase ) )
            {
                errorLevel = ErrorCorrectionLevel.L;
            }
            else if ( string.Equals( errorString, I18N._( "M" ), StringComparison.CurrentCultureIgnoreCase ) )
            {
                errorLevel = ErrorCorrectionLevel.M;
            }
            else if ( string.Equals( errorString, I18N._( "Q" ), StringComparison.CurrentCultureIgnoreCase ) )
            {
                errorLevel = ErrorCorrectionLevel.Q;
            }
            else if ( string.Equals( errorString, I18N._( "H" ), StringComparison.CurrentCultureIgnoreCase ) )
            {
                errorLevel = ErrorCorrectionLevel.H;
            }
            else
            {
                errorLevel = ErrorCorrectionLevel.Q;
            }
            appSection.Settings["ErrorCorrectionLevel"].Value = errorString;
            config.Save();
        }
Exemple #29
0
 private static Version chooseVersion(int numInputBits, ErrorCorrectionLevel ecLevel)
 {
    // In the following comments, we use numbers of Version 7-H.
    for (int versionNum = 1; versionNum <= 40; versionNum++)
    {
       Version version = Version.getVersionForNumber(versionNum);
       // numBytes = 196
       int numBytes = version.TotalCodewords;
       // getNumECBytes = 130
       Version.ECBlocks ecBlocks = version.getECBlocksForLevel(ecLevel);
       int numEcBytes = ecBlocks.TotalECCodewords;
       // getNumDataBytes = 196 - 130 = 66
       int numDataBytes = numBytes - numEcBytes;
       int totalInputBytes = (numInputBits + 7) / 8;
       if (numDataBytes >= totalInputBytes)
       {
          return version;
       }
    }
    throw new WriterException("Data too big");
 }
        /// <summary>
        /// Creates a MinimalEncoder
        /// </summary>
        /// <param name="stringToEncode">The string to encode</param>
        /// <param name="priorityCharset">The preferred <see cref="System.Text.Encoding"/>. When the value of the argument is null, the algorithm
        /// *   chooses charsets that leads to a minimal representation.Otherwise the algorithm will use the priority
        /// *   charset to encode any character in the input that can be encoded by it if the charset is among the
        /// *   supported charsets.</param>
        /// <param name="isGS1"> {@code true} if a FNC1 is to be prepended; {@code false} otherwise</param>
        /// <param name="ecLevel">The error correction level.</param>
        public MinimalEncoder(String stringToEncode, Encoding priorityCharset, bool isGS1, ErrorCorrectionLevel ecLevel)
        {
            this.stringToEncode = stringToEncode;
            this.isGS1          = isGS1;
            this.ecLevel        = ecLevel;

            var neededEncoders = new List <Encoding>();

            neededEncoders.Add(Clone(StringUtils.ISO88591_ENCODING));
            var needUnicodeEncoder = priorityCharset != null && priorityCharset.WebName.StartsWith("UTF", StringComparison.OrdinalIgnoreCase);

            for (int i = 0; i < stringToEncode.Length; i++)
            {
                bool canEnc = false;
                foreach (var encoder in neededEncoders)
                {
                    if (canEncode(encoder, stringToEncode[i]))
                    {
                        canEnc = true;
                        break;
                    }
                }

                if (!canEnc)
                {
                    foreach (var encoder in ENCODERS)
                    {
                        if (canEncode(encoder, stringToEncode[i]))
                        {
                            neededEncoders.Add(encoder);
                            canEnc = true;
                            break;
                        }
                    }
                }

                if (!canEnc)
                {
                    needUnicodeEncoder = true;
                }
            }

            if (neededEncoders.Count == 1 && !needUnicodeEncoder)
            {
                encoders = new Encoding[] { neededEncoders[0] };
            }
            else
            {
                encoders = new Encoding[neededEncoders.Count + 2];
                int index = 0;
                foreach (var encoder in neededEncoders)
                {
                    encoders[index++] = encoder;
                }

                encoders[index]     = Clone(Encoding.UTF8);
                encoders[index + 1] = Clone(Encoding.BigEndianUnicode);
            }

            int priorityEncoderIndexValue = -1;

            if (priorityCharset != null)
            {
                for (int i = 0; i < encoders.Length; i++)
                {
                    if (encoders[i] != null && priorityCharset.WebName.Equals(encoders[i].WebName))
                    {
                        priorityEncoderIndexValue = i;
                        break;
                    }
                }
            }
            priorityEncoderIndex = priorityEncoderIndexValue;
        }
Exemple #31
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

         // 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)
            {
               var eciIsExplicitDisabled = (hints != null && hints.ContainsKey(EncodeHintType.DISABLE_ECI) ? (bool)hints[EncodeHintType.DISABLE_ECI] : false);
               if (!eciIsExplicitDisabled)
               {
                  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;
      }
 /// <summary>
 /// Encodes the string minimally
 /// </summary>
 /// <param name="stringToEncode">The string to encode</param>
 /// <param name="version">The preferred <see cref="Version"/>. A minimal version is computed(see
 ///  {@link ResultList#getVersion method} when the value of the argument is null</param>
 /// <param name="priorityCharset">The preferred { @link Charset}. When the value of the argument is null, the algorithm
 ///  chooses charsets that leads to a minimal representation.Otherwise the algorithm will use the priority
 /// charset to encode any character in the input that can be encoded by it if the charset is among the
 /// supported charsets.</param>
 /// <param name="isGS1">{ @code true} if a FNC1 is to be prepended;{ @code false}otherwise</param>
 /// <param name="ecLevel">The error correction level.</param>
 /// <returns>An instance of { @code ResultList}
 ///        representing the minimal solution.
 /// @see ResultList#getBits
 /// @see ResultList#getVersion
 /// @see ResultList#getSize</returns>
 public static ResultList encode(String stringToEncode, Version version, Encoding priorityCharset, bool isGS1, ErrorCorrectionLevel ecLevel)
 {
     return(new MinimalEncoder(stringToEncode, priorityCharset, isGS1, ecLevel).encode(version));
 }