Skip to content

Commit 51e8c92

Browse files
authored
Merge branch 'master' into string_optimizations
2 parents 8d13dd7 + b26488e commit 51e8c92

File tree

3 files changed

+53
-49
lines changed

3 files changed

+53
-49
lines changed
+28
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

+15-6
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

+10-43
Original file line numberDiff line numberDiff line change
@@ -231,17 +231,17 @@ private static QRCodeData GenerateQrCode(BitArray bitArray, ECCLevel eccLevel, i
231231
{
232232
//Calculate error correction words
233233
codeWordWithECC = new List<CodewordBlock>(eccInfo.BlocksInGroup1 + eccInfo.BlocksInGroup2);
234-
AddCodeWordBlocks(1, eccInfo.BlocksInGroup1, eccInfo.CodewordsInGroup1, bitArray, 0, bitArray.Length, generatorPolynom);
234+
AddCodeWordBlocks(1, eccInfo.BlocksInGroup1, eccInfo.CodewordsInGroup1, 0, bitArray.Length, generatorPolynom);
235235
int offset = eccInfo.BlocksInGroup1 * eccInfo.CodewordsInGroup1 * 8;
236-
AddCodeWordBlocks(2, eccInfo.BlocksInGroup2, eccInfo.CodewordsInGroup2, bitArray, offset, bitArray.Length - offset, generatorPolynom);
236+
AddCodeWordBlocks(2, eccInfo.BlocksInGroup2, eccInfo.CodewordsInGroup2, offset, bitArray.Length - offset, generatorPolynom);
237237
}
238238

239239
//Calculate interleaved code word lengths
240240
int interleavedLength = 0;
241241
for (var i = 0; i < Math.Max(eccInfo.CodewordsInGroup1, eccInfo.CodewordsInGroup2); i++)
242242
{
243243
foreach (var codeBlock in codeWordWithECC)
244-
if (codeBlock.CodeWords.Length > i)
244+
if ((uint)codeBlock.CodeWordsLength / 8 > i)
245245
interleavedLength += 8;
246246
}
247247
for (var i = 0; i < eccInfo.ECCPerBlock; i++)
@@ -258,8 +258,10 @@ private static QRCodeData GenerateQrCode(BitArray bitArray, ECCLevel eccLevel, i
258258
for (var i = 0; i < Math.Max(eccInfo.CodewordsInGroup1, eccInfo.CodewordsInGroup2); i++)
259259
{
260260
foreach (var codeBlock in codeWordWithECC)
261-
if (codeBlock.CodeWords.Length > i)
262-
pos = DecToBin(codeBlock.CodeWords[i], 8, interleavedData, pos);
261+
{
262+
if ((uint)codeBlock.CodeWordsLength / 8 > i)
263+
pos = bitArray.CopyTo(interleavedData, (int)((uint)i * 8) + codeBlock.CodeWordsOffset, pos, 8);
264+
}
263265
}
264266
for (var i = 0; i < eccInfo.ECCPerBlock; i++)
265267
{
@@ -292,17 +294,13 @@ private static QRCodeData GenerateQrCode(BitArray bitArray, ECCLevel eccLevel, i
292294
ModulePlacer.AddQuietZone(qr);
293295
return qr;
294296

295-
void AddCodeWordBlocks(int blockNum, int blocksInGroup, int codewordsInGroup, BitArray bitArray2, int offset2, int count, Polynom generatorPolynom)
297+
void AddCodeWordBlocks(int blockNum, int blocksInGroup, int codewordsInGroup, int offset2, int count, Polynom generatorPolynom)
296298
{
297299
var groupLength = codewordsInGroup * 8;
298300
for (var i = 0; i < blocksInGroup; i++)
299301
{
300-
var bitBlockList = BinaryStringToBitBlockByteList(bitArray2, offset2, groupLength);
301-
var eccWordList = CalculateECCWords(bitArray2, offset2, groupLength, eccInfo, generatorPolynom);
302-
codeWordWithECC.Add(new CodewordBlock(
303-
bitBlockList,
304-
eccWordList)
305-
);
302+
var eccWordList = CalculateECCWords(bitArray, offset2, groupLength, eccInfo, generatorPolynom);
303+
codeWordWithECC.Add(new CodewordBlock(offset2, groupLength, eccWordList));
306304
offset2 += groupLength;
307305
}
308306
}
@@ -621,37 +619,6 @@ private static Polynom CalculateGeneratorPolynom(int numEccWords)
621619
return generatorPolynom; // Return the completed generator polynomial
622620
}
623621

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

0 commit comments

Comments
 (0)