Skip to content

Commit

Permalink
Merge pull request #344 from codebude/feature/art-qrcode-refactoring
Browse files Browse the repository at this point in the history
Feature/art qrcode refactoring
  • Loading branch information
codebude authored Nov 12, 2021
2 parents 942cd35 + f8d9c83 commit 0c3bc02
Show file tree
Hide file tree
Showing 10 changed files with 361 additions and 93 deletions.
190 changes: 153 additions & 37 deletions QRCoder/ArtQRCode.cs

Large diffs are not rendered by default.

123 changes: 123 additions & 0 deletions QRCoderTests/ArtQRCodeRendererTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
#if !NETCOREAPP1_1

using Xunit;
using QRCoder;
using Shouldly;
using System.Drawing;
using QRCoderTests.Helpers.XUnitExtenstions;
using QRCoderTests.Helpers;

namespace QRCoderTests
{

public class ArtQRCodeRendererTests
{


[Fact]
[Category("QRRenderer/ArtQRCode")]
public void can_create_standard_qrcode_graphic()
{
var gen = new QRCodeGenerator();
var data = gen.CreateQrCode("This is a quick test! 123#?", QRCodeGenerator.ECCLevel.H);
var bmp = new ArtQRCode(data).GetGraphic(10);

var result = HelperFunctions.BitmapToHash(bmp);
#if NET35_OR_GREATER || NET40_OR_GREATER
result.ShouldBe("11ebdda91b9632d016798cb6de2f5339");
#else
result.ShouldBe("cb38c3156eaf13cdfba699bdafc3a84c");
#endif
}

[Fact]
[Category("QRRenderer/ArtQRCode")]
public void can_create_standard_qrcode_graphic_with_custom_finder()
{
var gen = new QRCodeGenerator();
var data = gen.CreateQrCode("This is a quick test! 123#?", QRCodeGenerator.ECCLevel.H);
var finder = new Bitmap(15, 15);
var bmp = new ArtQRCode(data).GetGraphic(10, Color.Black, Color.White, Color.Transparent, finderPatternImage: finder);

var result = HelperFunctions.BitmapToHash(bmp);
#if NET35_OR_GREATER || NET40_OR_GREATER
result.ShouldBe("c54a7389ae995abc838f0d228acc3bad");
#else
result.ShouldBe("1102c0c6f235eaf4c3ac639f82f17bfa");
#endif
}

[Fact]
[Category("QRRenderer/ArtQRCode")]
public void can_create_standard_qrcode_graphic_without_quietzone()
{
var gen = new QRCodeGenerator();
var data = gen.CreateQrCode("This is a quick test! 123#?", QRCodeGenerator.ECCLevel.H);
var bmp = new ArtQRCode(data).GetGraphic(10, Color.Black, Color.White, Color.Transparent, drawQuietZones: false);

var result = HelperFunctions.BitmapToHash(bmp);
#if NET35_OR_GREATER || NET40_OR_GREATER
result.ShouldBe("550f31b988ff12d5f8429ef19d9d5a0c");
#else
result.ShouldBe("632315c8695416fc82fe06a202688433");
#endif
}

[Fact]
[Category("QRRenderer/ArtQRCode")]
public void can_create_standard_qrcode_graphic_with_background()
{
var gen = new QRCodeGenerator();
var data = gen.CreateQrCode("This is a quick test! 123#?", QRCodeGenerator.ECCLevel.H);
var bmp = new ArtQRCode(data).GetGraphic((Bitmap)Image.FromFile(HelperFunctions.GetAssemblyPath() + "\\assets\\noun_software engineer_2909346.png"));
//Used logo is licensed under public domain. Ref.: https://thenounproject.com/Iconathon1/collection/redefining-women/?i=2909346

var result = HelperFunctions.BitmapToHash(bmp);

#if NET35_OR_GREATER || NET40_OR_GREATER
result.ShouldBe("2caa9c0ee8fcb4a93841debb58cf41bc");
#else
result.ShouldBe("bbea08507282773175cfe7b52f0ddae4");
#endif
}

[Fact]
[Category("QRRenderer/ArtQRCode")]
public void should_throw_pixelfactor_oor_exception()
{
var gen = new QRCodeGenerator();
var data = gen.CreateQrCode("This is a quick test! 123#?", QRCodeGenerator.ECCLevel.H);
var aCode = new ArtQRCode(data);

var exception = Record.Exception(() => aCode.GetGraphic(10, Color.Black, Color.White, Color.Transparent, pixelSizeFactor: 2));
Assert.NotNull(exception);
Assert.IsType<System.Exception>(exception);
exception.Message.ShouldBe("The parameter pixelSize must be between 0 and 1. (0-100%)");
}

[Fact]
[Category("QRRenderer/ArtQRCode")]
public void can_instantate_parameterless()
{
var asciiCode = new ArtQRCode();
asciiCode.ShouldNotBeNull();
asciiCode.ShouldBeOfType<ArtQRCode>();
}

[Fact]
[Category("QRRenderer/ArtQRCode")]
public void can_render_artqrcode_from_helper()
{
//Create QR code
var bmp = ArtQRCodeHelper.GetQRCode("A", 10, Color.Black, Color.White, Color.Transparent, QRCodeGenerator.ECCLevel.L);

var result = HelperFunctions.BitmapToHash(bmp);
#if NET35_OR_GREATER || NET40_OR_GREATER
result.ShouldBe("fea51114bc4ff893542a1c0574c82a07");
#else
result.ShouldBe("57ecaa9bdeadcdcbeac8a19d734907ff");
#endif
}
}
}
#endif
6 changes: 2 additions & 4 deletions QRCoderTests/AsciiQRCodeRendererTests.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using Xunit;
using QRCoder;
using Shouldly;
using QRCoderTests.XUnitExtenstions;
using QRCoderTests.Helpers.XUnitExtenstions;


