diff --git a/QRCoder/Base64QRCode.cs b/QRCoder/Base64QRCode.cs index 539af073..0c9d119d 100644 --- a/QRCoder/Base64QRCode.cs +++ b/QRCoder/Base64QRCode.cs @@ -1,33 +1,23 @@ -#if NETFRAMEWORK || NETSTANDARD2_0 || NET5_0 || NET6_0_WINDOWS +#if !NETSTANDARD1_3 using System; using System.Drawing; using System.Drawing.Imaging; using System.IO; +using System.Runtime.InteropServices; using static QRCoder.Base64QRCode; using static QRCoder.QRCodeGenerator; namespace QRCoder { -#if NET6_0_WINDOWS - [System.Runtime.Versioning.SupportedOSPlatform("windows")] -#endif public class Base64QRCode : AbstractQRCode, IDisposable { - private QRCode qr; - /// /// Constructor without params to be used in COM Objects connections /// public Base64QRCode() { - qr = new QRCode(); } public Base64QRCode(QRCodeData data) : base(data) { - qr = new QRCode(data); - } - - public override void SetQRCodeData(QRCodeData data) { - this.qr.SetQRCodeData(data); } public string GetGraphic(int pixelsPerModule) @@ -43,16 +33,57 @@ public string GetGraphic(int pixelsPerModule, string darkColorHtmlHex, string li public string GetGraphic(int pixelsPerModule, Color darkColor, Color lightColor, bool drawQuietZones = true, ImageType imgType = ImageType.Png) { + if (imgType == ImageType.Png) + { + var pngCoder = new PngByteQRCode(QrCodeData); + + byte[] pngData; + if (darkColor == Color.Black && lightColor == Color.White) + { + pngData = pngCoder.GetGraphic(pixelsPerModule, drawQuietZones); + } + else + { + byte[] darkColorBytes; + byte[] lightColorBytes; + if (darkColor.A != 255 || lightColor.A != 255) + { + darkColorBytes = new byte[] { darkColor.R, darkColor.G, darkColor.B, darkColor.A }; + lightColorBytes = new byte[] { lightColor.R, lightColor.G, lightColor.B, lightColor.A }; + } + else + { + darkColorBytes = new byte[] { darkColor.R, darkColor.G, darkColor.B }; + lightColorBytes = new byte[] { lightColor.R, lightColor.G, lightColor.B }; + } + pngData = pngCoder.GetGraphic(pixelsPerModule, darkColorBytes, lightColorBytes, drawQuietZones); + } + + return Convert.ToBase64String(pngData, Base64FormattingOptions.None); + } + +#if NETFRAMEWORK || NETSTANDARD2_0 || NET5_0 || NET6_0_WINDOWS +#pragma warning disable CA1416 // Validate platform compatibility + var qr = new QRCode(QrCodeData); var base64 = string.Empty; using (Bitmap bmp = qr.GetGraphic(pixelsPerModule, darkColor, lightColor, drawQuietZones)) { base64 = BitmapToBase64(bmp, imgType); } return base64; +#pragma warning restore CA1416 // Validate platform compatibility +#else + throw new PlatformNotSupportedException("Only the PNG image type is supported on this platform."); +#endif } +#if NETFRAMEWORK || NETSTANDARD2_0 || NET5_0 || NET6_0_WINDOWS +#if NET6_0_OR_GREATER + [System.Runtime.Versioning.SupportedOSPlatform("windows")] +#endif public string GetGraphic(int pixelsPerModule, Color darkColor, Color lightColor, Bitmap icon, int iconSizePercent = 15, int iconBorderWidth = 6, bool drawQuietZones = true, ImageType imgType = ImageType.Png) { + var qr = new QRCode(QrCodeData); var base64 = string.Empty; using (Bitmap bmp = qr.GetGraphic(pixelsPerModule, darkColor, lightColor, icon, iconSizePercent, iconBorderWidth, drawQuietZones)) { @@ -60,8 +91,12 @@ public string GetGraphic(int pixelsPerModule, Color darkColor, Color lightColor, } return base64; } +#endif - +#if NETFRAMEWORK || NETSTANDARD2_0 || NET5_0 || NET6_0_WINDOWS +#if NET6_0_OR_GREATER + [System.Runtime.Versioning.SupportedOSPlatform("windows")] +#endif private string BitmapToBase64(Bitmap bmp, ImageType imgType) { var base64 = string.Empty; @@ -87,19 +122,23 @@ private string BitmapToBase64(Bitmap bmp, ImageType imgType) } return base64; } +#endif public enum ImageType { +#if NET6_0_OR_GREATER + [System.Runtime.Versioning.SupportedOSPlatform("windows")] +#endif Gif, +#if NET6_0_OR_GREATER + [System.Runtime.Versioning.SupportedOSPlatform("windows")] +#endif Jpeg, Png } } -#if NET6_0_WINDOWS - [System.Runtime.Versioning.SupportedOSPlatform("windows")] -#endif public static class Base64QRCodeHelper { public static string GetQRCode(string plainText, int pixelsPerModule, string darkColorHtmlHex, string lightColorHtmlHex, ECCLevel eccLevel, bool forceUtf8 = false, bool utf8BOM = false, EciMode eciMode = EciMode.Default, int requestedVersion = -1, bool drawQuietZones = true, ImageType imgType = ImageType.Png) diff --git a/QRCoder/QRCoder.csproj b/QRCoder/QRCoder.csproj index d67a7989..9b37e4c6 100644 --- a/QRCoder/QRCoder.csproj +++ b/QRCoder/QRCoder.csproj @@ -4,7 +4,7 @@ net35;net40;netstandard1.3;netstandard2.0;net5.0;net5.0-windows;net6.0;net6.0-windows false $(DefineConstants);NET5_0_WINDOWS - $(DefineConstants);NET6_0_WINDOWS + $(DefineConstants);NET6_0_WINDOWS false true diff --git a/QRCoderTests/Base64QRCodeRendererTests.cs b/QRCoderTests/Base64QRCodeRendererTests.cs new file mode 100644 index 00000000..58011fba --- /dev/null +++ b/QRCoderTests/Base64QRCodeRendererTests.cs @@ -0,0 +1,77 @@ +#if !NETCOREAPP1_1 +using QRCoder; +using QRCoderTests.Helpers.XUnitExtenstions; +using Shouldly; +using System; +using System.Drawing; +using System.IO; +using Xunit; + +namespace QRCoderTests +{ + public class Base64QRCodeRendererTests + { + private readonly QRCodeData data; + + public Base64QRCodeRendererTests() + { + var gen = new QRCodeGenerator(); + data = gen.CreateQrCode("This is a quick test! 123#?", QRCodeGenerator.ECCLevel.L); + } + + [Fact] + [Category("QRRenderer/Base64QRCode")] + public void can_render_base64_qrcode_blackwhite() + { + var pngCodeGfx = new PngByteQRCode(data).GetGraphic(5); + var base64QRCode = new Base64QRCode(data).GetGraphic(5); + base64QRCode.ShouldBe(Convert.ToBase64String(pngCodeGfx)); + } + + [Fact] + [Category("QRRenderer/Base64QRCode")] + public void can_render_base64_qrcode_noquietzones() + { + var pngCodeGfx = new PngByteQRCode(data).GetGraphic(5, false); + var base64QRCode = new Base64QRCode(data).GetGraphic(5, Color.Black, Color.White, false); + base64QRCode.ShouldBe(Convert.ToBase64String(pngCodeGfx)); + } + + [Fact] + [Category("QRRenderer/Base64QRCode")] + public void can_render_base64_qrcode_color() + { + var pngCodeGfx = new PngByteQRCode(data).GetGraphic(5, new byte[] { 255, 0, 0 }, new byte[] { 0, 0, 255 }); + var base64QRCode = new Base64QRCode(data).GetGraphic(5, Color.Red, Color.Blue); + base64QRCode.ShouldBe(Convert.ToBase64String(pngCodeGfx)); + } + + [Fact] + [Category("QRRenderer/Base64QRCode")] + public void can_render_base64_qrcode_transparent() + { + var pngCodeGfx = new PngByteQRCode(data).GetGraphic(5, new byte[] { 0, 255, 0, 255 }, new byte[] { 255, 255, 255, 0 }); + var base64QRCode = new Base64QRCode(data).GetGraphic(5, Color.Lime, Color.Transparent); + base64QRCode.ShouldBe(Convert.ToBase64String(pngCodeGfx)); + } + +#if NETFRAMEWORK || NETCOREAPP2_0 || NET5_0 || NET6_0_WINDOWS + [Fact] + [Category("QRRenderer/Base64QRCode")] + public void can_render_base64_qrcode_jpeg() + { + var ms = new MemoryStream(); + using (var bitmap = new QRCode(data).GetGraphic(5, Color.Black, Color.White, true)) + { + bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg); + } + ms.Position = 0; + var jpgString = Convert.ToBase64String(ms.ToArray()); + var base64QRCode = new Base64QRCode(data).GetGraphic(5, Color.Black, Color.White, true, Base64QRCode.ImageType.Jpeg); + base64QRCode.ShouldBe(jpgString); + } +#endif + } +} + +#endif diff --git a/QRCoderTests/Helpers/HelperFunctions.cs b/QRCoderTests/Helpers/HelperFunctions.cs index 5fd9aa13..1f337865 100644 --- a/QRCoderTests/Helpers/HelperFunctions.cs +++ b/QRCoderTests/Helpers/HelperFunctions.cs @@ -5,7 +5,7 @@ #if !NETCOREAPP1_1 using System.Drawing; #endif -#if NETFRAMEWORK || NET5_0_WINDOWS +#if NETFRAMEWORK || NET5_0_WINDOWS || NET6_0_WINDOWS using SW = System.Windows; using System.Windows.Media; using System.Windows.Media.Imaging; @@ -17,7 +17,7 @@ namespace QRCoderTests.Helpers public static class HelperFunctions { -#if NETFRAMEWORK || NET5_0_WINDOWS +#if NETFRAMEWORK || NET5_0_WINDOWS || NET6_0_WINDOWS public static BitmapSource ToBitmapSource(DrawingImage source) { DrawingVisual drawingVisual = new DrawingVisual(); diff --git a/QRCoderTests/QRCoderTests.csproj b/QRCoderTests/QRCoderTests.csproj index 3f1aa274..e5c01ba9 100644 --- a/QRCoderTests/QRCoderTests.csproj +++ b/QRCoderTests/QRCoderTests.csproj @@ -4,6 +4,7 @@ true true $(DefineConstants);NET5_0_WINDOWS + $(DefineConstants);NET6_0_WINDOWS false true false