Skip to content

Commit b26488e

Browse files
authored
Merge pull request #520 from Shane32/bitarray_codeword_blocks
Deduplicate data block buffers
2 parents 10093b7 + c877a97 commit b26488e

File tree

3 files changed

+53
-49
lines changed

3 files changed

+53
-49
lines changed
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
using System.Collections;
2+
3+
namespace QRCoder
4+
{
5+
/// <summary>
6+
/// Helper methods for <see cref="BitArray"/>.
7+
/// </summary>
8+
internal static class BitArrayExtensions
9+
{
10+
/// <summary>
11+
/// Copies a specified number of elements from one <see cref="BitArray"/> to another starting at the specified offsets.
12+
/// </summary>
13+
/// <param name="source">The source <see cref="BitArray"/> from which elements will be copied.</param>
14+
/// <param name="sourceOffset">The zero-based index in the source <see cref="BitArray"/> at which copying begins.</param>
15+
/// <param name="destination">The destination <see cref="BitArray"/> to which elements will be copied.</param>
16+
/// <param name="destinationOffset">The zero-based index in the destination <see cref="BitArray"/> at which storing begins.</param>
17+
/// <param name="count">The number of elements to copy.</param>
18+
/// <returns>The index in the destination <see cref="BitArray"/> immediately following the last copied element.</returns>
19+
public static int CopyTo(this BitArray source, BitArray destination, int sourceOffset, int destinationOffset, int count)
20+
{
21+
for (int i = 0; i < count; i++)
22+
{
23+
destination[destinationOffset + i] = source[sourceOffset + i];
24+
}
25+
return destinationOffset + count;
26+
}
27+
}
28+
}

