Skip to content

Commit 5c0fcd8

Browse files
committed
Add code comments
1 parent ff0fd9c commit 5c0fcd8

10 files changed

+455
-102
lines changed

QRCoder/QRCodeGenerator.ECCInfo.cs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,22 @@
22
{
33
public partial class QRCodeGenerator
44
{
5+
/// <summary>
6+
/// Represents the error correction coding (ECC) information for a specific version and error correction level of a QR code.
7+
/// </summary>
58
private struct ECCInfo
69
{
10+
/// <summary>
11+
/// Initializes a new instance of the ECCInfo struct with specified properties.
12+
/// </summary>
13+
/// <param name="version">The version number of the QR code.</param>
14+
/// <param name="errorCorrectionLevel">The error correction level used in the QR code.</param>
15+
/// <param name="totalDataCodewords">The total number of data codewords for this version and error correction level.</param>
16+
/// <param name="eccPerBlock">The number of error correction codewords per block.</param>
17+
/// <param name="blocksInGroup1">The number of blocks in group 1.</param>
18+
/// <param name="codewordsInGroup1">The number of codewords in each block of group 1.</param>
19+
/// <param name="blocksInGroup2">The number of blocks in group 2, if any.</param>
20+
/// <param name="codewordsInGroup2">The number of codewords in each block of group 2, if any.</param>
721
public ECCInfo(int version, ECCLevel errorCorrectionLevel, int totalDataCodewords, int eccPerBlock, int blocksInGroup1,
822
int codewordsInGroup1, int blocksInGroup2, int codewordsInGroup2)
923
{
@@ -16,13 +30,45 @@ public ECCInfo(int version, ECCLevel errorCorrectionLevel, int totalDataCodeword
1630
this.BlocksInGroup2 = blocksInGroup2;
1731
this.CodewordsInGroup2 = codewordsInGroup2;
1832
}
33+
34+
/// <summary>
35+
/// Gets the version number of the QR code.
36+
/// </summary>
1937
public int Version { get; }
38+
39+
/// <summary>
40+
/// Gets the error correction level of the QR code.
41+
/// </summary>
2042
public ECCLevel ErrorCorrectionLevel { get; }
43+
44+
/// <summary>
45+
/// Gets the total number of data codewords for this version and error correction level.
46+
/// </summary>
2147
public int TotalDataCodewords { get; }
48+
49+
/// <summary>
50+
/// Gets the number of error correction codewords per block.
51+
/// </summary>
2252
public int ECCPerBlock { get; }
53+
54+
/// <summary>
55+
/// Gets the number of blocks in group 1.
56+
/// </summary>
2357
public int BlocksInGroup1 { get; }
58+
59+
/// <summary>
60+
/// Gets the number of codewords in each block of group 1.
61+
/// </summary>
2462
public int CodewordsInGroup1 { get; }
63+
64+
/// <summary>
65+
/// Gets the number of blocks in group 2, if any.
66+
/// </summary>
2567
public int BlocksInGroup2 { get; }
68+
69+
/// <summary>
70+
/// Gets the number of codewords in each block of group 2, if any.
71+
/// </summary>
2672
public int CodewordsInGroup2 { get; }
2773
}
2874
}

QRCoder/QRCodeGenerator.EncodingMode.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,39 @@
22
{
33
public partial class QRCodeGenerator
44
{
5+
/// <summary>
6+
/// Specifies the encoding modes for the characters in a QR code.
7+
/// </summary>
58
private enum EncodingMode
69
{
10+
/// <summary>
11+
/// Numeric encoding mode, which is used to encode numeric data (digits 0-9).
12+
/// Three characters are encoded into 10 bits.
13+
/// </summary>
714
Numeric = 1,
15+
16+
/// <summary>
17+
/// Alphanumeric encoding mode, which is used to encode alphanumeric characters (0-9, A-Z, space, and some punctuation).
18+
/// Two characters are encoded into 11 bits.
19+
/// </summary>
820
Alphanumeric = 2,
21+
22+
/// <summary>
23+
/// Byte encoding mode, primarily using the ISO-8859-1 character set. Each character is encoded into 8 bits.
24+
/// When combined with ECI, it can be adapted to use other character sets.
25+
/// </summary>
926
Byte = 4,
27+
28+
/// <summary>
29+
/// Kanji encoding mode, which is used to encode characters from the Shift JIS character set, primarily for Japanese Kanji and Kana characters.
30+
/// One character is encoded into 13 bits.
31+
/// </summary>
1032
Kanji = 8,
33+
34+
/// <summary>
35+
/// Extended Channel Interpretation (ECI) mode, which specifies a character set via an 8-bit number followed by one of the other encoding modes.
36+
/// This allows adapting the byte encoding to accommodate various global text encodings.
37+
/// </summary>
1138
ECI = 7
1239
}
1340
}

QRCoder/QRCodeGenerator.ModulePlacer.MaskPattern.cs

Lines changed: 93 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Collections;
23
using System.Collections.Generic;
34

45
namespace QRCoder
@@ -7,63 +8,109 @@ public partial class QRCodeGenerator
78
{
89
private static partial class ModulePlacer
910
{
11+
/// <summary>
12+
/// Provides static methods and properties to handle mask patterns used in QR code generation.
13+
/// Mask patterns are applied to QR codes to break up patterns in the data matrix that might confuse scanners.
14+
/// </summary>
1015
private static class MaskPattern
1116
{
17+
/// <summary>
18+
/// A dictionary mapping each mask pattern index to its corresponding function that calculates whether a given pixel should be masked.
19+
/// </summary>
1220
public static readonly Dictionary<int, Func<int, int, bool>> Patterns =
1321
new Dictionary<int, Func<int, int, bool>>(8) {
1422
{ 1, MaskPattern.Pattern1 }, {2, MaskPattern.Pattern2 }, {3, MaskPattern.Pattern3 }, {4, MaskPattern.Pattern4 },
1523
{ 5, MaskPattern.Pattern5 }, {6, MaskPattern.Pattern6 }, {7, MaskPattern.Pattern7 }, {8, MaskPattern.Pattern8 }
1624
};
1725

26+
/// <summary>
27+
/// Mask pattern 1: (x + y) % 2 == 0
28+
/// Applies a checkerboard mask on the QR code.
29+
/// </summary>
1830
public static bool Pattern1(int x, int y)
1931
{
2032
return (x + y) % 2 == 0;
2133
}
2234

35+
/// <summary>
36+
/// Mask pattern 2: y % 2 == 0
37+
/// Applies a horizontal striping mask on the QR code.
38+
/// </summary>
2339
public static bool Pattern2(int x, int y)
2440
{
2541
return y % 2 == 0;
2642
}
2743

44+
/// <summary>
45+
/// Mask pattern 3: x % 3 == 0
46+
/// Applies a vertical striping mask on the QR code.
47+
/// </summary>
2848
public static bool Pattern3(int x, int y)
2949
{
3050
return x % 3 == 0;
3151
}
3252

53+
/// <summary>
54+
/// Mask pattern 4: (x + y) % 3 == 0
55+
/// Applies a diagonal striping mask on the QR code.
56+
/// </summary>
3357
public static bool Pattern4(int x, int y)
3458
{
3559
return (x + y) % 3 == 0;
3660
}
3761

62+
/// <summary>
63+
/// Mask pattern 5: ((y / 2) + (x / 3)) % 2 == 0
64+
/// Applies a complex pattern mask on the QR code, mixing horizontal and vertical rules.
65+
/// </summary>
3866
public static bool Pattern5(int x, int y)
3967
{
4068
return ((int)(Math.Floor(y / 2d) + Math.Floor(x / 3d)) % 2) == 0;
4169
}
4270

71+
/// <summary>
72+
/// Mask pattern 6: ((x * y) % 2 + (x * y) % 3) == 0
73+
/// Applies a mask based on the product of x and y coordinates modulo 2 and 3.
74+
/// </summary>
4375
public static bool Pattern6(int x, int y)
4476
{
4577
return ((x * y) % 2) + ((x * y) % 3) == 0;
4678
}
4779

80+
/// <summary>
81+
/// Mask pattern 7: (((x * y) % 2 + (x * y) % 3) % 2) == 0
82+
/// Applies a mask based on a more complex function involving the product of x and y coordinates.
83+
/// </summary>
4884
public static bool Pattern7(int x, int y)
4985
{
5086
return (((x * y) % 2) + ((x * y) % 3)) % 2 == 0;
5187
}
5288

89+
/// <summary>
90+
/// Mask pattern 8: (((x + y) % 2) + ((x * y) % 3) % 2) == 0
91+
/// Combines rules of checkers and complex multiplicative masks.
92+
/// </summary>
5393
public static bool Pattern8(int x, int y)
5494
{
5595
return (((x + y) % 2) + ((x * y) % 3)) % 2 == 0;
5696
}
5797

98+
/// <summary>
99+
/// Calculates a penalty score for a QR code to evaluate the effectiveness of a mask pattern.
100+
/// A lower score indicates a QR code that is easier for decoders to read accurately.
101+
/// The score is the sum of four penalty rules applied to the QR code.
102+
/// </summary>
103+
/// <param name="qrCode">The QR code data structure to be evaluated.</param>
104+
/// <returns>The total penalty score of the QR code.</returns>
58105
public static int Score(QRCodeData qrCode)
59106
{
60-
int score1 = 0,
61-
score2 = 0,
62-
score3 = 0,
63-
score4 = 0;
107+
int score1 = 0, // Penalty for groups of five or more same-color modules in a row (or column)
108+
score2 = 0, // Penalty for blocks of modules in the same color
109+
score3 = 0, // Penalty for specific patterns found within the QR code
110+
score4 = 0; // Penalty for having more than 50% black modules or more than 50% white modules
64111
var size = qrCode.ModuleMatrix.Count;
65112

66-
//Penalty 1
113+
//Penalty 1: Checking for consecutive modules of the same color in rows and columns
67114
for (var y = 0; y < size; y++)
68115
{
69116
var modInRow = 0;
@@ -72,6 +119,7 @@ public static int Score(QRCodeData qrCode)
72119
var lastValColumn = qrCode.ModuleMatrix[0][y];
73120
for (var x = 0; x < size; x++)
74121
{
122+
// Check rows for consecutive modules
75123
if (qrCode.ModuleMatrix[y][x] == lastValRow)
76124
modInRow++;
77125
else
@@ -82,7 +130,7 @@ public static int Score(QRCodeData qrCode)
82130
score1++;
83131
lastValRow = qrCode.ModuleMatrix[y][x];
84132

85-
133+
// Check columns for consecutive modules
86134
if (qrCode.ModuleMatrix[x][y] == lastValColumn)
87135
modInColumn++;
88136
else
@@ -95,79 +143,35 @@ public static int Score(QRCodeData qrCode)
95143
}
96144
}
97145

98-
99-
//Penalty 2
146+
//Penalty 2: Checking for blocks of modules in the same color
100147
for (var y = 0; y < size - 1; y++)
101148
{
102149
for (var x = 0; x < size - 1; x++)
103150
{
104151
if (qrCode.ModuleMatrix[y][x] == qrCode.ModuleMatrix[y][x + 1] &&
105152
qrCode.ModuleMatrix[y][x] == qrCode.ModuleMatrix[y + 1][x] &&
106153
qrCode.ModuleMatrix[y][x] == qrCode.ModuleMatrix[y + 1][x + 1])
154+
{
107155
score2 += 3;
156+
}
108157
}
109158
}
110159

111-
//Penalty 3
160+
//Penalty 3: Checking for specific patterns within the QR code (patterns that should be avoided)
112161
for (var y = 0; y < size; y++)
113162
{
114163
for (var x = 0; x < size - 10; x++)
115164
{
116-
if ((qrCode.ModuleMatrix[y][x] &&
117-
!qrCode.ModuleMatrix[y][x + 1] &&
118-
qrCode.ModuleMatrix[y][x + 2] &&
119-
qrCode.ModuleMatrix[y][x + 3] &&
120-
qrCode.ModuleMatrix[y][x + 4] &&
121-
!qrCode.ModuleMatrix[y][x + 5] &&
122-
qrCode.ModuleMatrix[y][x + 6] &&
123-
!qrCode.ModuleMatrix[y][x + 7] &&
124-
!qrCode.ModuleMatrix[y][x + 8] &&
125-
!qrCode.ModuleMatrix[y][x + 9] &&
126-
!qrCode.ModuleMatrix[y][x + 10]) ||
127-
(!qrCode.ModuleMatrix[y][x] &&
128-
!qrCode.ModuleMatrix[y][x + 1] &&
129-
!qrCode.ModuleMatrix[y][x + 2] &&
130-
!qrCode.ModuleMatrix[y][x + 3] &&
131-
qrCode.ModuleMatrix[y][x + 4] &&
132-
!qrCode.ModuleMatrix[y][x + 5] &&
133-
qrCode.ModuleMatrix[y][x + 6] &&
134-
qrCode.ModuleMatrix[y][x + 7] &&
135-
qrCode.ModuleMatrix[y][x + 8] &&
136-
!qrCode.ModuleMatrix[y][x + 9] &&
137-
qrCode.ModuleMatrix[y][x + 10]))
138-
{
165+
// Horizontal pattern matching
166+
if (MatchesPattern1(qrCode.ModuleMatrix, x, y))
139167
score3 += 40;
140-
}
141-
142-
if ((qrCode.ModuleMatrix[x][y] &&
143-
!qrCode.ModuleMatrix[x + 1][y] &&
144-
qrCode.ModuleMatrix[x + 2][y] &&
145-
qrCode.ModuleMatrix[x + 3][y] &&
146-
qrCode.ModuleMatrix[x + 4][y] &&
147-
!qrCode.ModuleMatrix[x + 5][y] &&
148-
qrCode.ModuleMatrix[x + 6][y] &&
149-
!qrCode.ModuleMatrix[x + 7][y] &&
150-
!qrCode.ModuleMatrix[x + 8][y] &&
151-
!qrCode.ModuleMatrix[x + 9][y] &&
152-
!qrCode.ModuleMatrix[x + 10][y]) ||
153-
(!qrCode.ModuleMatrix[x][y] &&
154-
!qrCode.ModuleMatrix[x + 1][y] &&
155-
!qrCode.ModuleMatrix[x + 2][y] &&
156-
!qrCode.ModuleMatrix[x + 3][y] &&
157-
qrCode.ModuleMatrix[x + 4][y] &&
158-
!qrCode.ModuleMatrix[x + 5][y] &&
159-
qrCode.ModuleMatrix[x + 6][y] &&
160-
qrCode.ModuleMatrix[x + 7][y] &&
161-
qrCode.ModuleMatrix[x + 8][y] &&
162-
!qrCode.ModuleMatrix[x + 9][y] &&
163-
qrCode.ModuleMatrix[x + 10][y]))
164-
{
168+
// Vertical pattern matching
169+
if (MatchesPattern1(qrCode.ModuleMatrix, y, x))
165170
score3 += 40;
166-
}
167171
}
168172
}
169173

170-
//Penalty 4
174+
//Penalty 4: Proportions of dark and light modules
171175
int blackModules = 0;
172176
foreach (var bitArray in qrCode.ModuleMatrix)
173177
for (var x = 0; x < size; x++)
@@ -179,8 +183,38 @@ public static int Score(QRCodeData qrCode)
179183
var nextMultipleOf5 = Math.Abs(percentDiv5 - 9);
180184
score4 = Math.Min(prevMultipleOf5, nextMultipleOf5) * 10;
181185

186+
// Return the sum of all four penalties
182187
return (score1 + score2) + (score3 + score4);
183188
}
189+
190+
/// <summary>
191+
/// Matches the specified pattern in QR code evaluation rules (1:1:3:1:1 ratio).
192+
/// </summary>
193+
private static bool MatchesPattern1(List<BitArray> matrix, int x, int y)
194+
{
195+
return (matrix[y][x] &&
196+
!matrix[y][x + 1] &&
197+
matrix[y][x + 2] &&
198+
matrix[y][x + 3] &&
199+
matrix[y][x + 4] &&
200+
!matrix[y][x + 5] &&
201+
matrix[y][x + 6] &&
202+
!matrix[y][x + 7] &&
203+
!matrix[y][x + 8] &&
204+
!matrix[y][x + 9] &&
205+
!matrix[y][x + 10]) ||
206+
(!matrix[y][x] &&
207+
!matrix[y][x + 1] &&
208+
!matrix[y][x + 2] &&
209+
!matrix[y][x + 3] &&
210+
matrix[y][x + 4] &&
211+
!matrix[y][x + 5] &&
212+
matrix[y][x + 6] &&
213+
matrix[y][x + 7] &&
214+
matrix[y][x + 8] &&
215+
!matrix[y][x + 9] &&
216+
matrix[y][x + 10]);
217+
}
184218
}
185219
}
186220
}

0 commit comments

Comments
 (0)