예제 #1
0
        /// <summary>
        /// Creates a list of zero or more segments to represent the specified text string.
        /// The resulting list optimally minimizes the total encoded bit length, subjected to the constraints
        /// of the specified error correction level, minimum and maximum version number.
        /// <para>
        /// This function potentially uses all four text encoding modes: numeric, alphanumeric, byte (UTF-8),
        /// and Kanji. It is a more sophisticated but slower replacement for <see cref="MakeSegments"/>.
        /// </para>
        /// <para>
        /// The text to be encoded can contain the full set of Unicode characters (code points).
        /// </para>
        /// </summary>
        /// <param name="text">The text to be encoded.</param>
        /// <param name="ecl">The error correction level to use.</param>
        /// <param name="minVersion">The minimum version (size) of the QR code (between 1 and 40).</param>
        /// <param name="maxVersion">The maximum version (size) of the QR code (between 1 and 40).</param>
        /// <returns>The created mutable list of segments encoding the specified text with a minimal bit length.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="text"/> or <paramref name="ecl"/> is <c>null</c>.</exception>
        /// <exception cref="ArgumentOutOfRangeException">1 &#x2264; minVersion &#x2264; maxVersion &#x2264; 40 is violated.</exception>
        /// <exception cref="DataTooLongException">The text is too long to fit into the QR code with the given encoding parameters.</exception>
        public static List <QrSegment> MakeSegmentsOptimally(string text, QrCode.Ecc ecl, int minVersion = QrCode.MinVersion, int maxVersion = QrCode.MaxVersion)
        {
            // Check arguments
            Objects.RequireNonNull(text);
            Objects.RequireNonNull(ecl);
            if (minVersion < QrCode.MinVersion || minVersion > maxVersion)
            {
                throw new ArgumentOutOfRangeException(nameof(minVersion), "Invalid value");
            }

            if (maxVersion > QrCode.MaxVersion)
            {
                throw new ArgumentOutOfRangeException(nameof(maxVersion), "Invalid value");
            }

            // Iterate through version numbers, and make tentative segments
            List <QrSegment> segs = null;
            var codePoints        = ToCodePoints(text);

            for (int version = minVersion;; version++)
            {
                if (version == minVersion || version == 10 || version == 27)
                {
                    segs = MakeSegmentsOptimally(codePoints, version);
                }
                Debug.Assert(segs != null);

                // Check if the segments fit
                int dataCapacityBits = QrCode.GetNumDataCodewords(version, ecl) * 8;
                int dataUsedBits     = GetTotalBits(segs, version);
                if (dataUsedBits != -1 && dataUsedBits <= dataCapacityBits)
                {
                    return(segs); // This version number is found to be suitable
                }
                if (version < maxVersion)
                {
                    continue;
                }

                // All versions in the range could not fit the given text
                var msg = "Segment too long";
                if (dataUsedBits != -1)
                {
                    msg = $"Data length = {dataUsedBits} bits, Max capacity = {dataCapacityBits} bits";
                }
                throw new DataTooLongException(msg);
            }
        }
        public static List <QrSegment> MakeSegmentsOptimally(string text, Ecc ecl, int minVersion, int maxVersion)
        {
            Utils.CheckNull(text, nameof(text));

            if (!(QrCode.MIN_VERSION <= minVersion && minVersion <= maxVersion && maxVersion <= QrCode.MAX_VERSION))
            {
                throw new ArgumentException("Invalid value");
            }

            List <QrSegment> segs = null;
            var codePoints        = ToCodePoints(text);

            for (int version = minVersion; ; version++)
            {
                if (version == minVersion || version == 10 || version == 27)
                {
                    segs = MakeSegmentsOptimally(codePoints, version);
                }

                var dataCapacityBits = QrCode.GetNumDataCodewords(version, ecl) * 8;
                var dataUsedBits     = QrSegment.GetTotalBits(segs, version);
                if (dataUsedBits != -1 && dataUsedBits <= dataCapacityBits)
                {
                    return(segs);
                }
                if (version >= maxVersion)
                {
                    var msg = "Segment too long";
                    if (dataUsedBits != -1)
                    {
                        msg = String.Format("Data length = {0} bits, Max capacity = {1} bits", dataUsedBits, dataCapacityBits);
                    }
                    throw new DataTooLongException(msg);
                }
            }
        }