/// <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 ≤ minVersion ≤ maxVersion ≤ 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); } } }