Beispiel #1
0
        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));
        }
Beispiel #2
0
        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));
        }