namespace QRCoderTests
Expand Down Expand Up @@ -67,9 +67,7 @@ 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);
//Create QR code
var asciiCode = AsciiQRCodeHelper.GetQRCode("A", 2, "X", " ", QRCodeGenerator.ECCLevel.Q);
asciiCode.ShouldBe(targetCode);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#endif
using Xunit.Sdk;

namespace QRCoderTests.XUnitExtenstions
namespace QRCoderTests.Helpers.XUnitExtenstions
{
#if NET35 || NET452
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
Expand Down
46 changes: 46 additions & 0 deletions QRCoderTests/Helpers/HelperFunctions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Security.Cryptography;
#if !NETCOREAPP1_1
using System.Drawing;
#endif

namespace QRCoderTests.Helpers
{
public static class HelperFunctions
{

#if !NETCOREAPP1_1
public static string GetAssemblyPath()
{
return
#if NET5_0
AppDomain.CurrentDomain.BaseDirectory;
#else
Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().CodeBase).Replace("file:\\", "");
#endif
}
#endif


#if !NETCOREAPP1_1
public static string BitmapToHash(Bitmap bmp)
{
byte[] imgBytes = null;
using (var ms = new MemoryStream())
{
bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
imgBytes = ms.ToArray();
ms.Dispose();
}
var md5 = new MD5CryptoServiceProvider();
var hash = md5.ComputeHash(imgBytes);
return BitConverter.ToString(hash).Replace("-", "").ToLower();
}
#endif

}
}
2 changes: 1 addition & 1 deletion QRCoderTests/PayloadGeneratorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
using Shouldly;
using System.Globalization;
using System.Threading;
using QRCoderTests.XUnitExtenstions;
using QRCoderTests.Helpers.XUnitExtenstions;
using static QRCoder.PayloadGenerator.BezahlCode;
using static QRCoder.PayloadGenerator.SwissQrCode.Reference;
using System.Reflection;
Expand Down
56 changes: 20 additions & 36 deletions QRCoderTests/QRCodeRendererTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
using Xunit;
using QRCoder;
using Shouldly;
using QRCoderTests.XUnitExtenstions;
using System.IO;
using System.Security.Cryptography;
using QRCoderTests.Helpers.XUnitExtenstions;
using QRCoderTests.Helpers;
#if !NETCOREAPP1_1
using System.Drawing;
#endif
Expand All @@ -24,31 +25,14 @@ public void can_create_standard_qrcode_graphic()
var data = gen.CreateQrCode("This is a quick test! 123#?", QRCodeGenerator.ECCLevel.H);
var bmp = new QRCode(data).GetGraphic(10);

var ms = new MemoryStream();
bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Gif);
var imgBytes = ms.ToArray();
var md5 = new MD5CryptoServiceProvider();
var hash = md5.ComputeHash(imgBytes);
var result = BitConverter.ToString(hash).Replace("-", "").ToLower();
ms.Dispose();

result.ShouldBe("a76c8a72e95df3368717663c6be41b3e");
var result = HelperFunctions.BitmapToHash(bmp);
result.ShouldBe("e8c61b8f0455924fe08ba68686d0d296");
}
#endif


#if !NETCOREAPP1_1 && !NETCOREAPP2_0

