/// <summary> /// Creates a segment representing the specified text string. /// The segment is encoded in alphanumeric mode. /// <para> /// Allowed characters are: 0 to 9, A to Z (uppercase only), space, /// dollar, percent, asterisk, plus, hyphen, period, slash, colon. /// </para> /// </summary> /// <param name="text">The text to encode, consisting of allowed characters only.</param> /// <returns>The created segment containing the text.</returns> /// <exception cref="ArgumentNullException"><c>text</c> is <c>null</c>.</exception> /// <exception cref="ArgumentOutOfRangeException"><c>text</c> contains non-encodable characters.</exception> public static QrSegment MakeAlphanumeric(string text) { Objects.RequireNonNull(text); if (!AlphanumericRegex.IsMatch(text)) { throw new ArgumentOutOfRangeException(nameof(text), "String contains unencodable characters in alphanumeric mode"); } BitArray ba = new BitArray(0); int i; for (i = 0; i <= text.Length - 2; i += 2) { // Process groups of 2 uint temp = (uint)AlphanumericCharset.IndexOf(text[i]) * 45; temp += (uint)AlphanumericCharset.IndexOf(text[i + 1]); BitArrayExtensions.AppendBits(ba, temp, 11); } if (i < text.Length) // 1 character remaining { BitArrayExtensions.AppendBits(ba, (uint)AlphanumericCharset.IndexOf(text[i]), 6); } return(new QrSegment(Mode.Alphanumeric, text.Length, ba)); }
/// <summary> /// Creates a segment representing an Extended Channel Interpretation /// (ECI) designator with the specified assignment value. /// </summary> /// <param name="assignVal">The ECI assignment number (see the AIM ECI specification).</param> /// <returns>The created segment containing the data.</returns> /// <exception cref="ArgumentOutOfRangeException"><c>assignVal</c>is outside the range [0, 10<sup>6</sup>).</exception> public static QrSegment MakeEci(int assignVal) { BitArray ba = new BitArray(0); if (assignVal < 0) { throw new ArgumentOutOfRangeException(nameof(assignVal), "ECI assignment value out of range"); } if (assignVal < 1 << 7) { BitArrayExtensions.AppendBits(ba, (uint)assignVal, 8); } else if (assignVal < 1 << 14) { BitArrayExtensions.AppendBits(ba, 2, 2); BitArrayExtensions.AppendBits(ba, (uint)assignVal, 14); } else if (assignVal < 1000000) { BitArrayExtensions.AppendBits(ba, 6, 3); BitArrayExtensions.AppendBits(ba, (uint)assignVal, 21); } else { throw new ArgumentOutOfRangeException(nameof(assignVal), "ECI assignment value out of range"); } return(new QrSegment(Mode.Eci, 0, ba)); }
/// <summary> /// Creates a segment representing the specified binary data /// encoded in byte mode. All input byte arrays are acceptable. /// <para> /// Any text string can be converted to UTF-8 bytes (using <c>Encoding.UTF8.GetBytes(str)</c>) /// and encoded as a byte mode segment. /// </para> /// </summary> /// <param name="data">The binary data to encode.</param> /// <returns>The created segment containing the specified data.</returns> /// <exception cref="ArgumentNullException"><c>data</c> is <c>null</c>.</exception> public static QrSegment MakeBytes(byte[] data) { Objects.RequireNonNull(data); BitArray ba = new BitArray(0); foreach (byte b in data) { BitArrayExtensions.AppendBits(ba, b, 8); } return(new QrSegment(Mode.Byte, data.Length, ba)); }
/// <summary> /// Creates a segment encoding the specified text in Kanji mode. /// <para> /// Broadly speaking, the set of encodable characters are Kanji used in Japan, /// Hiragana, Katakana, East Asian punctuation, full-width ASCII, Greek, and Cyrillic. /// Examples of non-encodable characters include ordinary ASCII, half-width Katakana, /// more extensive Chinese Hanzi. /// </para> /// </summary> /// <param name="text">The text to encoding, containing only characters allowed by the Kanji encoding.</param> /// <returns>The created segment respresenting the specified text.</returns> /// <exception cref="ArgumentNullException"><paramref name="text"/> is <c>null</c>.</exception> /// <exception cref="ArgumentOutOfRangeException"><paramref name="text"/> contains non-encodable characters.</exception> /// <seealso cref="IsEncodableAsKanji"/> public static QrSegment MakeKanji(string text) { Objects.RequireNonNull(text); BitArray ba = new BitArray(0); foreach (char t in text) { ushort val = UnicodeToQrKanji[t]; if (val == 0xffff) { throw new ArgumentOutOfRangeException(text.GetType().Name, "String contains non-kanji-mode characters"); } BitArrayExtensions.AppendBits(ba, val, 13); } return(new QrSegment(QrSegment.Mode.Kanji, text.Length, ba)); }
/// <summary> /// Creates a segment representing the specified string of decimal digits. /// The segment is encoded in numeric mode. /// </summary> /// <param name="digits">The text to encode, consisting of digits from 0 to 9 only.</param> /// <returns>The created segment containing the text.</returns> /// <exception cref="ArgumentNullException"><c>digits</c> is <c>null</c>.</exception> /// <exception cref="ArgumentOutOfRangeException"><c>digits</c> contains non-digit characters</exception> public static QrSegment MakeNumeric(string digits) { Objects.RequireNonNull(digits); if (!NumericRegex.IsMatch(digits)) { throw new ArgumentOutOfRangeException(nameof(digits), "String contains non-numeric characters"); } BitArray ba = new BitArray(0); for (int i = 0; i < digits.Length;) { // Consume up to 3 digits per iteration int n = Math.Min(digits.Length - i, 3); BitArrayExtensions.AppendBits(ba, uint.Parse(digits.Substring(i, n)), n * 3 + 1); i += n; } return(new QrSegment(Mode.Numeric, digits.Length, ba)); }