Skip to content

Commit 25217a0

Browse files
authored
Merge pull request #339 from codebude/bugfix/330-corrupt-ascii-qr-code
Bugfix/330 corrupt ascii qr code
2 parents 90990ec + 467c95a commit 25217a0

File tree

2 files changed

+94
-43
lines changed

2 files changed

+94
-43
lines changed

QRCoder/ASCIIQRCode.cs

Lines changed: 14 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,7 @@ public AsciiQRCode() { }
1414

1515
public AsciiQRCode(QRCodeData data) : base(data) { }
1616

17-
/// <summary>
18-
/// Returns a strings that contains the resulting QR code as ASCII chars.
19-
/// </summary>
20-
/// <param name="repeatPerModule">Number of repeated darkColorString/whiteSpaceString per module.</param>
21-
/// <returns></returns>
22-
public string GetGraphic(int repeatPerModule)
23-
{
24-
return string.Join("\n", GetLineByLineGraphic(repeatPerModule));
25-
}
26-
27-
17+
2818
/// <summary>
2919
/// Returns a strings that contains the resulting QR code as ASCII chars.
3020
/// </summary>
@@ -33,22 +23,11 @@ public string GetGraphic(int repeatPerModule)
3323
/// <param name="whiteSpaceString">String for use as white modules (whitespace). In case of string make sure darkColorString has the same length.</param>
3424
/// <param name="endOfLine">End of line separator. (Default: \n)</param>
3525
/// <returns></returns>
36-
public string GetGraphic(int repeatPerModule, string darkColorString, string whiteSpaceString, string endOfLine = "\n")
26+
public string GetGraphic(int repeatPerModule, string darkColorString = "██", string whiteSpaceString = " ", bool drawQuietZones = true, string endOfLine = "\n")
3727
{
38-
return string.Join(endOfLine, GetLineByLineGraphic(repeatPerModule, darkColorString, whiteSpaceString));
28+
return string.Join(endOfLine, GetLineByLineGraphic(repeatPerModule, darkColorString, whiteSpaceString, drawQuietZones));
3929
}
40-
41-
42-
/// <summary>
43-
/// Returns an array of strings that contains each line of the resulting QR code as ASCII chars.
44-
/// </summary>
45-
/// <param name="repeatPerModule">Number of repeated darkColorString/whiteSpaceString per module.</param>
46-
/// <returns></returns>
47-
public string[] GetLineByLineGraphic(int repeatPerModule)
48-
{
49-
return GetLineByLineGraphic(repeatPerModule, "██", " ");
50-
}
51-
30+
5231

5332
/// <summary>
5433
/// Returns an array of strings that contains each line of the resulting QR code as ASCII chars.
@@ -57,51 +36,43 @@ public string[] GetLineByLineGraphic(int repeatPerModule)
5736
/// <param name="darkColorString">String for use as dark color modules. In case of string make sure whiteSpaceString has the same length.</param>
5837
/// <param name="whiteSpaceString">String for use as white modules (whitespace). In case of string make sure darkColorString has the same length.</param>
5938
/// <returns></returns>
60-
public string[] GetLineByLineGraphic(int repeatPerModule, string darkColorString, string whiteSpaceString)
39+
public string[] GetLineByLineGraphic(int repeatPerModule, string darkColorString = "██", string whiteSpaceString = " ", bool drawQuietZones = true)
6140
{
6241
var qrCode = new List<string>();
6342
//We need to adjust the repeatPerModule based on number of characters in darkColorString
6443
//(we assume whiteSpaceString has the same number of characters)
6544
//to keep the QR code as square as possible.
45+
var quietZonesModifier = (drawQuietZones ? 0 : 8);
46+
var quietZonesOffset = (int)(quietZonesModifier * 0.5);
6647
var adjustmentValueForNumberOfCharacters = darkColorString.Length / 2 != 1 ? darkColorString.Length / 2 : 0;
6748
var verticalNumberOfRepeats = repeatPerModule + adjustmentValueForNumberOfCharacters;
68-
var sideLength = QrCodeData.ModuleMatrix.Count * verticalNumberOfRepeats;
49+
var sideLength = (QrCodeData.ModuleMatrix.Count - quietZonesModifier) * verticalNumberOfRepeats;
6950
for (var y = 0; y < sideLength; y++)
7051
{
71-
bool emptyLine = true;
7252
var lineBuilder = new StringBuilder();
73-
74-
for (var x = 0; x < QrCodeData.ModuleMatrix.Count; x++)
53+
for (var x = 0; x < QrCodeData.ModuleMatrix.Count - quietZonesModifier; x++)
7554
{
76-
var module = QrCodeData.ModuleMatrix[x][(y + verticalNumberOfRepeats) / verticalNumberOfRepeats - 1];
77-
55+
var module = QrCodeData.ModuleMatrix[x + quietZonesOffset][((y + verticalNumberOfRepeats) / verticalNumberOfRepeats - 1)+quietZonesOffset];
7856
for (var i = 0; i < repeatPerModule; i++)
7957
{
8058
lineBuilder.Append(module ? darkColorString : whiteSpaceString);
8159
}
82-
if (module)
83-
{
84-
emptyLine = false;
85-
}
86-
}
87-
if (!emptyLine)
88-
{
89-
qrCode.Add(lineBuilder.ToString());
9060
}
91-
61+
qrCode.Add(lineBuilder.ToString());
9262
}
9363
return qrCode.ToArray();
9464
}
9565
}
9666

