diff --git a/QRCoder/QRCodeGenerator.cs b/QRCoder/QRCodeGenerator.cs
index 7f52921a..b12f7221 100644
--- a/QRCoder/QRCodeGenerator.cs
+++ b/QRCoder/QRCodeGenerator.cs
@@ -226,109 +226,147 @@ private static ECCLevel ValidateECCLevel(ECCLevel eccLevel)
/// A QRCodeData structure containing the full QR code matrix, which can be used for rendering or analysis.
private static QRCodeData GenerateQrCode(BitArray bitArray, ECCLevel eccLevel, int version)
{
- //Fill up data code word
var eccInfo = capacityECCTable.Single(x => x.Version == version && x.ErrorCorrectionLevel == eccLevel);
- var dataLength = eccInfo.TotalDataCodewords * 8;
- var lengthDiff = dataLength - bitArray.Length;
- if (lengthDiff > 0)
+
+ // Fill up data code word
+ PadData();
+
+ // Calculate error correction blocks
+ var codeWordWithECC = CalculateECCBlocks();
+
+ // Calculate interleaved code word lengths
+ var interleavedLength = CalculateInterleavedLength();
+
+ // Interleave code words
+ var interleavedData = InterleaveData();
+
+ // Place interleaved data on module matrix
+ var qrData = PlaceModules();
+
+ return qrData;
+
+
+ // fills the bit array with a repeating pattern to reach the required length
+ void PadData()
{
- // set 'write index' to end of existing bit array
- var index = bitArray.Length;
- // extend bit array to required length
- bitArray.Length = dataLength;
- // pad with 4 zeros (or less if lengthDiff < 4)
- index += Math.Min(lengthDiff, 4);
- // pad to nearest 8 bit boundary
- if ((uint)index % 8 != 0)
- index += 8 - (int)((uint)index % 8);
- // pad with repeating pattern
- var repeatingPatternIndex = 0;
- while (index < dataLength)
+ var dataLength = eccInfo.TotalDataCodewords * 8;
+ var lengthDiff = dataLength - bitArray.Length;
+ if (lengthDiff > 0)
{
- bitArray[index++] = _repeatingPattern[repeatingPatternIndex++];
- if (repeatingPatternIndex >= _repeatingPattern.Length)
- repeatingPatternIndex = 0;
+ // set 'write index' to end of existing bit array
+ var index = bitArray.Length;
+ // extend bit array to required length
+ bitArray.Length = dataLength;
+ // pad with 4 zeros (or less if lengthDiff < 4)
+ index += Math.Min(lengthDiff, 4);
+ // pad to nearest 8 bit boundary
+ if ((uint)index % 8 != 0)
+ index += 8 - (int)((uint)index % 8);
+ // pad with repeating pattern
+ var repeatingPatternIndex = 0;
+ while (index < dataLength)
+ {
+ bitArray[index++] = _repeatingPattern[repeatingPatternIndex++];
+ if (repeatingPatternIndex >= _repeatingPattern.Length)
+ repeatingPatternIndex = 0;
+ }
}
}
- // Generate the generator polynomial using the number of ECC words.
- List codeWordWithECC;
- using (var generatorPolynom = CalculateGeneratorPolynom(eccInfo.ECCPerBlock))
+ List CalculateECCBlocks()
{
- //Calculate error correction words
- codeWordWithECC = new List(eccInfo.BlocksInGroup1 + eccInfo.BlocksInGroup2);
- AddCodeWordBlocks(1, eccInfo.BlocksInGroup1, eccInfo.CodewordsInGroup1, 0, bitArray.Length, generatorPolynom);
- int offset = eccInfo.BlocksInGroup1 * eccInfo.CodewordsInGroup1 * 8;
- AddCodeWordBlocks(2, eccInfo.BlocksInGroup2, eccInfo.CodewordsInGroup2, offset, bitArray.Length - offset, generatorPolynom);
- }
+ List codewordBlocks;
+ // Generate the generator polynomial using the number of ECC words.
+ using (var generatorPolynom = CalculateGeneratorPolynom(eccInfo.ECCPerBlock))
+ {
+ //Calculate error correction words
+ codewordBlocks = new List(eccInfo.BlocksInGroup1 + eccInfo.BlocksInGroup2);
+ AddCodeWordBlocks(1, eccInfo.BlocksInGroup1, eccInfo.CodewordsInGroup1, 0, bitArray.Length, generatorPolynom);
+ int offset = eccInfo.BlocksInGroup1 * eccInfo.CodewordsInGroup1 * 8;
+ AddCodeWordBlocks(2, eccInfo.BlocksInGroup2, eccInfo.CodewordsInGroup2, offset, bitArray.Length - offset, generatorPolynom);
+ return codewordBlocks;
+ }
- //Calculate interleaved code word lengths
- int interleavedLength = 0;
- for (var i = 0; i < Math.Max(eccInfo.CodewordsInGroup1, eccInfo.CodewordsInGroup2); i++)
- {
- foreach (var codeBlock in codeWordWithECC)
- if ((uint)codeBlock.CodeWordsLength / 8 > i)
- interleavedLength += 8;
- }
- for (var i = 0; i < eccInfo.ECCPerBlock; i++)
- {
- foreach (var codeBlock in codeWordWithECC)
- if (codeBlock.ECCWords.Length > i)
- interleavedLength += 8;
+ void AddCodeWordBlocks(int blockNum, int blocksInGroup, int codewordsInGroup, int offset2, int count, Polynom generatorPolynom)
+ {
+ var groupLength = codewordsInGroup * 8;
+ for (var i = 0; i < blocksInGroup; i++)
+ {
+ var eccWordList = CalculateECCWords(bitArray, offset2, groupLength, eccInfo, generatorPolynom);
+ codewordBlocks.Add(new CodewordBlock(offset2, groupLength, eccWordList));
+ offset2 += groupLength;
+ }
+ }
}
- interleavedLength += remainderBits[version - 1];
- //Interleave code words
- var interleavedData = new BitArray(interleavedLength);
- int pos = 0;
- for (var i = 0; i < Math.Max(eccInfo.CodewordsInGroup1, eccInfo.CodewordsInGroup2); i++)
+ // Calculate the length of the interleaved data
+ int CalculateInterleavedLength()
{
- foreach (var codeBlock in codeWordWithECC)
+ var length = 0;
+ for (var i = 0; i < Math.Max(eccInfo.CodewordsInGroup1, eccInfo.CodewordsInGroup2); i++)
{
- if ((uint)codeBlock.CodeWordsLength / 8 > i)
- pos = bitArray.CopyTo(interleavedData, (int)((uint)i * 8) + codeBlock.CodeWordsOffset, pos, 8);
+ foreach (var codeBlock in codeWordWithECC)
+ if ((uint)codeBlock.CodeWordsLength / 8 > i)
+ length += 8;
}
- }
- for (var i = 0; i < eccInfo.ECCPerBlock; i++)
- {
- foreach (var codeBlock in codeWordWithECC)
- if (codeBlock.ECCWords.Length > i)
- pos = DecToBin(codeBlock.ECCWords[i], 8, interleavedData, pos);
+ for (var i = 0; i < eccInfo.ECCPerBlock; i++)
+ {
+ foreach (var codeBlock in codeWordWithECC)
+ if (codeBlock.ECCWords.Length > i)
+ length += 8;
+ }
+ length += remainderBits[version - 1];
+ return length;
}
- //Place interleaved data on module matrix
- var qr = new QRCodeData(version);
- var blockedModules = new List(17);
- ModulePlacer.PlaceFinderPatterns(qr, blockedModules);
- ModulePlacer.ReserveSeperatorAreas(qr.ModuleMatrix.Count, blockedModules);
- ModulePlacer.PlaceAlignmentPatterns(qr, alignmentPatternTable[version].PatternPositions, blockedModules);
- ModulePlacer.PlaceTimingPatterns(qr, blockedModules);
- ModulePlacer.PlaceDarkModule(qr, version, blockedModules);
- ModulePlacer.ReserveVersionAreas(qr.ModuleMatrix.Count, version, blockedModules);
- ModulePlacer.PlaceDataWords(qr, interleavedData, blockedModules);
- var maskVersion = ModulePlacer.MaskCode(qr, version, blockedModules, eccLevel);
- var formatStr = GetFormatString(eccLevel, maskVersion);
-
- ModulePlacer.PlaceFormat(qr, formatStr);
- if (version >= 7)
+ // Interleave the data
+ BitArray InterleaveData()
{
- var versionString = GetVersionString(version);
- ModulePlacer.PlaceVersion(qr, versionString);
- }
-
+ var data = new BitArray(interleavedLength);
+ int pos = 0;
+ for (var i = 0; i < Math.Max(eccInfo.CodewordsInGroup1, eccInfo.CodewordsInGroup2); i++)
+ {
+ foreach (var codeBlock in codeWordWithECC)
+ {
+ if ((uint)codeBlock.CodeWordsLength / 8 > i)
+ pos = bitArray.CopyTo(data, (int)((uint)i * 8) + codeBlock.CodeWordsOffset, pos, 8);
+ }
+ }
+ for (var i = 0; i < eccInfo.ECCPerBlock; i++)
+ {
+ foreach (var codeBlock in codeWordWithECC)
+ if (codeBlock.ECCWords.Length > i)
+ pos = DecToBin(codeBlock.ECCWords[i], 8, data, pos);
+ }
- ModulePlacer.AddQuietZone(qr);
- return qr;
+ return data;
+ }
- void AddCodeWordBlocks(int blockNum, int blocksInGroup, int codewordsInGroup, int offset2, int count, Polynom generatorPolynom)
+ // Place the modules on the QR code matrix
+ QRCodeData PlaceModules()
{
- var groupLength = codewordsInGroup * 8;
- for (var i = 0; i < blocksInGroup; i++)
+ var qr = new QRCodeData(version);
+ var blockedModules = new List(17);
+ ModulePlacer.PlaceFinderPatterns(qr, blockedModules);
+ ModulePlacer.ReserveSeperatorAreas(qr.ModuleMatrix.Count, blockedModules);
+ ModulePlacer.PlaceAlignmentPatterns(qr, alignmentPatternTable[version].PatternPositions, blockedModules);
+ ModulePlacer.PlaceTimingPatterns(qr, blockedModules);
+ ModulePlacer.PlaceDarkModule(qr, version, blockedModules);
+ ModulePlacer.ReserveVersionAreas(qr.ModuleMatrix.Count, version, blockedModules);
+ ModulePlacer.PlaceDataWords(qr, interleavedData, blockedModules);
+ var maskVersion = ModulePlacer.MaskCode(qr, version, blockedModules, eccLevel);
+ var formatStr = GetFormatString(eccLevel, maskVersion);
+
+ ModulePlacer.PlaceFormat(qr, formatStr);
+ if (version >= 7)
{
- var eccWordList = CalculateECCWords(bitArray, offset2, groupLength, eccInfo, generatorPolynom);
- codeWordWithECC.Add(new CodewordBlock(offset2, groupLength, eccWordList));
- offset2 += groupLength;
+ var versionString = GetVersionString(version);
+ ModulePlacer.PlaceVersion(qr, versionString);
}
+
+ ModulePlacer.AddQuietZone(qr);
+
+ return qr;
}
}