예제 #1
0
        static MinimalEncoder()
        {
            var names = new[]
            {
                "ISO-8859-2",
                "ISO-8859-3",
                "ISO-8859-4",
                "ISO-8859-5",
                "ISO-8859-6",
                "ISO-8859-7",
                "ISO-8859-8",
                "ISO-8859-9",
                "ISO-8859-10",
                "ISO-8859-11",
                "ISO-8859-13",
                "ISO-8859-14",
                "ISO-8859-15",
                "ISO-8859-16",
                "windows-1250",
                "windows-1251",
                "windows-1252",
                "windows-1253",
                "windows-1254",
                "windows-1255",
                "windows-1256",
                "windows-1257",
                "windows-1258",
                "Shift_JIS"
            };

            foreach (String name in names)
            {
                if (CharacterSetECI.getCharacterSetECIByName(name) != null)
                {
                    try
                    {
                        ENCODERS.Add(Clone(Encoding.GetEncoding(name)));
                    }
                    catch (Exception)
                    {
                        // continue
                    }
                }
            }
        }
예제 #2
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);
        }
        /// <summary>
        /// Performs high-level encoding of a PDF417 message using the algorithm described in annex P
        /// of ISO/IEC 15438:2001(E). If byte compaction has been selected, then only byte compaction
        /// is used.
        /// </summary>
        /// <param name="msg">the message</param>
        /// <param name="compaction">compaction mode to use</param>
        /// <param name="encoding">character encoding used to encode in default or byte compaction
        /// or null for default / not applicable</param>
        /// <param name="disableEci">if true, don't add an ECI segment for different encodings than default</param>
        /// <returns>the encoded message (the char values range from 0 to 928)</returns>
        internal static String encodeHighLevel(String msg, Compaction compaction, Encoding encoding, bool disableEci)
        {
            //the codewords 0..928 are encoded as Unicode characters
            var sb = new StringBuilder(msg.Length);

            if (encoding != null && !disableEci && String.Compare(DEFAULT_ENCODING_NAME, encoding.WebName, StringComparison.Ordinal) != 0)
            {
                CharacterSetECI eci = CharacterSetECI.getCharacterSetECIByName(encoding.WebName);
                if (eci != null)
                {
                    encodingECI(eci.Value, sb);
                }
            }

            int len         = msg.Length;
            int p           = 0;
            int textSubMode = SUBMODE_ALPHA;

            // User selected encoding mode
            switch (compaction)
            {
            case Compaction.TEXT:
                encodeText(msg, p, len, sb, textSubMode);
                break;

            case Compaction.BYTE:
                var msgBytes = toBytes(msg, encoding);
                encodeBinary(msgBytes, p, msgBytes.Length, BYTE_COMPACTION, sb);
                break;

            case Compaction.NUMERIC:
                sb.Append((char)LATCH_TO_NUMERIC);
                encodeNumeric(msg, p, len, sb);
                break;

            default:
                int    encodingMode = TEXT_COMPACTION; //Default mode, see 4.4.2.1
                byte[] bytes        = null;
                while (p < len)
                {
                    int n = determineConsecutiveDigitCount(msg, p);
                    if (n >= 13)
                    {
                        sb.Append((char)LATCH_TO_NUMERIC);
                        encodingMode = NUMERIC_COMPACTION;
                        textSubMode  = SUBMODE_ALPHA; //Reset after latch
                        encodeNumeric(msg, p, n, sb);
                        p += n;
                    }
                    else
                    {
                        int t = determineConsecutiveTextCount(msg, p);
                        if (t >= 5 || n == len)
                        {
                            if (encodingMode != TEXT_COMPACTION)
                            {
                                sb.Append((char)LATCH_TO_TEXT);
                                encodingMode = TEXT_COMPACTION;
                                textSubMode  = SUBMODE_ALPHA; //start with submode alpha after latch
                            }
                            textSubMode = encodeText(msg, p, t, sb, textSubMode);
                            p          += t;
                        }
                        else
                        {
                            if (bytes == null)
                            {
                                bytes = toBytes(msg, encoding);
                            }
                            int b = determineConsecutiveBinaryCount(msg, bytes, p, encoding);
                            if (b == 0)
                            {
                                b = 1;
                            }
                            if (b == 1 && encodingMode == TEXT_COMPACTION)
                            {
                                //Switch for one byte (instead of latch)
                                encodeBinary(bytes, 0, 1, TEXT_COMPACTION, sb);
                            }
                            else
                            {
                                //Mode latch performed by encodeBinary()
                                encodeBinary(bytes,
                                             toBytes(msg.Substring(0, p), encoding).Length,
                                             toBytes(msg.Substring(p, b), encoding).Length,
                                             encodingMode,
                                             sb);
                                encodingMode = BYTE_COMPACTION;
                                textSubMode  = SUBMODE_ALPHA; //Reset after latch
                            }
                            p += b;
                        }
                    }
                }
                break;
            }

            return(sb.ToString());
        }
