From c992946dda3062fd137b6c6c402d8141f8bcfc62 Mon Sep 17 00:00:00 2001 From: Shane32 Date: Mon, 6 May 2024 19:55:32 -0400 Subject: [PATCH 1/7] Use BitArray for codeword blocks --- QRCoder/Extensions/BitArrayExtensions.cs | 60 ++++++++++++++++++++++++ QRCoder/QRCodeGenerator.CodewordBlock.cs | 23 +++++++-- QRCoder/QRCodeGenerator.cs | 15 ++++-- 3 files changed, 90 insertions(+), 8 deletions(-) create mode 100644 QRCoder/Extensions/BitArrayExtensions.cs diff --git a/QRCoder/Extensions/BitArrayExtensions.cs b/QRCoder/Extensions/BitArrayExtensions.cs new file mode 100644 index 00000000..2387a540 --- /dev/null +++ b/QRCoder/Extensions/BitArrayExtensions.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections; +using System.Linq; +using System.Text; + +namespace QRCoder +{ + /// + /// Helper methods for . + /// + internal static class BitArrayExtensions + { + /// Copies a specified number of elements from one to another starting at the specified offsets. + /// + /// The source from which elements will be copied. + /// The zero-based index in the source at which copying begins. + /// The destination to which elements will be copied. + /// The zero-based index in the destination at which storing begins. + /// The number of elements to copy. + /// The index in the destination immediately following the last copied element. + public static int CopyTo(this BitArray source, int sourceOffset, BitArray destination, int destinationOffset, int count) + { + for (int i = 0; i < count; i++) + { + destination[destinationOffset + i] = source[sourceOffset + i]; + } + return destinationOffset + count; + } + + /// + /// Copies a specified number of elements from one to another starting at the specified offsets, + /// and reverses every set of 8 bits during the copy operation. + /// + /// The source from which elements will be copied. + /// The zero-based index in the source at which copying begins. + /// The destination to which elements will be copied. + /// The zero-based index in the destination at which storing begins. + /// The number of elements to copy. Must be a multiple of 8. + /// The index in the destination immediately following the last copied element. + public static int CopyToRev8(this BitArray source, int sourceOffset, BitArray destination, int destinationOffset, int count) + { + if (count % 8 != 0) + { + throw new ArgumentException("Count must be a multiple of 8.", nameof(count)); + } + + for (int i = 0; i < count; i += 8) + { + // Reverse the current set of 8 bits + for (int j = 0; j < 8; j++) + { + destination[destinationOffset + i + j] = source[sourceOffset + i + (7 - j)]; + } + } + + return destinationOffset + count; + } + + } +} diff --git a/QRCoder/QRCodeGenerator.CodewordBlock.cs b/QRCoder/QRCodeGenerator.CodewordBlock.cs index 460b742a..b1d28f15 100644 --- a/QRCoder/QRCodeGenerator.CodewordBlock.cs +++ b/QRCoder/QRCodeGenerator.CodewordBlock.cs @@ -1,4 +1,6 @@ -namespace QRCoder +using System.Collections; + +namespace QRCoder { public partial class QRCodeGenerator { @@ -13,16 +15,31 @@ private struct CodewordBlock /// /// The array of data codewords for this block. Data codewords carry the actual information. /// The array of error correction codewords for this block. These codewords help recover the data if the QR code is damaged. - public CodewordBlock(byte[] codeWords, byte[] eccWords) + public CodewordBlock(/* byte[] codeWordsArray, */ BitArray codeWords, int codeWordsOffset, int codeWordsLength, byte[] eccWords) { + //this.CodeWordsArray = codeWordsArray; this.CodeWords = codeWords; + this.CodeWordsOffset = codeWordsOffset; + this.CodeWordsLength = codeWordsLength; this.ECCWords = eccWords; } + //public byte[] CodeWordsArray { get; } + /// /// Gets the data codewords associated with this block. /// - public byte[] CodeWords { get; } + public BitArray CodeWords { get; } + + /// + /// Gets the offset of the data codewords in the BitArray. + /// + public int CodeWordsOffset { get; } + + /// + /// Gets the length of the data codewords in the BitArray. + /// + public int CodeWordsLength { get; } /// /// Gets the error correction codewords associated with this block. diff --git a/QRCoder/QRCodeGenerator.cs b/QRCoder/QRCodeGenerator.cs index 9716017d..cea6602b 100644 --- a/QRCoder/QRCodeGenerator.cs +++ b/QRCoder/QRCodeGenerator.cs @@ -234,7 +234,7 @@ private static QRCodeData GenerateQrCode(BitArray bitArray, ECCLevel eccLevel, i for (var i = 0; i < Math.Max(eccInfo.CodewordsInGroup1, eccInfo.CodewordsInGroup2); i++) { foreach (var codeBlock in codeWordWithECC) - if (codeBlock.CodeWords.Length > i) + if (codeBlock.CodeWordsLength / 8 > i) interleavedLength += 8; } for (var i = 0; i < eccInfo.ECCPerBlock; i++) @@ -251,8 +251,10 @@ private static QRCodeData GenerateQrCode(BitArray bitArray, ECCLevel eccLevel, i for (var i = 0; i < Math.Max(eccInfo.CodewordsInGroup1, eccInfo.CodewordsInGroup2); i++) { foreach (var codeBlock in codeWordWithECC) - if (codeBlock.CodeWords.Length > i) - pos = DecToBin(codeBlock.CodeWords[i], 8, interleavedData, pos); + { + if (codeBlock.CodeWordsLength / 8 > i) + pos = codeBlock.CodeWords.CopyTo(i * 8 + codeBlock.CodeWordsOffset, interleavedData, pos, 8); + } } for (var i = 0; i < eccInfo.ECCPerBlock; i++) { @@ -290,10 +292,13 @@ void AddCodeWordBlocks(int blockNum, int blocksInGroup, int codewordsInGroup, Bi var groupLength = codewordsInGroup * 8; for (var i = 0; i < blocksInGroup; i++) { - var bitBlockList = BinaryStringToBitBlockByteList(bitArray2, offset2, groupLength); + //var bitBlockList = BinaryStringToBitBlockByteList(bitArray2, offset2, groupLength); var eccWordList = CalculateECCWords(bitArray2, offset2, groupLength, eccInfo); codeWordWithECC.Add(new CodewordBlock( - bitBlockList, + //bitBlockList, + bitArray2, + offset2, + groupLength, eccWordList) ); offset2 += groupLength; From eb7a0ad102805af1715b27675b2e82800ae94fb6 Mon Sep 17 00:00:00 2001 From: Shane32 Date: Mon, 6 May 2024 23:21:55 -0400 Subject: [PATCH 2/7] Update --- QRCoder/QRCodeGenerator.CodewordBlock.cs | 14 ++------- QRCoder/QRCodeGenerator.cs | 37 ++---------------------- 2 files changed, 5 insertions(+), 46 deletions(-) diff --git a/QRCoder/QRCodeGenerator.CodewordBlock.cs b/QRCoder/QRCodeGenerator.CodewordBlock.cs index b1d28f15..2d53efe4 100644 --- a/QRCoder/QRCodeGenerator.CodewordBlock.cs +++ b/QRCoder/QRCodeGenerator.CodewordBlock.cs @@ -13,24 +13,16 @@ private struct CodewordBlock /// /// Initializes a new instance of the CodewordBlock struct with specified arrays of code words and error correction (ECC) words. /// - /// The array of data codewords for this block. Data codewords carry the actual information. + /// The offset of the data codewords within the main BitArray. Data codewords carry the actual information. + /// The length in bits of the data codewords within the main BitArray. /// The array of error correction codewords for this block. These codewords help recover the data if the QR code is damaged. - public CodewordBlock(/* byte[] codeWordsArray, */ BitArray codeWords, int codeWordsOffset, int codeWordsLength, byte[] eccWords) + public CodewordBlock(int codeWordsOffset, int codeWordsLength, byte[] eccWords) { - //this.CodeWordsArray = codeWordsArray; - this.CodeWords = codeWords; this.CodeWordsOffset = codeWordsOffset; this.CodeWordsLength = codeWordsLength; this.ECCWords = eccWords; } - //public byte[] CodeWordsArray { get; } - - /// - /// Gets the data codewords associated with this block. - /// - public BitArray CodeWords { get; } - /// /// Gets the offset of the data codewords in the BitArray. /// diff --git a/QRCoder/QRCodeGenerator.cs b/QRCoder/QRCodeGenerator.cs index cea6602b..409b640d 100644 --- a/QRCoder/QRCodeGenerator.cs +++ b/QRCoder/QRCodeGenerator.cs @@ -253,7 +253,7 @@ private static QRCodeData GenerateQrCode(BitArray bitArray, ECCLevel eccLevel, i foreach (var codeBlock in codeWordWithECC) { if (codeBlock.CodeWordsLength / 8 > i) - pos = codeBlock.CodeWords.CopyTo(i * 8 + codeBlock.CodeWordsOffset, interleavedData, pos, 8); + pos = bitArray.CopyTo(i * 8 + codeBlock.CodeWordsOffset, interleavedData, pos, 8); } } for (var i = 0; i < eccInfo.ECCPerBlock; i++) @@ -292,11 +292,9 @@ void AddCodeWordBlocks(int blockNum, int blocksInGroup, int codewordsInGroup, Bi var groupLength = codewordsInGroup * 8; for (var i = 0; i < blocksInGroup; i++) { - //var bitBlockList = BinaryStringToBitBlockByteList(bitArray2, offset2, groupLength); var eccWordList = CalculateECCWords(bitArray2, offset2, groupLength, eccInfo); codeWordWithECC.Add(new CodewordBlock( - //bitBlockList, - bitArray2, + //bitArray2, offset2, groupLength, eccWordList) @@ -624,37 +622,6 @@ private static Polynom CalculateGeneratorPolynom(int numEccWords) return generatorPolynom; // Return the completed generator polynomial } - /// - /// Converts a segment of a BitArray into a list of bytes where each byte represents a consecutive block of 8 bits from the BitArray. - /// - private static byte[] BinaryStringToBitBlockByteList(BitArray bitString, int offset, int count) - { - const int blockSize = 8; - if (count % blockSize != 0) - ThrowCountMustBeMultipleOf8Exception(); - var numberOfBlocks = (int)((uint)count / blockSize); - var blocklist = new byte[numberOfBlocks]; - - int j = 0; - count += offset; - for (int i = offset; i < count; i += blockSize) - { - blocklist[j++] = (byte)( - (bitString[i] ? 128 : 0) + - (bitString[i + 1] ? 64 : 0) + - (bitString[i + 2] ? 32 : 0) + - (bitString[i + 3] ? 16 : 0) + - (bitString[i + 4] ? 8 : 0) + - (bitString[i + 5] ? 4 : 0) + - (bitString[i + 6] ? 2 : 0) + - (bitString[i + 7] ? 1 : 0)); - } - - return blocklist; - - void ThrowCountMustBeMultipleOf8Exception() => throw new ArgumentOutOfRangeException(nameof(count), "Count must be a multiple of 8."); - } - /// /// Converts a segment of a BitArray into its decimal (integer) equivalent. /// From 8a177f010feba0d9bddd657486fb57bc61742ef9 Mon Sep 17 00:00:00 2001 From: Shane32 Date: Mon, 6 May 2024 23:25:34 -0400 Subject: [PATCH 3/7] Update --- QRCoder/Extensions/BitArrayExtensions.cs | 32 +----------------------- QRCoder/QRCodeGenerator.cs | 17 +++++-------- 2 files changed, 7 insertions(+), 42 deletions(-) diff --git a/QRCoder/Extensions/BitArrayExtensions.cs b/QRCoder/Extensions/BitArrayExtensions.cs index 2387a540..11f961eb 100644 --- a/QRCoder/Extensions/BitArrayExtensions.cs +++ b/QRCoder/Extensions/BitArrayExtensions.cs @@ -18,7 +18,7 @@ internal static class BitArrayExtensions /// The zero-based index in the destination at which storing begins. /// The number of elements to copy. /// The index in the destination immediately following the last copied element. - public static int CopyTo(this BitArray source, int sourceOffset, BitArray destination, int destinationOffset, int count) + public static int CopyTo(this BitArray source, BitArray destination, int sourceOffset, int destinationOffset, int count) { for (int i = 0; i < count; i++) { @@ -26,35 +26,5 @@ public static int CopyTo(this BitArray source, int sourceOffset, BitArray destin } return destinationOffset + count; } - - /// - /// Copies a specified number of elements from one to another starting at the specified offsets, - /// and reverses every set of 8 bits during the copy operation. - /// - /// The source from which elements will be copied. - /// The zero-based index in the source at which copying begins. - /// The destination to which elements will be copied. - /// The zero-based index in the destination at which storing begins. - /// The number of elements to copy. Must be a multiple of 8. - /// The index in the destination immediately following the last copied element. - public static int CopyToRev8(this BitArray source, int sourceOffset, BitArray destination, int destinationOffset, int count) - { - if (count % 8 != 0) - { - throw new ArgumentException("Count must be a multiple of 8.", nameof(count)); - } - - for (int i = 0; i < count; i += 8) - { - // Reverse the current set of 8 bits - for (int j = 0; j < 8; j++) - { - destination[destinationOffset + i + j] = source[sourceOffset + i + (7 - j)]; - } - } - - return destinationOffset + count; - } - } } diff --git a/QRCoder/QRCodeGenerator.cs b/QRCoder/QRCodeGenerator.cs index 409b640d..779d98a2 100644 --- a/QRCoder/QRCodeGenerator.cs +++ b/QRCoder/QRCodeGenerator.cs @@ -224,9 +224,9 @@ private static QRCodeData GenerateQrCode(BitArray bitArray, ECCLevel eccLevel, i //Calculate error correction words var codeWordWithECC = new List(eccInfo.BlocksInGroup1 + eccInfo.BlocksInGroup2); - AddCodeWordBlocks(1, eccInfo.BlocksInGroup1, eccInfo.CodewordsInGroup1, bitArray, 0, bitArray.Length); + AddCodeWordBlocks(1, eccInfo.BlocksInGroup1, eccInfo.CodewordsInGroup1, 0, bitArray.Length); int offset = eccInfo.BlocksInGroup1 * eccInfo.CodewordsInGroup1 * 8; - AddCodeWordBlocks(2, eccInfo.BlocksInGroup2, eccInfo.CodewordsInGroup2, bitArray, offset, bitArray.Length - offset); + AddCodeWordBlocks(2, eccInfo.BlocksInGroup2, eccInfo.CodewordsInGroup2, offset, bitArray.Length - offset); //Calculate interleaved code word lengths @@ -253,7 +253,7 @@ private static QRCodeData GenerateQrCode(BitArray bitArray, ECCLevel eccLevel, i foreach (var codeBlock in codeWordWithECC) { if (codeBlock.CodeWordsLength / 8 > i) - pos = bitArray.CopyTo(i * 8 + codeBlock.CodeWordsOffset, interleavedData, pos, 8); + pos = bitArray.CopyTo(interleavedData, i * 8 + codeBlock.CodeWordsOffset, pos, 8); } } for (var i = 0; i < eccInfo.ECCPerBlock; i++) @@ -287,18 +287,13 @@ private static QRCodeData GenerateQrCode(BitArray bitArray, ECCLevel eccLevel, i ModulePlacer.AddQuietZone(qr); return qr; - void AddCodeWordBlocks(int blockNum, int blocksInGroup, int codewordsInGroup, BitArray bitArray2, int offset2, int count) + void AddCodeWordBlocks(int blockNum, int blocksInGroup, int codewordsInGroup, int offset2, int count) { var groupLength = codewordsInGroup * 8; for (var i = 0; i < blocksInGroup; i++) { - var eccWordList = CalculateECCWords(bitArray2, offset2, groupLength, eccInfo); - codeWordWithECC.Add(new CodewordBlock( - //bitArray2, - offset2, - groupLength, - eccWordList) - ); + var eccWordList = CalculateECCWords(bitArray, offset2, groupLength, eccInfo); + codeWordWithECC.Add(new CodewordBlock(offset2, groupLength, eccWordList)); offset2 += groupLength; } } From 04425ff52146c714c6f1bda049de57d97344ed94 Mon Sep 17 00:00:00 2001 From: Shane32 Date: Mon, 6 May 2024 23:28:01 -0400 Subject: [PATCH 4/7] Remove unused usings --- QRCoder/Extensions/BitArrayExtensions.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/QRCoder/Extensions/BitArrayExtensions.cs b/QRCoder/Extensions/BitArrayExtensions.cs index 11f961eb..1735f8d3 100644 --- a/QRCoder/Extensions/BitArrayExtensions.cs +++ b/QRCoder/Extensions/BitArrayExtensions.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections; -using System.Linq; -using System.Text; +using System.Collections; namespace QRCoder { From 72f7583906efae94777a875c7645228229503870 Mon Sep 17 00:00:00 2001 From: Shane Krueger Date: Thu, 9 May 2024 10:08:08 -0400 Subject: [PATCH 5/7] Update QRCoder/Extensions/BitArrayExtensions.cs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Günther Foidl --- QRCoder/Extensions/BitArrayExtensions.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/QRCoder/Extensions/BitArrayExtensions.cs b/QRCoder/Extensions/BitArrayExtensions.cs index 1735f8d3..4cddb522 100644 --- a/QRCoder/Extensions/BitArrayExtensions.cs +++ b/QRCoder/Extensions/BitArrayExtensions.cs @@ -7,6 +7,7 @@ namespace QRCoder /// internal static class BitArrayExtensions { + /// /// Copies a specified number of elements from one to another starting at the specified offsets. /// /// The source from which elements will be copied. From 132def2692b45c9c134be37faa27fdcaa1ef961d Mon Sep 17 00:00:00 2001 From: Shane Krueger Date: Thu, 9 May 2024 10:08:29 -0400 Subject: [PATCH 6/7] Update QRCoder/QRCodeGenerator.cs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Günther Foidl --- QRCoder/QRCodeGenerator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/QRCoder/QRCodeGenerator.cs b/QRCoder/QRCodeGenerator.cs index 779d98a2..bd0c877b 100644 --- a/QRCoder/QRCodeGenerator.cs +++ b/QRCoder/QRCodeGenerator.cs @@ -253,7 +253,7 @@ private static QRCodeData GenerateQrCode(BitArray bitArray, ECCLevel eccLevel, i foreach (var codeBlock in codeWordWithECC) { if (codeBlock.CodeWordsLength / 8 > i) - pos = bitArray.CopyTo(interleavedData, i * 8 + codeBlock.CodeWordsOffset, pos, 8); + pos = bitArray.CopyTo(interleavedData, (int)((uint)i * 8) + codeBlock.CodeWordsOffset, pos, 8); } } for (var i = 0; i < eccInfo.ECCPerBlock; i++) From d5e2712cb47f57c8e59b72c3b358b3a404cd046a Mon Sep 17 00:00:00 2001 From: Shane32 Date: Sat, 11 May 2024 11:23:07 -0400 Subject: [PATCH 7/7] Apply code suggestions --- QRCoder/QRCodeGenerator.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/QRCoder/QRCodeGenerator.cs b/QRCoder/QRCodeGenerator.cs index bd0c877b..2fe7449d 100644 --- a/QRCoder/QRCodeGenerator.cs +++ b/QRCoder/QRCodeGenerator.cs @@ -234,7 +234,7 @@ private static QRCodeData GenerateQrCode(BitArray bitArray, ECCLevel eccLevel, i for (var i = 0; i < Math.Max(eccInfo.CodewordsInGroup1, eccInfo.CodewordsInGroup2); i++) { foreach (var codeBlock in codeWordWithECC) - if (codeBlock.CodeWordsLength / 8 > i) + if ((uint)codeBlock.CodeWordsLength / 8 > i) interleavedLength += 8; } for (var i = 0; i < eccInfo.ECCPerBlock; i++) @@ -252,7 +252,7 @@ private static QRCodeData GenerateQrCode(BitArray bitArray, ECCLevel eccLevel, i { foreach (var codeBlock in codeWordWithECC) { - if (codeBlock.CodeWordsLength / 8 > i) + if ((uint)codeBlock.CodeWordsLength / 8 > i) pos = bitArray.CopyTo(interleavedData, (int)((uint)i * 8) + codeBlock.CodeWordsOffset, pos, 8); } }