diff --git a/QRCoder/ASCIIQRCode.cs b/QRCoder/ASCIIQRCode.cs
index bffe7cd0..6f07c447 100644
--- a/QRCoder/ASCIIQRCode.cs
+++ b/QRCoder/ASCIIQRCode.cs
@@ -16,18 +16,21 @@ public AsciiQRCode(QRCodeData data) : base(data) { }
///
- /// Returns a strings that contains the resulting QR code as ASCII chars.
+ /// Returns a strings that contains the resulting QR code as textual representation.
///
/// Number of repeated darkColorString/whiteSpaceString per module.
/// 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.
+ /// Bool that defines if quiet zones around the QR code shall be drawn
/// End of line separator. (Default: \n)
///
public string GetGraphic(int repeatPerModule, string darkColorString = "██", string whiteSpaceString = " ", bool drawQuietZones = true, string endOfLine = "\n")
{
+ if (repeatPerModule < 1)
+ throw new Exception("The repeatPerModule-parameter must be 1 or greater.");
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.
@@ -35,6 +38,7 @@ public string GetGraphic(int repeatPerModule, string darkColorString = "██",
/// Number of repeated darkColorString/whiteSpaceString per module.
/// 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.
+ /// Bool that defines if quiet zones around the QR code shall be drawn
///
public string[] GetLineByLineGraphic(int repeatPerModule, string darkColorString = "██", string whiteSpaceString = " ", bool drawQuietZones = true)
{
@@ -62,6 +66,61 @@ public string[] GetLineByLineGraphic(int repeatPerModule, string darkColorString
}
return qrCode.ToArray();
}
+
+ ///
+ /// Returns a strings that contains the resulting QR code as minified textual representation.
+ ///
+ /// Bool that defines if quiet zones around the QR code shall be drawn
+ /// If set to true, dark and light colors will be inverted
+ /// End of line separator. (Default: \n)
+ ///
+ public string GetGraphicSmall(bool drawQuietZones = true, bool invert = false, string endOfLine = "\n")
+ {
+ bool BLACK = true, WHITE = false;
+
+ var palette = new
+ {
+ WHITE_ALL = "\u2588",
+ WHITE_BLACK = "\u2580",
+ BLACK_WHITE = "\u2584",
+ BLACK_ALL = " ",
+ };
+
+ var moduleData = QrCodeData.ModuleMatrix;
+ var sbSize = (moduleData.Count + endOfLine.Length) * (int)Math.Ceiling(moduleData.Count / 2.0) - 1;
+ var lineBuilder = new StringBuilder(sbSize);
+
+ var quietZonesModifier = (drawQuietZones ? 0 : 8);
+ var quietZonesOffset = (int)(quietZonesModifier * 0.5);
+ var sideLength = (moduleData.Count - quietZonesModifier);
+
+ for (var row = 0; row < sideLength; row += 2)
+ {
+ for (var col = 0; col < sideLength; col++)
+ {
+ var current = moduleData[col + quietZonesOffset][row + quietZonesOffset] ^ invert;
+ var nextRowId = row + quietZonesOffset + 1;
+
+ // Set next to whitespace "color"
+ var next = BLACK;
+ // Fill next with value, if in data range
+ if (nextRowId < QrCodeData.ModuleMatrix.Count)
+ next = moduleData[col + quietZonesOffset][nextRowId] ^ invert;
+
+ if (current == WHITE && next == WHITE)
+ lineBuilder.Append(palette.WHITE_ALL);
+ else if (current == WHITE && next == BLACK)
+ lineBuilder.Append(palette.WHITE_BLACK);
+ else if (current == BLACK && next == WHITE)
+ lineBuilder.Append(palette.BLACK_WHITE);
+ else
+ lineBuilder.Append(palette.BLACK_ALL);
+ }
+ if (row + 2 < sideLength)
+ lineBuilder.Append(endOfLine);
+ }
+ return lineBuilder.ToString();
+ }
}
@@ -74,5 +133,13 @@ public static string GetQRCode(string plainText, int pixelsPerModule, string dar
using (var qrCode = new AsciiQRCode(qrCodeData))
return qrCode.GetGraphic(pixelsPerModule, darkColorString, whiteSpaceString, drawQuietZones, endOfLine);
}
+
+ public static string GetQRCode(string plainText, ECCLevel eccLevel, bool forceUtf8 = false, bool utf8BOM = false, EciMode eciMode = EciMode.Default, int requestedVersion = -1, string endOfLine = "\n", bool drawQuietZones = true, bool invert = 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.GetGraphicSmall(drawQuietZones, invert, endOfLine);
+ }
}
}
\ No newline at end of file
diff --git a/QRCoderTests/AsciiQRCodeRendererTests.cs b/QRCoderTests/AsciiQRCodeRendererTests.cs
index 7ac2656b..75152911 100644
--- a/QRCoderTests/AsciiQRCodeRendererTests.cs
+++ b/QRCoderTests/AsciiQRCodeRendererTests.cs
@@ -24,6 +24,62 @@ public void can_render_ascii_qrcode()
asciiCode.ShouldBe(targetCode);
}
+ [Fact]
+ [Category("QRRenderer/AsciiQRCode")]
+ public void can_render_small_ascii_qrcode()
+ {
+ var targetCode = "█████████████████████████████\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).GetGraphicSmall();
+
+ asciiCode.ShouldBe(targetCode);
+ }
+
+ [Fact]
+ [Category("QRRenderer/AsciiQRCode")]
+ public void can_render_small_ascii_qrcode_without_quietzones()
+ {
+ var targetCode = " ▄▄▄▄▄ █▀▄█ ▀█ ▄▄▄▄▄ \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).GetGraphicSmall(drawQuietZones: false);
+
+ asciiCode.ShouldBe(targetCode);
+ }
+
+ [Fact]
+ [Category("QRRenderer/AsciiQRCode")]
+ public void can_render_small_ascii_qrcode_inverted()
+ {
+ var targetCode = " \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).GetGraphicSmall(invert: true);
+
+ asciiCode.ShouldBe(targetCode);
+ }
+
+ [Fact]
+ [Category("QRRenderer/AsciiQRCode")]
+ public void can_render_small_ascii_qrcode_with_custom_eol()
+ {
+ var targetCode = "█████████████████████████████\r\n█████████████████████████████\r\n████ ▄▄▄▄▄ █▀▄█ ▀█ ▄▄▄▄▄ ████\r\n████ █ █ █▄█ █▄█ █ █ ████\r\n████ █▄▄▄█ █▄▀▀▀▀█ █▄▄▄█ ████\r\n████▄▄▄▄▄▄▄█ █ ▀▄█▄▄▄▄▄▄▄████\r\n████ ▄▄ █▄ ██▀ ▄▄▄▀ ▀ ▄▀████\r\n████▀█▄█ █▄ ▄ ▀▄▀ █▄█▄▄█████\r\n█████▄▄▄▄█▄▄▄████▀▀ █▄█▄████\r\n████ ▄▄▄▄▄ █▄▄█▄▄▀ ▀ ▄█▄▄████\r\n████ █ █ █ ▀ █▄▀█ ██▄█▄████\r\n████ █▄▄▄█ █ ▀▄▀ █▄█▄ █ ▄████\r\n████▄▄▄▄▄▄▄█▄▄▄█████▄█▄▄▄████\r\n█████████████████████████████\r\n▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀";
+
+ //Create QR code
+ var gen = new QRCodeGenerator();
+ var data = gen.CreateQrCode("A05", QRCodeGenerator.ECCLevel.Q);
+ var asciiCode = new AsciiQRCode(data).GetGraphicSmall(endOfLine: "\r\n");
+
+ asciiCode.ShouldBe(targetCode);
+ }
+
[Fact]
[Category("QRRenderer/AsciiQRCode")]
public void can_render_ascii_qrcode_without_quietzones()