From e41c2b02bd36c13162ad97f8c39d7e76dffc12b8 Mon Sep 17 00:00:00 2001 From: Raffael Herrmann Date: Mon, 8 Nov 2021 19:53:50 +0100 Subject: [PATCH 1/3] Bugfix for #330 Empty lines were falsely removed. (I guess the author initially wanted to remove the whitespace around the QR code. I will add a flag to suppress whitespace in another commit.) --- QRCoder/ASCIIQRCode.cs | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/QRCoder/ASCIIQRCode.cs b/QRCoder/ASCIIQRCode.cs index eabeb7b6..018175af 100644 --- a/QRCoder/ASCIIQRCode.cs +++ b/QRCoder/ASCIIQRCode.cs @@ -68,7 +68,6 @@ public string[] GetLineByLineGraphic(int repeatPerModule, string darkColorString var sideLength = QrCodeData.ModuleMatrix.Count * verticalNumberOfRepeats; for (var y = 0; y < sideLength; y++) { - bool emptyLine = true; var lineBuilder = new StringBuilder(); for (var x = 0; x < QrCodeData.ModuleMatrix.Count; x++) @@ -79,16 +78,8 @@ public string[] GetLineByLineGraphic(int repeatPerModule, string darkColorString { lineBuilder.Append(module ? darkColorString : whiteSpaceString); } - if (module) - { - emptyLine = false; - } } - if (!emptyLine) - { - qrCode.Add(lineBuilder.ToString()); - } - + qrCode.Add(lineBuilder.ToString()); } return qrCode.ToArray(); } From 9a06a554d6a307e127c95f71aad2fd348a77c976 Mon Sep 17 00:00:00 2001 From: Raffael Herrmann Date: Mon, 8 Nov 2021 20:15:15 +0100 Subject: [PATCH 2/3] Added new parameter "drawQuietZones" Added new parameter "drawQuietZones" which enables to suppress the drawing of the quietzones (white border) around the QR code graphic --- QRCoder/ASCIIQRCode.cs | 46 ++++++++++++------------------------------ 1 file changed, 13 insertions(+), 33 deletions(-) diff --git a/QRCoder/ASCIIQRCode.cs b/QRCoder/ASCIIQRCode.cs index 018175af..bffe7cd0 100644 --- a/QRCoder/ASCIIQRCode.cs +++ b/QRCoder/ASCIIQRCode.cs @@ -14,17 +14,7 @@ public AsciiQRCode() { } public AsciiQRCode(QRCodeData data) : base(data) { } - /// - /// Returns a strings that contains the resulting QR code as ASCII chars. - /// - /// Number of repeated darkColorString/whiteSpaceString per module. - /// - public string GetGraphic(int repeatPerModule) - { - return string.Join("\n", GetLineByLineGraphic(repeatPerModule)); - } - - + /// /// Returns a strings that contains the resulting QR code as ASCII chars. /// @@ -33,22 +23,11 @@ public string GetGraphic(int repeatPerModule) /// String for use as white modules (whitespace). In case of string make sure darkColorString has the same length. /// End of line separator. (Default: \n) /// - public string GetGraphic(int repeatPerModule, string darkColorString, string whiteSpaceString, string endOfLine = "\n") - { - return string.Join(endOfLine, GetLineByLineGraphic(repeatPerModule, darkColorString, whiteSpaceString)); - } - - - /// - /// Returns an array of strings that contains each line of the resulting QR code as ASCII chars. - /// - /// Number of repeated darkColorString/whiteSpaceString per module. - /// - public string[] GetLineByLineGraphic(int repeatPerModule) + public string GetGraphic(int repeatPerModule, string darkColorString = "██", string whiteSpaceString = " ", bool drawQuietZones = true, string endOfLine = "\n") { - return GetLineByLineGraphic(repeatPerModule, "██", " "); + return string.Join(endOfLine, GetLineByLineGraphic(repeatPerModule, darkColorString, whiteSpaceString, drawQuietZones)); } - + /// /// Returns an array of strings that contains each line of the resulting QR code as ASCII chars. @@ -57,23 +36,23 @@ public string[] GetLineByLineGraphic(int repeatPerModule) /// String for use as dark color modules. In case of string make sure whiteSpaceString has the same length. /// String for use as white modules (whitespace). In case of string make sure darkColorString has the same length. /// - public string[] GetLineByLineGraphic(int repeatPerModule, string darkColorString, string whiteSpaceString) + public string[] GetLineByLineGraphic(int repeatPerModule, string darkColorString = "██", string whiteSpaceString = " ", bool drawQuietZones = true) { var qrCode = new List(); //We need to adjust the repeatPerModule based on number of characters in darkColorString //(we assume whiteSpaceString has the same number of characters) //to keep the QR code as square as possible. + var quietZonesModifier = (drawQuietZones ? 0 : 8); + var quietZonesOffset = (int)(quietZonesModifier * 0.5); var adjustmentValueForNumberOfCharacters = darkColorString.Length / 2 != 1 ? darkColorString.Length / 2 : 0; var verticalNumberOfRepeats = repeatPerModule + adjustmentValueForNumberOfCharacters; - var sideLength = QrCodeData.ModuleMatrix.Count * verticalNumberOfRepeats; + var sideLength = (QrCodeData.ModuleMatrix.Count - quietZonesModifier) * verticalNumberOfRepeats; for (var y = 0; y < sideLength; y++) { var lineBuilder = new StringBuilder(); - - for (var x = 0; x < QrCodeData.ModuleMatrix.Count; x++) + for (var x = 0; x < QrCodeData.ModuleMatrix.Count - quietZonesModifier; x++) { - var module = QrCodeData.ModuleMatrix[x][(y + verticalNumberOfRepeats) / verticalNumberOfRepeats - 1]; - + var module = QrCodeData.ModuleMatrix[x + quietZonesOffset][((y + verticalNumberOfRepeats) / verticalNumberOfRepeats - 1)+quietZonesOffset]; for (var i = 0; i < repeatPerModule; i++) { lineBuilder.Append(module ? darkColorString : whiteSpaceString); @@ -85,14 +64,15 @@ public string[] GetLineByLineGraphic(int repeatPerModule, string darkColorString } } + public static class AsciiQRCodeHelper { - 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") + 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) { using (var qrGenerator = new QRCodeGenerator()) using (var qrCodeData = qrGenerator.CreateQrCode(plainText, eccLevel, forceUtf8, utf8BOM, eciMode, requestedVersion)) using (var qrCode = new AsciiQRCode(qrCodeData)) - return qrCode.GetGraphic(pixelsPerModule, darkColorString, whiteSpaceString, endOfLine); + return qrCode.GetGraphic(pixelsPerModule, darkColorString, whiteSpaceString, drawQuietZones, endOfLine); } } } \ No newline at end of file From 467c95af16d4e58f0f7c8b06043bc218cabf1b7e Mon Sep 17 00:00:00 2001 From: Raffael Herrmann Date: Mon, 8 Nov 2021 20:37:23 +0100 Subject: [PATCH 3/3] Added test cases for AsciiQrCode --- QRCoderTests/AsciiQRCodeRendererTests.cs | 80 ++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 QRCoderTests/AsciiQRCodeRendererTests.cs diff --git a/QRCoderTests/AsciiQRCodeRendererTests.cs b/QRCoderTests/AsciiQRCodeRendererTests.cs new file mode 100644 index 00000000..6b0517a0 --- /dev/null +++ b/QRCoderTests/AsciiQRCodeRendererTests.cs @@ -0,0 +1,80 @@ +using Xunit; +using QRCoder; +using Shouldly; +using QRCoderTests.XUnitExtenstions; + + +namespace QRCoderTests +{ + + public class AsciiQRCodeRendererTests + { + + [Fact] + [Category("QRRenderer/AsciiQRCode")] + public void can_render_ascii_qrcode() + { + 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 "; + + //Create QR code + var gen = new QRCodeGenerator(); + var data = gen.CreateQrCode("A05", QRCodeGenerator.ECCLevel.Q); + var asciiCode = new AsciiQRCode(data).GetGraphic(1); + + asciiCode.ShouldBe(targetCode); + } + + [Fact] + [Category("QRRenderer/AsciiQRCode")] + public void can_render_ascii_qrcode_without_quietzones() + { + var targetCode = "██████████████ ██ ██ ██████████████\n██ ██ ██ ████ ██ ██\n██ ██████ ██ ██ ██ ██ ██ ██████ ██\n██ ██████ ██ ██ ██ ██████ ██\n██ ██████ ██ ██ ██ ██████ ██\n██ ██ ████████ ██ ██\n██████████████ ██ ██ ██ ██████████████\n ██ ████ \n██████████ ████ ████████ ██ ████ \n████ ██ ██ ████ ████████ ██\n ██ ██ ██████████ ██ ██ ██ ████ \n██ ██ ████ ████ ████ \n ████████ ██████ ████ ██ ██\n ████████ \n██████████████ ████ ████ ██ ████ ████\n██ ██ ████████ \n██ ██████ ██ ██ ██ ██ ██ ██ ██\n██ ██████ ██ ██████ ██ ██ \n██ ██████ ██ ██ ██ ██ ██ ████ ████\n██ ██ ████ ████ ██ ██ \n██████████████ ██████ ██ ██████"; + + //Create QR code + var gen = new QRCodeGenerator(); + var data = gen.CreateQrCode("A05", QRCodeGenerator.ECCLevel.Q); + var asciiCode = new AsciiQRCode(data).GetGraphic(1, drawQuietZones : false); + + asciiCode.ShouldBe(targetCode); + } + + [Fact] + [Category("QRRenderer/AsciiQRCode")] + public void can_render_ascii_qrcode_with_custom_symbols() + { + 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 "; + + //Create QR code + var gen = new QRCodeGenerator(); + var data = gen.CreateQrCode("A", QRCodeGenerator.ECCLevel.Q); + var asciiCode = new AsciiQRCode(data).GetGraphic(2, "X", " "); + + asciiCode.ShouldBe(targetCode); + } + + [Fact] + [Category("QRRenderer/AsciiQRCode")] + public void can_instantate_parameterless() + { + var asciiCode = new AsciiQRCode(); + asciiCode.ShouldNotBeNull(); + asciiCode.ShouldBeOfType(); + } + + [Fact] + [Category("QRRenderer/AsciiQRCode")] + public void can_render_ascii_qrcode_from_helper() + { + 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 "; + + //Create QR code + var gen = new QRCodeGenerator(); + var data = gen.CreateQrCode("A", QRCodeGenerator.ECCLevel.Q); + var asciiCode = AsciiQRCodeHelper.GetQRCode("A", 2, "X", " ", QRCodeGenerator.ECCLevel.Q); + asciiCode.ShouldBe(targetCode); + } + } +} + + +