private string GetAssemblyPath()
{
return
#if NET5_0
AppDomain.CurrentDomain.BaseDirectory;
#else
Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().CodeBase).Replace("file:\\", "");
#endif
}

[Fact]
[Category("QRRenderer/QRCode")]
public void can_create_qrcode_with_transparent_logo_graphic()
Expand All @@ -57,15 +41,15 @@ public void can_create_qrcode_with_transparent_logo_graphic()
var gen = new QRCodeGenerator();
var data = gen.CreateQrCode("This is a quick test! 123#?", QRCodeGenerator.ECCLevel.H);

var bmp = new QRCode(data).GetGraphic(10, Color.Black, Color.Transparent, icon: (Bitmap)Image.FromFile(GetAssemblyPath() + "\\assets\\noun_software engineer_2909346.png"));
var bmp = new QRCode(data).GetGraphic(10, Color.Black, Color.Transparent, icon: (Bitmap)Image.FromFile(HelperFunctions.GetAssemblyPath() + "\\assets\\noun_software engineer_2909346.png"));
//Used logo is licensed under public domain. Ref.: https://thenounproject.com/Iconathon1/collection/redefining-women/?i=2909346

var imgBytes = PixelsToAveragedByteArray(bmp);
var md5 = new MD5CryptoServiceProvider();
var hash = md5.ComputeHash(imgBytes);
var result = BitConverter.ToString(hash).Replace("-", "").ToLower();

result.ShouldBe("33c250bf306b7cbbd3dd71b6029b8784");
var result = HelperFunctions.BitmapToHash(bmp);
#if NET35_OR_GREATER || NET40_OR_GREATER
result.ShouldBe("ee65d96c3013f6032b561cc768251eef");
#else
result.ShouldBe("150f8fc7dae4487ba2887d2b2bea1c25");
#endif
}

[Fact]
Expand All @@ -75,18 +59,18 @@ public void can_create_qrcode_with_non_transparent_logo_graphic()
//Create QR code
var gen = new QRCodeGenerator();
var data = gen.CreateQrCode("This is a quick test! 123#?", QRCodeGenerator.ECCLevel.H);
var bmp = new QRCode(data).GetGraphic(10, Color.Black, Color.White, icon: (Bitmap)Bitmap.FromFile(GetAssemblyPath() + "\\assets\\noun_software engineer_2909346.png"));
var bmp = new QRCode(data).GetGraphic(10, Color.Black, Color.White, icon: (Bitmap)Bitmap.FromFile(HelperFunctions.GetAssemblyPath() + "\\assets\\noun_software engineer_2909346.png"));
//Used logo is licensed under public domain. Ref.: https://thenounproject.com/Iconathon1/collection/redefining-women/?i=2909346

var imgBytes = PixelsToAveragedByteArray(bmp);
var md5 = new MD5CryptoServiceProvider();
var hash = md5.ComputeHash(imgBytes);
var result = BitConverter.ToString(hash).Replace("-", "").ToLower();

result.ShouldBe("33c250bf306b7cbbd3dd71b6029b8784");
var result = HelperFunctions.BitmapToHash(bmp);
#if NET35_OR_GREATER || NET40_OR_GREATER
result.ShouldBe("1d718f06f904af4a46748f02af2d4eec");
#else
result.ShouldBe("c46a7ec51bf978d7a882059c322ca69d");
#endif
}


/*
private static byte[] PixelsToAveragedByteArray(Bitmap bmp)
{
//Re-color
Expand All @@ -107,7 +91,7 @@ private static byte[] PixelsToAveragedByteArray(Bitmap bmp)
}
return bytes.ToArray();
}

*/
#endif
}
}
2 changes: 1 addition & 1 deletion QRCoderTests/QRGeneratorTests.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using QRCoder;
using QRCoderTests.XUnitExtenstions;
using QRCoderTests.Helpers.XUnitExtenstions;
using Shouldly;
using System.Collections.Generic;
using System.Reflection;
Expand Down
2 changes: 1 addition & 1 deletion QRCoderTests/SvgQRCodeRendererTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
using Xunit;
using QRCoder;
using Shouldly;
using QRCoderTests.XUnitExtenstions;
using QRCoderTests.Helpers.XUnitExtenstions;
using System.IO;
using System.Security.Cryptography;
#if !NETCOREAPP1_1
Expand Down
25 changes: 13 additions & 12 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,18 +73,19 @@ There are a plenty of other options. So feel free to read more on that in our wi

Besides the normal QRCode class (which is shown in the example above) for creating QR codes in Bitmap format, there are some more QR code rendering classes, each for another special purpose.