67+
9768
public static class AsciiQRCodeHelper
9869
{
99-
public static string GetQRCode(string plainText, int pixelsPerModule, string darkColorString, string whiteSpaceString, ECCLevel eccLevel, bool forceUtf8 = false, bool utf8BOM = false, EciMode eciMode = EciMode.Default, int requestedVersion = -1, string endOfLine = "\n")
70+
public static string GetQRCode(string plainText, int pixelsPerModule, string darkColorString, string whiteSpaceString, ECCLevel eccLevel, bool forceUtf8 = false, bool utf8BOM = false, EciMode eciMode = EciMode.Default, int requestedVersion = -1, string endOfLine = "\n", bool drawQuietZones = true)
10071
{
10172
using (var qrGenerator = new QRCodeGenerator())
10273
using (var qrCodeData = qrGenerator.CreateQrCode(plainText, eccLevel, forceUtf8, utf8BOM, eciMode, requestedVersion))
10374
using (var qrCode = new AsciiQRCode(qrCodeData))
104-
return qrCode.GetGraphic(pixelsPerModule, darkColorString, whiteSpaceString, endOfLine);
75+
return qrCode.GetGraphic(pixelsPerModule, darkColorString, whiteSpaceString, drawQuietZones, endOfLine);
10576
}
10677
}
10778
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
using Xunit;
2+
using QRCoder;
3+
using Shouldly;
4+
using QRCoderTests.XUnitExtenstions;
5+
6+
7+
namespace QRCoderTests
8+
{
9+
10+
public class AsciiQRCodeRendererTests
11+
{
12+
13+
[Fact]
14+
[Category("QRRenderer/AsciiQRCode")]
15+
public void can_render_ascii_qrcode()
16+
{
17+
var targetCode = " \n \n \n \n ██████████████ ██ ██ ██████████████ \n ██ ██ ██ ████ ██ ██ \n ██ ██████ ██ ██ ██ ██ ██ ██████ ██ \n ██ ██████ ██ ██ ██ ██████ ██ \n ██ ██████ ██ ██ ██ ██████ ██ \n ██ ██ ████████ ██ ██ \n ██████████████ ██ ██ ██ ██████████████ \n ██ ████ \n ██████████ ████ ████████ ██ ████ \n ████ ██ ██ ████ ████████ ██ \n ██ ██ ██████████ ██ ██ ██ ████ \n ██ ██ ████ ████ ████ \n ████████ ██████ ████ ██ ██ \n ████████ \n ██████████████ ████ ████ ██ ████ ████ \n ██ ██ ████████ \n ██ ██████ ██ ██ ██ ██ ██ ██ ██ \n ██ ██████ ██ ██████ ██ ██ \n ██ ██████ ██ ██ ██ ██ ██ ████ ████ \n ██ ██ ████ ████ ██ ██ \n ██████████████ ██████ ██ ██████ \n \n \n \n ";
18+
19+
//Create QR code
20+
var gen = new QRCodeGenerator();
21+
var data = gen.CreateQrCode("A05", QRCodeGenerator.ECCLevel.Q);
22+
var asciiCode = new AsciiQRCode(data).GetGraphic(1);
23+
24+
asciiCode.ShouldBe(targetCode);
25+
}
26+
27+
[Fact]
28+
[Category("QRRenderer/AsciiQRCode")]
29+
public void can_render_ascii_qrcode_without_quietzones()
30+
{
31+
var targetCode = "██████████████ ██ ██ ██████████████\n██ ██ ██ ████ ██ ██\n██ ██████ ██ ██ ██ ██ ██ ██████ ██\n██ ██████ ██ ██ ██ ██████ ██\n██ ██████ ██ ██ ██ ██████ ██\n██ ██ ████████ ██ ██\n██████████████ ██ ██ ██ ██████████████\n ██ ████ \n██████████ ████ ████████ ██ ████ \n████ ██ ██ ████ ████████ ██\n ██ ██ ██████████ ██ ██ ██ ████ \n██ ██ ████ ████ ████ \n ████████ ██████ ████ ██ ██\n ████████ \n██████████████ ████ ████ ██ ████ ████\n██ ██ ████████ \n██ ██████ ██ ██ ██ ██ ██ ██ ██\n██ ██████ ██ ██████ ██ ██ \n██ ██████ ██ ██ ██ ██ ██ ████ ████\n██ ██ ████ ████ ██ ██ \n██████████████ ██████ ██ ██████";
32+
33+
//Create QR code
34+
var gen = new QRCodeGenerator();
35+
var data = gen.CreateQrCode("A05", QRCodeGenerator.ECCLevel.Q);
36+
var asciiCode = new AsciiQRCode(data).GetGraphic(1, drawQuietZones : false);
37+
38+
asciiCode.ShouldBe(targetCode);
39+
}
40+
41+
[Fact]
42+
[Category("QRRenderer/AsciiQRCode")]
43+
public void can_render_ascii_qrcode_with_custom_symbols()
44+
{
45+
var targetCode = " \n \n \n \n \n \n \n \n XXXXXXXXXXXXXX XXXX XXXXXXXXXXXXXX \n XXXXXXXXXXXXXX XXXX XXXXXXXXXXXXXX \n XX XX XXXXXX XX XX XX \n XX XX XXXXXX XX XX XX \n XX XXXXXX XX XXXXXXXX XX XXXXXX XX \n XX XXXXXX XX XXXXXXXX XX XXXXXX XX \n XX XXXXXX XX XXXX XX XXXXXX XX \n XX XXXXXX XX XXXX XX XXXXXX XX \n XX XXXXXX XX XX XX XX XXXXXX XX \n XX XXXXXX XX XX XX XX XXXXXX XX \n XX XX XX XX XX \n XX XX XX XX XX \n XXXXXXXXXXXXXX XX XX XX XXXXXXXXXXXXXX \n XXXXXXXXXXXXXX XX XX XX XXXXXXXXXXXXXX \n XXXXXXXX \n XXXXXXXX \n XX XXXXXX XXXXXX XX XX XX \n XX XXXXXX XXXXXX XX XX XX \n XX XXXXXX XXXX XXXXXXXX XXXXXX XX \n XX XXXXXX XXXX XXXXXXXX XXXXXX XX \n XX XX XX XX XX XX \n XX XX XX XX XX XX \n XX XX XX XX XXXXXX \n XX XX XX XX XXXXXX \n XX XXXXXXXX XXXX XX XXXXXXXX XX \n XX XXXXXXXX XXXX XX XXXXXXXX XX \n XX XXXXXXXX XXXX \n XX XXXXXXXX XXXX \n XXXXXXXXXXXXXX XXXXXXXX XX XXXXXX \n XXXXXXXXXXXXXX XXXXXXXX XX XXXXXX \n XX XX XXXXXX XXXXXXXX \n XX XX XXXXXX XXXXXXXX \n XX XXXXXX XX XX XXXX XX XXXX \n XX XXXXXX XX XX XXXX XX XXXX \n XX XXXXXX XX XXXX XXXXXXXX \n XX XXXXXX XX XXXX XXXXXXXX \n XX XXXXXX XX XX XXXXXXXX XX XXXXXX \n XX XXXXXX XX XX XXXXXXXX XX XXXXXX \n XX XX XX XXXX XX \n XX XX XX XXXX XX \n XXXXXXXXXXXXXX XX XXXXXX XXXX XXXX \n XXXXXXXXXXXXXX XX XXXXXX XXXX XXXX \n \n \n \n \n \n \n \n ";
46+
47+
//Create QR code
48+
var gen = new QRCodeGenerator();
49+
var data = gen.CreateQrCode("A", QRCodeGenerator.ECCLevel.Q);
50+
var asciiCode = new AsciiQRCode(data).GetGraphic(2, "X", " ");
51+
52+
asciiCode.ShouldBe(targetCode);
53+
}
54+
55+
[Fact]
56+
[Category("QRRenderer/AsciiQRCode")]
57+
public void can_instantate_parameterless()
58+
{
59+
var asciiCode = new AsciiQRCode();
60+
asciiCode.ShouldNotBeNull();
61+
asciiCode.ShouldBeOfType<AsciiQRCode>();
62+
}
63+
64+
[Fact]
65+
[Category("QRRenderer/AsciiQRCode")]
66+
public void can_render_ascii_qrcode_from_helper()
67+
{
68+
var targetCode = " \n \n \n \n \n \n \n \n XXXXXXXXXXXXXX XXXX XXXXXXXXXXXXXX \n XXXXXXXXXXXXXX XXXX XXXXXXXXXXXXXX \n XX XX XXXXXX XX XX XX \n XX XX XXXXXX XX XX XX \n XX XXXXXX XX XXXXXXXX XX XXXXXX XX \n XX XXXXXX XX XXXXXXXX XX XXXXXX XX \n XX XXXXXX XX XXXX XX XXXXXX XX \n XX XXXXXX XX XXXX XX XXXXXX XX \n XX XXXXXX XX XX XX XX XXXXXX XX \n XX XXXXXX XX XX XX XX XXXXXX XX \n XX XX XX XX XX \n XX XX XX XX XX \n XXXXXXXXXXXXXX XX XX XX XXXXXXXXXXXXXX \n XXXXXXXXXXXXXX XX XX XX XXXXXXXXXXXXXX \n XXXXXXXX \n XXXXXXXX \n XX XXXXXX XXXXXX XX XX XX \n XX XXXXXX XXXXXX XX XX XX \n XX XXXXXX XXXX XXXXXXXX XXXXXX XX \n XX XXXXXX XXXX XXXXXXXX XXXXXX XX \n XX XX XX XX XX XX \n XX XX XX XX XX XX \n XX XX XX XX XXXXXX \n XX XX XX XX XXXXXX \n XX XXXXXXXX XXXX XX XXXXXXXX XX \n XX XXXXXXXX XXXX XX XXXXXXXX XX \n XX XXXXXXXX XXXX \n XX XXXXXXXX XXXX \n XXXXXXXXXXXXXX XXXXXXXX XX XXXXXX \n XXXXXXXXXXXXXX XXXXXXXX XX XXXXXX \n XX XX XXXXXX XXXXXXXX \n XX XX XXXXXX XXXXXXXX \n XX XXXXXX XX XX XXXX XX XXXX \n XX XXXXXX XX XX XXXX XX XXXX \n XX XXXXXX XX XXXX XXXXXXXX \n XX XXXXXX XX XXXX XXXXXXXX \n XX XXXXXX XX XX XXXXXXXX XX XXXXXX \n XX XXXXXX XX XX XXXXXXXX XX XXXXXX \n XX XX XX XXXX XX \n XX XX XX XXXX XX \n XXXXXXXXXXXXXX XX XXXXXX XXXX XXXX \n XXXXXXXXXXXXXX XX XXXXXX XXXX XXXX \n \n \n \n \n \n \n \n ";
69+
70+
//Create QR code
71+
var gen = new QRCodeGenerator();
72+
var data = gen.CreateQrCode("A", QRCodeGenerator.ECCLevel.Q);
73+
var asciiCode = AsciiQRCodeHelper.GetQRCode("A", 2, "X", " ", QRCodeGenerator.ECCLevel.Q);
74+
asciiCode.ShouldBe(targetCode);
75+
}
76+
}
77+
}
78+
79+
80+

0 commit comments

Comments
 (0)