Skip to content

Commit 7524541

Browse files
committed
Support Base64QRCode on Linux
1 parent 56ace43 commit 7524541

File tree

5 files changed

+172
-26
lines changed

5 files changed

+172
-26
lines changed

QRCoder/Base64QRCode.cs

Lines changed: 81 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,25 @@
1-
#if NETFRAMEWORK || NETSTANDARD2_0 || NET5_0 || NET6_0_WINDOWS
1+
#if !NETSTANDARD1_3
22
using System;
33
using System.Drawing;
44
using System.Drawing.Imaging;
55
using System.IO;
6+
using System.Runtime.InteropServices;
67
using static QRCoder.Base64QRCode;
78
using static QRCoder.QRCodeGenerator;
89

910
namespace QRCoder
1011
{
11-
#if NET6_0_WINDOWS
12-
[System.Runtime.Versioning.SupportedOSPlatform("windows")]
13-
#endif
1412
public class Base64QRCode : AbstractQRCode, IDisposable
1513
{
16-
private QRCode qr;
17-
1814
/// <summary>
1915
/// Constructor without params to be used in COM Objects connections
2016
/// </summary>
21-
public Base64QRCode() {
22-
qr = new QRCode();
23-
}
24-
25-
public Base64QRCode(QRCodeData data) : base(data) {
26-
qr = new QRCode(data);
17+
public Base64QRCode()
18+
{
2719
}
2820

29-
public override void SetQRCodeData(QRCodeData data) {
30-
this.qr.SetQRCodeData(data);
21+
public Base64QRCode(QRCodeData data) : base(data)
22+
{
3123
}
3224

3325
public string GetGraphic(int pixelsPerModule)
@@ -43,30 +35,92 @@ public string GetGraphic(int pixelsPerModule, string darkColorHtmlHex, string li
4335

4436
public string GetGraphic(int pixelsPerModule, Color darkColor, Color lightColor, bool drawQuietZones = true, ImageType imgType = ImageType.Png)
4537
{
46-
var base64 = string.Empty;
47-
using (Bitmap bmp = qr.GetGraphic(pixelsPerModule, darkColor, lightColor, drawQuietZones))
38+
if (imgType == ImageType.Png)
4839
{
49-
base64 = BitmapToBase64(bmp, imgType);
40+
var pngCoder = new PngByteQRCode(QrCodeData);
41+
42+
byte[] pngData;
43+
if (darkColor == Color.Black && lightColor == Color.White)
44+
{
45+
pngData = pngCoder.GetGraphic(pixelsPerModule, drawQuietZones);
46+
}
47+
else
48+
{
49+
byte[] darkColorBytes;
50+
byte[] lightColorBytes;
51+
if (darkColor.A != 255 || lightColor.A != 255)
52+
{
53+
darkColorBytes = new byte[] { darkColor.R, darkColor.G, darkColor.B, darkColor.A };
54+
lightColorBytes = new byte[] { lightColor.R, lightColor.G, lightColor.B, lightColor.A };
55+
}
56+
else
57+
{
58+
darkColorBytes = new byte[] { darkColor.R, darkColor.G, darkColor.B };
59+
lightColorBytes = new byte[] { lightColor.R, lightColor.G, lightColor.B };
60+
}
61+
pngData = pngCoder.GetGraphic(pixelsPerModule, darkColorBytes, lightColorBytes, drawQuietZones);
62+
}
63+
64+
return Convert.ToBase64String(pngData, Base64FormattingOptions.None);
65+
66+
byte[] ToRgba(Color color)
67+
{
68+
return new byte[] { color.R, color.G, color.B, color.A };
69+
}
5070
}
51-
return base64;
71+
72+
#if NETFRAMEWORK || NETSTANDARD2_0 || NET5_0 || NET6_0_WINDOWS
73+
if (
74+
#if NET6_0_OR_GREATER
75+
RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
76+
#else
77+
true
78+
#endif
79+
)
80+
{
81+
var qr = new QRCode(QrCodeData);
82+
var base64 = string.Empty;
83+
using (Bitmap bmp = qr.GetGraphic(pixelsPerModule, darkColor, lightColor, drawQuietZones))
84+
{
85+
base64 = BitmapToBase64(bmp, imgType);
86+
}
87+
return base64;
88+
}
89+
else
90+
{
91+
throw new PlatformNotSupportedException("The specified image type is not supported on this platform.");
92+
}
93+
#else
94+
throw new PlatformNotSupportedException("The specified image type is not supported on this platform.");
95+
#endif
5296
}
5397

98+
#if NETFRAMEWORK || NETSTANDARD2_0 || NET5_0 || NET6_0_WINDOWS
99+
#if NET6_0_WINDOWS
100+
[System.Runtime.Versioning.SupportedOSPlatform("windows")]
101+
#endif
54102
public string GetGraphic(int pixelsPerModule, Color darkColor, Color lightColor, Bitmap icon, int iconSizePercent = 15, int iconBorderWidth = 6, bool drawQuietZones = true, ImageType imgType = ImageType.Png)
55103
{
104+
var qr = new QRCode(QrCodeData);
56105
var base64 = string.Empty;
57106
using (Bitmap bmp = qr.GetGraphic(pixelsPerModule, darkColor, lightColor, icon, iconSizePercent, iconBorderWidth, drawQuietZones))
58107
{
59108
base64 = BitmapToBase64(bmp, imgType);
60109
}
61110
return base64;
62111
}
112+
#endif
63113

64-
114+
#if NETFRAMEWORK || NETSTANDARD2_0 || NET5_0 || NET6_0_WINDOWS
115+
#if NET6_0_WINDOWS
116+
[System.Runtime.Versioning.SupportedOSPlatform("windows")]
117+
#endif
65118
private string BitmapToBase64(Bitmap bmp, ImageType imgType)
66119
{
67120
var base64 = string.Empty;
68121
ImageFormat iFormat;
69-
switch (imgType) {
122+
switch (imgType)
123+
{
70124
case ImageType.Png:
71125
iFormat = ImageFormat.Png;
72126
break;
@@ -87,19 +141,23 @@ private string BitmapToBase64(Bitmap bmp, ImageType imgType)
87141
}
88142
return base64;
89143
}
144+
#endif
90145

91146
public enum ImageType
92147
{
148+
#if NET6_0_WINDOWS
149+
[System.Runtime.Versioning.SupportedOSPlatform("windows")]
150+
#endif
93151
Gif,
152+
#if NET6_0_WINDOWS
153+
[System.Runtime.Versioning.SupportedOSPlatform("windows")]
154+
#endif
94155
Jpeg,
95156
Png
96157
}
97158

98159
}
99160

100-
#if NET6_0_WINDOWS
101-
[System.Runtime.Versioning.SupportedOSPlatform("windows")]
102-
#endif
103161
public static class Base64QRCodeHelper
104162
{
105163
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)

QRCoder/QRCoder.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<TargetFrameworks>net35;net40;netstandard1.3;netstandard2.0;net5.0;net5.0-windows;net6.0;net6.0-windows</TargetFrameworks>
55
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
66
<DefineConstants Condition="'$(TargetFramework)' == 'net5.0-windows'">$(DefineConstants);NET5_0_WINDOWS</DefineConstants>
7-
<DefineConstants Condition="'$(TargetFramework)' == 'net6.0-windows'">$(DefineConstants);NET6_0_WINDOWS</DefineConstants>
7+
<DefineConstants Condition="'$(TargetFramework)' == 'net6.0-windows'">$(DefineConstants);NET6_0_WINDOWS</DefineConstants>
88
<CheckEolTargetFramework>false</CheckEolTargetFramework>
99
<DisableImplicitNuGetFallbackFolder>true</DisableImplicitNuGetFallbackFolder>
1010
</PropertyGroup>
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
#if !NETCOREAPP1_1
2+
using Xunit;
3+
using QRCoder;
4+
using Shouldly;
5+
using QRCoderTests.Helpers.XUnitExtenstions;
6+
using QRCoderTests.Helpers;
7+
using System;
8+
9+
using System.Drawing;
10+
using System.IO;
11+
using System.Security.Policy;
12+
13+
namespace QRCoderTests
14+
{
15+
/****************************************************************************************************
16+
* Note: Test cases compare the outcome visually even if it's slower than a byte-wise compare.
17+
* This is necessary, because the Deflate implementation differs on the different target
18+
* platforms and thus the outcome, even if visually identical, differs. Thus only a visual
19+
* test method makes sense. In addition bytewise differences shouldn't be important, if the
20+
* visual outcome is identical and thus the qr code is identical/scannable.
21+
****************************************************************************************************/
22+
public class Base64QRCodeRendererTests
23+
{
24+
private readonly QRCodeData data;
25+
26+
public Base64QRCodeRendererTests()
27+
{
28+
var gen = new QRCodeGenerator();
29+
data = gen.CreateQrCode("This is a quick test! 123#?", QRCodeGenerator.ECCLevel.L);
30+
}
31+
32+
[Fact]
33+
[Category("QRRenderer/Base64QRCode")]
34+
public void can_render_base64_qrcode_blackwhite()
35+
{
36+
var pngCodeGfx = new PngByteQRCode(data).GetGraphic(5);
37+
var base64QRCode = new Base64QRCode(data).GetGraphic(5);
38+
base64QRCode.ShouldBe(Convert.ToBase64String(pngCodeGfx));
39+
}
40+
41+
[Fact]
42+
[Category("QRRenderer/Base64QRCode")]
43+
public void can_render_base64_qrcode_noquietzones()
44+
{
45+
var pngCodeGfx = new PngByteQRCode(data).GetGraphic(5, false);
46+
var base64QRCode = new Base64QRCode(data).GetGraphic(5, Color.Black, Color.White, false);
47+
base64QRCode.ShouldBe(Convert.ToBase64String(pngCodeGfx));
48+
}
49+
50+
[Fact]
51+
[Category("QRRenderer/Base64QRCode")]
52+
public void can_render_base64_qrcode_color()
53+
{
54+
var pngCodeGfx = new PngByteQRCode(data).GetGraphic(5, new byte[] { 255, 0, 0 }, new byte[] { 0, 0, 255 });
55+
var base64QRCode = new Base64QRCode(data).GetGraphic(5, Color.Red, Color.Blue);
56+
base64QRCode.ShouldBe(Convert.ToBase64String(pngCodeGfx));
57+
}
58+
59+
[Fact]
60+
[Category("QRRenderer/Base64QRCode")]
61+
public void can_render_base64_qrcode_transparent()
62+
{
63+
var pngCodeGfx = new PngByteQRCode(data).GetGraphic(5, new byte[] { 0, 255, 0, 255 }, new byte[] { 255, 255, 255, 0 });
64+
var base64QRCode = new Base64QRCode(data).GetGraphic(5, Color.Lime, Color.Transparent);
65+
base64QRCode.ShouldBe(Convert.ToBase64String(pngCodeGfx));
66+
}
67+
68+
#if NETFRAMEWORK || NETCOREAPP2_0 || NET5_0 || NET6_0_WINDOWS
69+
[Fact]
70+
[Category("QRRenderer/Base64QRCode")]
71+
public void can_render_base64_qrcode_jpeg()
72+
{
73+
var ms = new MemoryStream();
74+
using (var bitmap = new QRCode(data).GetGraphic(5, Color.Black, Color.White, true))
75+
{
76+
bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
77+
}
78+
ms.Position = 0;
79+
var jpgString = Convert.ToBase64String(ms.ToArray());
80+
var base64QRCode = new Base64QRCode(data).GetGraphic(5, Color.Black, Color.White, true, Base64QRCode.ImageType.Jpeg);
81+
base64QRCode.ShouldBe(jpgString);
82+
}
83+
#endif
84+
}
85+
}
86+
87+
#endif

QRCoderTests/Helpers/HelperFunctions.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
#if !NETCOREAPP1_1
66
using System.Drawing;
77
#endif
8-
#if NETFRAMEWORK || NET5_0_WINDOWS
8+
#if NETFRAMEWORK || NET5_0_WINDOWS || NET6_0_WINDOWS
99
using SW = System.Windows;
1010
using System.Windows.Media;
1111
using System.Windows.Media.Imaging;
@@ -17,7 +17,7 @@ namespace QRCoderTests.Helpers
1717
public static class HelperFunctions
1818
{
1919

20-
#if NETFRAMEWORK || NET5_0_WINDOWS
20+
#if NETFRAMEWORK || NET5_0_WINDOWS || NET6_0_WINDOWS
2121
public static BitmapSource ToBitmapSource(DrawingImage source)
2222
{
2323
DrawingVisual drawingVisual = new DrawingVisual();

QRCoderTests/QRCoderTests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
<UseWindowsForms Condition="'$(TargetFramework)' == 'net5.0-windows'">true</UseWindowsForms>
55
<UseWPF Condition="'$(TargetFramework)' == 'net5.0-windows'">true</UseWPF>
66
<DefineConstants Condition="'$(TargetFramework)' == 'net5.0-windows'">$(DefineConstants);NET5_0_WINDOWS</DefineConstants>
7+
<DefineConstants Condition="'$(TargetFramework)' == 'net6.0-windows'">$(DefineConstants);NET6_0_WINDOWS</DefineConstants>
78
<IsPackable>false</IsPackable>
89
<IsTestProject>true</IsTestProject>
910
<CheckEolTargetFramework>false</CheckEolTargetFramework>

0 commit comments

Comments
 (0)