public static QRSegment CreateNumericSegment(string digits) { if (digits is null) { throw new ArgumentNullException(nameof(digits)); } var numbers = digits .Select(x => x >= '0' && x <= '9' ? x - '0' : throw new ArgumentException("String contains non-numeric characters", nameof(digits))) .Bucket(3) .Select(x => { int[] currentDigits = x.ToArray(); return(new { Count = currentDigits.Length, Number = x.Aggregate(0, (a, b) => a * 10 + b) }); }); BitList bits = new BitList(); foreach (var num in numbers) { bits.Add(num.Number, num.Count * 3 + 1); } return(new QRSegment(Mode.Numeric, digits.Length, bits)); }
public static QRCode EncodeSegments(IEnumerable <QRSegment> segments, CorrectionLevel correctionLevel, int minVersion, int maxVersion, Mask mask, bool boostECL) { if (segments is null) { throw new ArgumentNullException(nameof(segments)); } if (correctionLevel is null) { throw new ArgumentNullException(nameof(correctionLevel)); } if (!(MinVersion <= minVersion && minVersion <= maxVersion && maxVersion <= MaxVersion)) { throw new ArgumentOutOfRangeException(nameof(minVersion), nameof(maxVersion)); } List <QRSegment> segmentList = segments.ToList(); int version; int usedBits; for (version = minVersion; ; ++version) { int capacity = ComputeCodewordsCount(version, correctionLevel) * 8; usedBits = QRSegment.ComputeBitLength(segmentList, version); if (usedBits != -1 && usedBits <= capacity) { break; } if (version >= maxVersion) { throw new ArgumentOutOfRangeException(nameof(segments), "Data length was too long"); } } if (boostECL) { while (correctionLevel.Id != CorrectionLevel.MaxValue) { CorrectionLevel check = correctionLevel + 1; if (usedBits <= ComputeCodewordsCount(version, check) * 8) { correctionLevel = check; } else { break; } } } BitList bits = new BitList(); foreach (QRSegment segment in segmentList) { bits.Add(segment.Mode.ModeBits, 4); bits.Add(segment.CharsCount, segment.Mode.GetCharsCountBitsCount(version)); bits.Add(segment.Data); } Debug.Assert(bits.Length == usedBits); int dataCapacityBits = ComputeCodewordsCount(version, correctionLevel) * 8; Debug.Assert(bits.Length <= dataCapacityBits); bits.Add(0, Math.Min(4, dataCapacityBits - bits.Length)); bits.Add(0, (8 - bits.Length % 8) % 8); Debug.Assert(bits.Length % 8 == 0); for (int padByte = 0b11101100; bits.Length < dataCapacityBits; padByte ^= 0b11111101) { bits.Add(padByte, 8); } byte[] dataCodewords = new byte[bits.Length / 8]; for (int i = 0; i < bits.Length; ++i) { int index = i >> 3; dataCodewords[index] = (byte)(dataCodewords[index] | (bits[i] << (7 - (i & 7)))); } return(new QRCode(version, correctionLevel, dataCodewords, mask)); }
public void Add(BitList list) => Data.AddRange(list.Data);
public QRSegment(Mode mode, int charsCount, BitList data) { Mode = mode ?? throw new ArgumentNullException(nameof(mode)); CharsCount = charsCount >= 0 ? charsCount : throw new ArgumentOutOfRangeException(nameof(charsCount)); _data = (data ?? throw new ArgumentNullException(nameof(data))).Clone(); }