* [QRCode<sup>*</sup>](https://github.com/codebude/QRCoder/wiki/Advanced-usage---QR-Code-renderers#21-qrcode-renderer-in-detail)
* [AsciiQRCode<sup></sup>](https://github.com/codebude/QRCoder/wiki/Advanced-usage---QR-Code-renderers#22-asciiqrcode-renderer-in-detail)
* [Base64QRCode<sup>*</sup>](https://github.com/codebude/QRCoder/wiki/Advanced-usage---QR-Code-renderers#23-base64qrcode-renderer-in-detail)
* [BitmapByteQRCode<sup></sup>](https://github.com/codebude/QRCoder/wiki/Advanced-usage---QR-Code-renderers#24-bitmapbyteqrcode-renderer-in-detail)
* [PdfByteQRCode<sup>*</sup>](https://github.com/codebude/QRCoder/wiki/Advanced-usage---QR-Code-renderers#210-pdfbyteqrcode-renderer-in-detail)
* [PngByteQRCode<sup></sup>](https://github.com/codebude/QRCoder/wiki/Advanced-usage---QR-Code-renderers#25-pngbyteqrcode-renderer-in-detail)
* [PostscriptQRCode<sup>*</sup>](https://github.com/codebude/QRCoder/wiki/Advanced-usage---QR-Code-renderers#29-postscriptqrcode-renderer-in-detail)
* [SvgQRCode<sup>*</sup>](https://github.com/codebude/QRCoder/wiki/Advanced-usage---QR-Code-renderers#26-svgqrcode-renderer-in-detail)
* [UnityQRCode<sup>**</sup>](https://github.com/codebude/QRCoder/wiki/Advanced-usage---QR-Code-renderers#27-unityqrcode-renderer-in-detail)
* [XamlQRCode<sup>*</sup>](https://github.com/codebude/QRCoder/wiki/Advanced-usage---QR-Code-renderers#28-xamlqrcode-renderer-in-detail)

*(&ast;) - These classes are only available in the .NET Framework/.NET Standard version. If you use the PCL version (e.g. for Universal apps), you have to use either BitmapByteQRCode or PngByteQRCode classes.*
* [QRCode](https://github.com/codebude/QRCoder/wiki/Advanced-usage---QR-Code-renderers#21-qrcode-renderer-in-detail)
* [ArtQRCode](https://github.com/codebude/QRCoder/wiki/Advanced-usage---QR-Code-renderers#211-artqrcode-renderer-in-detail)
* [AsciiQRCode](https://github.com/codebude/QRCoder/wiki/Advanced-usage---QR-Code-renderers#22-asciiqrcode-renderer-in-detail)
* [Base64QRCode](https://github.com/codebude/QRCoder/wiki/Advanced-usage---QR-Code-renderers#23-base64qrcode-renderer-in-detail)
* [BitmapByteQRCode](https://github.com/codebude/QRCoder/wiki/Advanced-usage---QR-Code-renderers#24-bitmapbyteqrcode-renderer-in-detail)
* [PdfByteQRCode](https://github.com/codebude/QRCoder/wiki/Advanced-usage---QR-Code-renderers#210-pdfbyteqrcode-renderer-in-detail)
* [PngByteQRCode](https://github.com/codebude/QRCoder/wiki/Advanced-usage---QR-Code-renderers#25-pngbyteqrcode-renderer-in-detail)
* [PostscriptQRCode](https://github.com/codebude/QRCoder/wiki/Advanced-usage---QR-Code-renderers#29-postscriptqrcode-renderer-in-detail)
* [SvgQRCode](https://github.com/codebude/QRCoder/wiki/Advanced-usage---QR-Code-renderers#26-svgqrcode-renderer-in-detail)
* [UnityQRCode<sup>*</sup>](https://github.com/codebude/QRCoder/wiki/Advanced-usage---QR-Code-renderers#27-unityqrcode-renderer-in-detail)
* [XamlQRCode](https://github.com/codebude/QRCoder/wiki/Advanced-usage---QR-Code-renderers#28-xamlqrcode-renderer-in-detail)

*Note: Please be aware that not all renderers are available on all target frameworks. Please check the [compatibility table](https://github.com/codebude/QRCoder/wiki/Advanced-usage---QR-Code-renderers#2-overview-of-the-different-renderers) in our wiki, to see if a specific renderer is available on your favourite target framework.*
*(&ast;&ast;) - This class is hosted in an own package ([QRCoder.Unity](https://github.com/codebude/QRCoder.Unity)).*


Expand Down

0 comments on commit 0c3bc02

Please sign in to comment.