QRCoder/QRCodeGenerator.CodewordBlock.cs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
namespace QRCoder
1+
using System.Collections;
2+
3+
namespace QRCoder
24
{
35
public partial class QRCodeGenerator
46
{
@@ -11,18 +13,25 @@ private struct CodewordBlock
1113
/// <summary>
1214
/// Initializes a new instance of the CodewordBlock struct with specified arrays of code words and error correction (ECC) words.
1315
/// </summary>
14-
/// <param name="codeWords">The array of data codewords for this block. Data codewords carry the actual information.</param>
16+
/// <param name="codeWordsOffset">The offset of the data codewords within the main BitArray. Data codewords carry the actual information.</param>
17+
/// <param name="codeWordsLength">The length in bits of the data codewords within the main BitArray.</param>
1518
/// <param name="eccWords">The array of error correction codewords for this block. These codewords help recover the data if the QR code is damaged.</param>
16-
public CodewordBlock(byte[] codeWords, byte[] eccWords)
19+
public CodewordBlock(int codeWordsOffset, int codeWordsLength, byte[] eccWords)
1720
{
18-
this.CodeWords = codeWords;
21+
this.CodeWordsOffset = codeWordsOffset;
22+
this.CodeWordsLength = codeWordsLength;
1923
this.ECCWords = eccWords;
2024
}
2125

2226
/// <summary>
23-
/// Gets the data codewords associated with this block.
27+
/// Gets the offset of the data codewords in the BitArray.
28+
/// </summary>
29+
public int CodeWordsOffset { get; }
30+
31+
/// <summary>
32+
/// Gets the length of the data codewords in the BitArray.
2433
/// </summary>
25-
public byte[] CodeWords { get; }
34+
public int CodeWordsLength { get; }
2635

2736
/// <summary>
2837
/// Gets the error correction codewords associated with this block.

QRCoder/QRCodeGenerator.cs

Lines changed: 10 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -228,17 +228,17 @@ private static QRCodeData GenerateQrCode(BitArray bitArray, ECCLevel eccLevel, i
228228
{
229229
//Calculate error correction words
230230
codeWordWithECC = new List<CodewordBlock>(eccInfo.BlocksInGroup1 + eccInfo.BlocksInGroup2);
231-
AddCodeWordBlocks(1, eccInfo.BlocksInGroup1, eccInfo.CodewordsInGroup1, bitArray, 0, bitArray.Length, generatorPolynom);
231+
AddCodeWordBlocks(1, eccInfo.BlocksInGroup1, eccInfo.CodewordsInGroup1, 0, bitArray.Length, generatorPolynom);
232232
int offset = eccInfo.BlocksInGroup1 * eccInfo.CodewordsInGroup1 * 8;
233-
AddCodeWordBlocks(2, eccInfo.BlocksInGroup2, eccInfo.CodewordsInGroup2, bitArray, offset, bitArray.Length - offset, generatorPolynom);
233+
AddCodeWordBlocks(2, eccInfo.BlocksInGroup2, eccInfo.CodewordsInGroup2, offset, bitArray.Length - offset, generatorPolynom);
234234
}
235235

236236
//Calculate interleaved code word lengths
237237
int interleavedLength = 0;
238238
for (var i = 0; i < Math.Max(eccInfo.CodewordsInGroup1, eccInfo.CodewordsInGroup2); i++)
239239
{
240240
foreach (var codeBlock in codeWordWithECC)
241-
if (codeBlock.CodeWords.Length > i)
241+
if ((uint)codeBlock.CodeWordsLength / 8 > i)
242242
interleavedLength += 8;
243243
}
244244
for (var i = 0; i < eccInfo.ECCPerBlock; i++)
@@ -255,8 +255,10 @@ private static QRCodeData GenerateQrCode(BitArray bitArray, ECCLevel eccLevel, i
255255
for (var i = 0; i < Math.Max(eccInfo.CodewordsInGroup1, eccInfo.CodewordsInGroup2); i++)
256256
{
257257
foreach (var codeBlock in codeWordWithECC)
258-
if (codeBlock.CodeWords.Length > i)
259-
pos = DecToBin(codeBlock.CodeWords[i], 8, interleavedData, pos);
258+
{
259+
if ((uint)codeBlock.CodeWordsLength / 8 > i)
260+
pos = bitArray.CopyTo(interleavedData, (int)((uint)i * 8) + codeBlock.CodeWordsOffset, pos, 8);
261+
}
260262
}
261263
for (var i = 0; i < eccInfo.ECCPerBlock; i++)
262264
{
@@ -289,17 +291,13 @@ private static QRCodeData GenerateQrCode(BitArray bitArray, ECCLevel eccLevel, i
289291
ModulePlacer.AddQuietZone(qr);
290292
return qr;
291293

292-
void AddCodeWordBlocks(int blockNum, int blocksInGroup, int codewordsInGroup, BitArray bitArray2, int offset2, int count, Polynom generatorPolynom)
294+
void AddCodeWordBlocks(int blockNum, int blocksInGroup, int codewordsInGroup, int offset2, int count, Polynom generatorPolynom)
293295
{
294296
var groupLength = codewordsInGroup * 8;
295297
for (var i = 0; i < blocksInGroup; i++)
296298
{
297-
var bitBlockList = BinaryStringToBitBlockByteList(bitArray2, offset2, groupLength);
298-
var eccWordList = CalculateECCWords(bitArray2, offset2, groupLength, eccInfo, generatorPolynom);
299-
codeWordWithECC.Add(new CodewordBlock(
300-
bitBlockList,
301-
eccWordList)
302-
);
299+
var eccWordList = CalculateECCWords(bitArray, offset2, groupLength, eccInfo, generatorPolynom);
300+
codeWordWithECC.Add(new CodewordBlock(offset2, groupLength, eccWordList));
303301
offset2 += groupLength;
304302
}
305303
}
@@ -618,37 +616,6 @@ private static Polynom CalculateGeneratorPolynom(int numEccWords)
618616
return generatorPolynom; // Return the completed generator polynomial
619617
}
620618

621-
/// <summary>
622-
/// Converts a segment of a BitArray into a list of bytes where each byte represents a consecutive block of 8 bits from the BitArray.
623-
/// </summary>
624-
private static byte[] BinaryStringToBitBlockByteList(BitArray bitString, int offset, int count)
625-
{
626-
const int blockSize = 8;
627-
if (count % blockSize != 0)
628-
ThrowCountMustBeMultipleOf8Exception();
629-
var numberOfBlocks = (int)((uint)count / blockSize);
630-
var blocklist = new byte[numberOfBlocks];
631-
632-
int j = 0;
633-
count += offset;
634-
for (int i = offset; i < count; i += blockSize)
635-
{
636-
blocklist[j++] = (byte)(
637-
(bitString[i] ? 128 : 0) +
638-
(bitString[i + 1] ? 64 : 0) +
639-
(bitString[i + 2] ? 32 : 0) +
640-
(bitString[i + 3] ? 16 : 0) +
641-
(bitString[i + 4] ? 8 : 0) +
642-
(bitString[i + 5] ? 4 : 0) +
643-
(bitString[i + 6] ? 2 : 0) +
644-
(bitString[i + 7] ? 1 : 0));
645-
}
646-
647-
return blocklist;
648-
649-
void ThrowCountMustBeMultipleOf8Exception() => throw new ArgumentOutOfRangeException(nameof(count), "Count must be a multiple of 8.");
650-
}
651-
652619
/// <summary>
653620
/// Converts a segment of a BitArray into its decimal (integer) equivalent.
654621
/// </summary>

0 commit comments

Comments
 (0)