private int GetVersion(int length, EncodingMode encMode, EccLevel eccLevel) { var version = capacityTable .Where(x => x.Details.Any(y => (y.ErrorCorrectionLevel == eccLevel && y.CapacityDict[encMode] >= Convert.ToInt32(length)))) .Select(x => new { version = x.Version, capacity = x.Details.Single(y => y.ErrorCorrectionLevel == eccLevel).CapacityDict[encMode] }).Min(x => x.version); return version; }
public QrCode CreateQrCode(string plainText, EccLevel eccLevel, bool utf8Bom = false) { var encoding = GetEncodingFromPlaintext(plainText); var codedText = PlainTextToBinary(plainText, encoding, utf8Bom); var dataInputLength = GetDataLength(encoding, plainText, codedText); var version = GetVersion(dataInputLength, encoding, eccLevel); var modeIndicator = DecToBin((int)encoding, 4); var countIndicator = DecToBin(dataInputLength, GetCountIndicatorLength(version, encoding)); var bitString = modeIndicator + countIndicator; bitString += codedText; //Fill up data code word var eccInfo = capacityEccTable.Single(x => x.Version == version && x.ErrorCorrectionLevel.Equals(eccLevel)); var dataLength = eccInfo.TotalDataCodewords * 8; var lengthDiff = dataLength - bitString.Length; if (lengthDiff > 0) bitString += new string('0', Math.Min(lengthDiff, 4)); if ((bitString.Length % 8) != 0) bitString += new string('0', 8 - (bitString.Length % 8)); while (bitString.Length < dataLength) bitString += "1110110000010001"; if (bitString.Length > dataLength) bitString = bitString.Substring(0, dataLength); //Calculate error correction words var codeWordWithEcc = new List<CodewordBlock>(); for (var i = 0; i < eccInfo.BlocksInGroup1; i++) { var bitStr = bitString.Substring(i * eccInfo.CodewordsInGroup1 * 8, eccInfo.CodewordsInGroup1 * 8); codeWordWithEcc.Add(new CodewordBlock() { BitString = bitStr, BlockNumber = i + 1, GroupNumber = 1, CodeWords = BinaryStringToBitBlockList(bitStr), ECCWords = CalculateEccWords(bitStr, eccInfo) }); } bitString = bitString.Substring(eccInfo.BlocksInGroup1 * eccInfo.CodewordsInGroup1 * 8); for (var i = 0; i < eccInfo.BlocksInGroup2; i++) { var bitStr = bitString.Substring(i * eccInfo.CodewordsInGroup2 * 8, eccInfo.CodewordsInGroup2 * 8); codeWordWithEcc.Add(new CodewordBlock() { BitString = bitStr, BlockNumber = i + 1, GroupNumber = 2, CodeWords = BinaryStringToBitBlockList(bitStr), ECCWords = CalculateEccWords(bitStr, eccInfo) }); } //Interleave code words var interleavedWordsSb = new StringBuilder(); for (var i = 0; i < Math.Max(eccInfo.CodewordsInGroup1, eccInfo.CodewordsInGroup2); i++) { var i1 = i; foreach (var codeBlock in codeWordWithEcc.Where(codeBlock => codeBlock.CodeWords.Count > i1)) interleavedWordsSb.Append(codeBlock.CodeWords[i]); } for (var i = 0; i < eccInfo.ECCPerBlock; i++) { var i1 = i; foreach (var codeBlock in codeWordWithEcc.Where(codeBlock => codeBlock.ECCWords.Count > i1)) interleavedWordsSb.Append(codeBlock.ECCWords[i]); } interleavedWordsSb.Append(new string('0', remainderBits[version - 1])); var interleavedData = interleavedWordsSb.ToString(); //Place interleaved data on module matrix var qr = new QrCode(version); var blockedModules = new List<Rectangle>(); ModulePlacer.PlaceFinderPatterns(ref qr, ref blockedModules); ModulePlacer.ReserveSeperatorAreas(qr.ModuleMatrix.Count, ref blockedModules); ModulePlacer.PlaceAlignmentPatterns(ref qr, alignmentPatternTable.Where(x => x.Version == version).Select(x => x.PatternPositions).First(), ref blockedModules); ModulePlacer.PlaceTimingPatterns(ref qr, ref blockedModules); ModulePlacer.PlaceDarkModule(ref qr, version, ref blockedModules); ModulePlacer.ReserveVersionAreas(qr.ModuleMatrix.Count, version, ref blockedModules); ModulePlacer.PlaceDataWords(ref qr, interleavedData, ref blockedModules); var maskVersion = ModulePlacer.MaskCode(ref qr, version, ref blockedModules); var formatStr = GetFormatString(eccLevel, maskVersion); ModulePlacer.PlaceFormat(ref qr, formatStr); if (version >= 7) { var versionString = GetVersionString(version); ModulePlacer.PlaceVersion(ref qr, versionString); } ModulePlacer.AddQuietZone(ref qr); return qr; }
private string GetFormatString(EccLevel level, int maskVersion) { var generator = "10100110111"; var fStrMask = "101010000010010"; var fStr = (level == EccLevel.L) ? "01" : (level == EccLevel.M) ? "00" : (level == EccLevel.Q) ? "11" : "10"; fStr += DecToBin(maskVersion, 3); var fStrEcc = fStr.PadRight(15, '0').TrimStart('0'); while (fStrEcc.Length > 10) { var sb = new StringBuilder(); generator = generator.PadRight(fStrEcc.Length, '0'); for (var i = 0; i < fStrEcc.Length; i++) sb.Append((Convert.ToInt32(fStrEcc[i]) ^ Convert.ToInt32(generator[i])).ToString()); fStrEcc = sb.ToString().TrimStart('0'); } fStrEcc = fStrEcc.PadLeft(10, '0'); fStr += fStrEcc; var sbMask = new StringBuilder(); for (var i = 0; i < fStr.Length; i++) sbMask.Append((Convert.ToInt32(fStr[i]) ^ Convert.ToInt32(fStrMask[i])).ToString()); return sbMask.ToString(); }