Skip to content

Commit

Permalink
Merge pull request #495 from Shane32/support_base64_linux
Browse files Browse the repository at this point in the history
Support Base64QRCode on .NET6+ on Linux
  • Loading branch information
codebude committed Apr 25, 2024
2 parents c9c9f1b + e61e4bf commit 6ec439e
Show file tree
Hide file tree
Showing 5 changed files with 136 additions and 19 deletions.
71 changes: 55 additions & 16 deletions 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;

/// <summary>
/// Constructor without params to be used in COM Objects connections
/// </summary>
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)
Expand All @@ -43,25 +33,70 @@ 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);

Check warning on line 86 in QRCoder/Base64QRCode.cs

View workflow job for this annotation

GitHub Actions / build

This call site is reachable on all platforms. 'QRCode' is only supported on: 'windows'.
var base64 = string.Empty;
using (Bitmap bmp = qr.GetGraphic(pixelsPerModule, darkColor, lightColor, icon, iconSizePercent, iconBorderWidth, drawQuietZones))

Check warning on line 88 in QRCoder/Base64QRCode.cs

View workflow job for this annotation

GitHub Actions / build

This call site is reachable on all platforms. 'QRCode.GetGraphic(int, Color, Color, Bitmap, int, int, bool, Color?)' is only supported on: 'windows'.
{
base64 = BitmapToBase64(bmp, imgType);
}
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;
Expand All @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion QRCoder/QRCoder.csproj
Expand Up @@ -4,7 +4,7 @@
<TargetFrameworks>net35;net40;netstandard1.3;netstandard2.0;net5.0;net5.0-windows;net6.0;net6.0-windows</TargetFrameworks>
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
<DefineConstants Condition="'$(TargetFramework)' == 'net5.0-windows'">$(DefineConstants);NET5_0_WINDOWS</DefineConstants>
<DefineConstants Condition="'$(TargetFramework)' == 'net6.0-windows'">$(DefineConstants);NET6_0_WINDOWS</DefineConstants>
<DefineConstants Condition="'$(TargetFramework)' == 'net6.0-windows'">$(DefineConstants);NET6_0_WINDOWS</DefineConstants>
<CheckEolTargetFramework>false</CheckEolTargetFramework>
<DisableImplicitNuGetFallbackFolder>true</DisableImplicitNuGetFallbackFolder>
</PropertyGroup>
Expand Down
77 changes: 77 additions & 0 deletions 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
4 changes: 2 additions & 2 deletions QRCoderTests/Helpers/HelperFunctions.cs
Expand Up @@ -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;
Expand All @@ -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();
Expand Down
1 change: 1 addition & 0 deletions QRCoderTests/QRCoderTests.csproj
Expand Up @@ -4,6 +4,7 @@
<UseWindowsForms Condition="'$(TargetFramework)' == 'net5.0-windows'">true</UseWindowsForms>
<UseWPF Condition="'$(TargetFramework)' == 'net5.0-windows'">true</UseWPF>
<DefineConstants Condition="'$(TargetFramework)' == 'net5.0-windows'">$(DefineConstants);NET5_0_WINDOWS</DefineConstants>
<DefineConstants Condition="'$(TargetFramework)' == 'net6.0-windows'">$(DefineConstants);NET6_0_WINDOWS</DefineConstants>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
<CheckEolTargetFramework>false</CheckEolTargetFramework>
Expand Down

0 comments on commit 6ec439e

Please sign in to comment.