예제 #4
0
        /// <summary>
        /// Performs high-level encoding of a PDF417 message using the algorithm described in annex P
        /// of ISO/IEC 15438:2001(E). If byte compaction has been selected, then only byte compaction
        /// is used.
        ///
        /// <param name="msg">the message</param>
        /// <returns>the encoded message (the char values range from 0 to 928)</returns>
        /// </summary>
        internal static String encodeHighLevel(String msg, Compaction compaction, Encoding encoding, bool disableEci)
        {
            //the codewords 0..928 are encoded as Unicode characters
            var sb = new StringBuilder(msg.Length);

            if (!DEFAULT_ENCODING.Equals(encoding) && !disableEci)
            {
                CharacterSetECI eci = CharacterSetECI.getCharacterSetECIByName(encoding.WebName);
                if (eci != null)
                {
                    encodingECI(eci.Value, sb);
                }
            }

            int len         = msg.Length;
            int p           = 0;
            int textSubMode = SUBMODE_ALPHA;

            // User selected encoding mode
            byte[] bytes = null; //Fill later and only if needed
            if (compaction == Compaction.TEXT)
            {
                encodeText(msg, p, len, sb, textSubMode);
            }
            else if (compaction == Compaction.BYTE)
            {
                bytes = encoding.GetBytes(msg);
                encodeBinary(bytes, p, bytes.Length, BYTE_COMPACTION, sb);
            }
            else if (compaction == Compaction.NUMERIC)
            {
                sb.Append((char)LATCH_TO_NUMERIC);
                encodeNumeric(msg, p, len, sb);
            }
            else
            {
                int encodingMode = TEXT_COMPACTION; //Default mode, see 4.4.2.1
                while (p < len)
                {
                    int n = determineConsecutiveDigitCount(msg, p);
                    if (n >= 13)
                    {
                        sb.Append((char)LATCH_TO_NUMERIC);
                        encodingMode = NUMERIC_COMPACTION;
                        textSubMode  = SUBMODE_ALPHA; //Reset after latch
                        encodeNumeric(msg, p, n, sb);
                        p += n;
                    }
                    else
                    {
                        int t = determineConsecutiveTextCount(msg, p);
                        if (t >= 5 || n == len)
                        {
                            if (encodingMode != TEXT_COMPACTION)
                            {
                                sb.Append((char)LATCH_TO_TEXT);
                                encodingMode = TEXT_COMPACTION;
                                textSubMode  = SUBMODE_ALPHA; //start with submode alpha after latch
                            }
                            textSubMode = encodeText(msg, p, t, sb, textSubMode);
                            p          += t;
                        }
                        else
                        {
                            if (bytes == null)
                            {
                                bytes = encoding.GetBytes(msg);
                            }
                            int b = determineConsecutiveBinaryCount(msg, bytes, p);
                            if (b == 0)
                            {
                                b = 1;
                            }
                            if (b == 1 && encodingMode == TEXT_COMPACTION)
                            {
                                //Switch for one byte (instead of latch)
                                encodeBinary(bytes, p, 1, TEXT_COMPACTION, sb);
                            }
                            else
                            {
                                //Mode latch performed by encodeBinary()
                                encodeBinary(bytes, p, b, encodingMode, sb);
                                encodingMode = BYTE_COMPACTION;
                                textSubMode  = SUBMODE_ALPHA; //Reset after latch
                            }
                            p += b;
                        }
                    }
                }
            }

            return(sb.ToString());
        }
예제 #5
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);
        }
예제 #6
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);
        }