Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions .github/workflows/wf-build-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,9 @@ jobs:
strategy:
matrix:
dotnet-framework:
- { name: ".NET 3.5", framework: "net35", coverage: false, no-build: true, sdk: "8.0.x" }
- { name: ".NET 4.52", framework: "net452", coverage: false, no-build: true, sdk: "8.0.x" }
- { name: ".NET Core 1.1", framework: "netcoreapp1.1", coverage: false, no-build: false, sdk: "1.0.x" }
- { name: ".NET Core 2.0", framework: "netcoreapp2.0", coverage: true, no-build: false, sdk: "2.0.x" }
- { name: ".NET Framework 4.6.2", framework: "net462", coverage: false, no-build: true, sdk: "8.0.x" }
- { name: ".NET Core 2.1", framework: "netcoreapp2.1", coverage: true, no-build: false, sdk: "2.1.x" }
- { name: ".NET Core 3.1", framework: "netcoreapp3.1", coverage: true, no-build: true, sdk: "3.1.x" }
- { name: ".NET 5.0", framework: "net5.0", coverage: true, no-build: true, sdk: "5.0.x" }
- { name: ".NET 5.0 Windows", framework: "net5.0-windows", coverage: true, no-build: true, sdk: "5.0.x" }
- { name: ".NET 6.0", framework: "net6.0", coverage: true, no-build: true, sdk: "6.0.x" }
Expand Down
3 changes: 0 additions & 3 deletions QRCoder.sln
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,8 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{A402660A-59F5-43E2-B5B0-69CE5E56DEA1}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
.gitignore = .gitignore
Directory.Build.props = Directory.Build.props
global.json = global.json
LICENSE.txt = LICENSE.txt
readme.md = readme.md
EndProjectSection
EndProject
Global
Expand Down
2 changes: 1 addition & 1 deletion QRCoderTests/ArtQRCodeRendererTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ 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"));
var bmp = new ArtQRCode(data).GetGraphic(HelperFunctions.GetIconBitmap());
//Used logo is licensed under public domain. Ref.: https://thenounproject.com/Iconathon1/collection/redefining-women/?i=2909346

var result = HelperFunctions.BitmapToHash(bmp);
Expand Down
3 changes: 0 additions & 3 deletions QRCoderTests/Base64QRCodeRendererTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#if !NETCOREAPP1_1
using System;
using System.Drawing;
using System.IO;
Expand Down Expand Up @@ -66,5 +65,3 @@ public void can_render_base64_qrcode_jpeg()
}
#endif
}

#endif
65 changes: 52 additions & 13 deletions QRCoderTests/Helpers/HelperFunctions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@
using System.IO;
using System.Security.Cryptography;
using System.Reflection;
#if !NETCOREAPP1_1
using System.Drawing;
#endif
#if TEST_XAML
using SW = System.Windows;
using System.Windows.Media;
Expand Down Expand Up @@ -46,16 +44,10 @@ public static Bitmap BitmapSourceToBitmap(DrawingImage xamlImg)
public static string GetAssemblyPath()
#if NET5_0_OR_GREATER
=> AppDomain.CurrentDomain.BaseDirectory;
#elif NETFRAMEWORK
=> Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().CodeBase).Replace("file:\\", "");
#elif NETCOREAPP1_1
=> Path.GetDirectoryName(typeof(HelperFunctions).GetTypeInfo().Assembly.Location).Replace("file:\\", "");
#else
=> Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location).Replace("file:\\", "");
#endif


#if !NETCOREAPP1_1
/// <summary>
/// Converts a bitmap to a hash string based on the pixel data
/// using a deterministic algorithm that ignores compression algorithm
Expand Down Expand Up @@ -86,19 +78,66 @@ public static string BitmapToHash(Bitmap bitmap)
// Hash the resulting byte array
return ByteArrayToHash(rgbValues);
}
#endif

public static string ByteArrayToHash(byte[] data)
{
#if !NETCOREAPP1_1
var md5 = MD5.Create();
var hash = md5.ComputeHash(data);
#else
var hash = new SshNet.Security.Cryptography.MD5().ComputeHash(data);
#endif
return BitConverter.ToString(hash).Replace("-", "").ToLower();
}

public static string StringToHash(string data)
=> ByteArrayToHash(Encoding.UTF8.GetBytes(data));

/// <summary>
/// Gets the embedded PNG icon as a Bitmap.
/// </summary>
public static Bitmap GetIconBitmap()
{
var assembly = Assembly.GetExecutingAssembly();
var resourceName = "QRCoderTests.assets.noun_software engineer_2909346.png";
using (var stream = assembly.GetManifestResourceStream(resourceName))
{
if (stream == null)
throw new InvalidOperationException($"Embedded resource '{resourceName}' not found.");
return new Bitmap(stream);
}
}

/// <summary>
/// Gets the embedded PNG icon as a byte array.
/// </summary>
public static byte[] GetIconBytes()
{
var assembly = Assembly.GetExecutingAssembly();
var resourceName = "QRCoderTests.assets.noun_software engineer_2909346.png";
using (var stream = assembly.GetManifestResourceStream(resourceName))
{
if (stream == null)
throw new InvalidOperationException($"Embedded resource '{resourceName}' not found.");
using (var memoryStream = new MemoryStream())
{
stream.CopyTo(memoryStream);
return memoryStream.ToArray();
}
}
}

/// <summary>
/// Gets the embedded SVG icon as a string.
/// </summary>
public static string GetIconSvg()
{
var assembly = Assembly.GetExecutingAssembly();
var resourceName = "QRCoderTests.assets.noun_Scientist_2909361.svg";
using (var stream = assembly.GetManifestResourceStream(resourceName))
{
if (stream == null)
throw new InvalidOperationException($"Embedded resource '{resourceName}' not found.");
using (var reader = new StreamReader(stream))
{
return reader.ReadToEnd();
}
}
}
}
9 changes: 0 additions & 9 deletions QRCoderTests/PayloadGeneratorTests/BitcoinAddressTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,8 @@ public void bitcoin_address_generator_should_round_to_satoshi()
[Fact]
public void bitcoin_address_generator_disregards_current_culture()
{
#if NETCOREAPP1_1
var currentCulture = CultureInfo.DefaultThreadCurrentCulture;
CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("de-DE");
#else
var currentCulture = Thread.CurrentThread.CurrentCulture;
Thread.CurrentThread.CurrentCulture = new CultureInfo("de-DE");
#endif

var address = "175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W";
var amount = .123;
Expand All @@ -87,10 +82,6 @@ public void bitcoin_address_generator_disregards_current_culture()
.ToString()
.ShouldBe("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=.123");

#if NETCOREAPP1_1
CultureInfo.DefaultThreadCurrentCulture = currentCulture;
#else
Thread.CurrentThread.CurrentCulture = currentCulture;
#endif
}
}
10 changes: 5 additions & 5 deletions QRCoderTests/QRCodeRendererTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ 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(HelperFunctions.GetAssemblyPath() + "\\assets\\noun_software engineer_2909346.png"));
var bmp = new QRCode(data).GetGraphic(10, Color.Black, Color.Transparent, icon: HelperFunctions.GetIconBitmap());
//Used logo is licensed under public domain. Ref.: https://thenounproject.com/Iconathon1/collection/redefining-women/?i=2909346
var result = HelperFunctions.BitmapToHash(bmp);
result.ShouldBe("c99a82b43ce48ddae18a75862c476a9e");
Expand All @@ -65,7 +65,7 @@ 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(HelperFunctions.GetAssemblyPath() + "\\assets\\noun_software engineer_2909346.png"));
var bmp = new QRCode(data).GetGraphic(10, Color.Black, Color.White, icon: HelperFunctions.GetIconBitmap());
//Used logo is licensed under public domain. Ref.: https://thenounproject.com/Iconathon1/collection/redefining-women/?i=2909346

var result = HelperFunctions.BitmapToHash(bmp);
Expand All @@ -79,7 +79,7 @@ public void can_create_qrcode_with_logo_and_with_transparent_border()
var gen = new QRCodeGenerator();
var data = gen.CreateQrCode("This is a quick test! 123#?", QRCodeGenerator.ECCLevel.H);

var logo = (Bitmap)Image.FromFile(HelperFunctions.GetAssemblyPath() + "\\assets\\noun_software engineer_2909346.png");
var logo = HelperFunctions.GetIconBitmap();
var bmp = new QRCode(data).GetGraphic(10, Color.Black, Color.Transparent, icon: logo, iconBorderWidth: 6);
//Used logo is licensed under public domain. Ref.: https://thenounproject.com/Iconathon1/collection/redefining-women/?i=2909346
var result = HelperFunctions.BitmapToHash(bmp);
Expand All @@ -93,7 +93,7 @@ public void can_create_qrcode_with_logo_and_with_standard_border()
var gen = new QRCodeGenerator();
var data = gen.CreateQrCode("This is a quick test! 123#?", QRCodeGenerator.ECCLevel.H);

var logo = (Bitmap)Image.FromFile(HelperFunctions.GetAssemblyPath() + "\\assets\\noun_software engineer_2909346.png");
var logo = HelperFunctions.GetIconBitmap();
var bmp = new QRCode(data).GetGraphic(10, Color.Black, Color.White, icon: logo, iconBorderWidth: 6);
//Used logo is licensed under public domain. Ref.: https://thenounproject.com/Iconathon1/collection/redefining-women/?i=2909346
var result = HelperFunctions.BitmapToHash(bmp);
Expand All @@ -107,7 +107,7 @@ public void can_create_qrcode_with_logo_and_with_custom_border()
var gen = new QRCodeGenerator();
var data = gen.CreateQrCode("This is a quick test! 123#?", QRCodeGenerator.ECCLevel.H);

var logo = (Bitmap)Image.FromFile(HelperFunctions.GetAssemblyPath() + "\\assets\\noun_software engineer_2909346.png");
var logo = HelperFunctions.GetIconBitmap();
var bmp = new QRCode(data).GetGraphic(10, Color.Black, Color.Transparent, icon: logo, iconBorderWidth: 6, iconBackgroundColor: Color.DarkGreen);
//Used logo is licensed under public domain. Ref.: https://thenounproject.com/Iconathon1/collection/redefining-women/?i=2909346
var result = HelperFunctions.BitmapToHash(bmp);
Expand Down
71 changes: 31 additions & 40 deletions QRCoderTests/QRCoderTests.csproj
Original file line number Diff line number Diff line change
@@ -1,64 +1,55 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net35;net452;netcoreapp1.1;netcoreapp2.0;net5.0;net5.0-windows;net6.0;net6.0-windows</TargetFrameworks>
<TargetFrameworks>net462;netcoreapp2.1;netcoreapp3.1;net5.0;net5.0-windows;net6.0;net6.0-windows</TargetFrameworks>
<UseWindowsForms Condition="'$(TargetFramework)' == 'net5.0-windows'">true</UseWindowsForms>
<UseWPF Condition="'$(TargetFramework)' == 'net5.0-windows'">true</UseWPF>
<DefineConstants Condition="'$(TargetFramework)' != 'net6.0' AND '$(TargetFramework)' != 'netcoreapp1.1'">$(DefineConstants);SYSTEM_DRAWING</DefineConstants>
<DefineConstants Condition="'$(TargetFramework)' == 'net35' or '$(TargetFramework)' == 'net452' or '$(TargetFramework)' == 'net5.0-windows' or '$(TargetFramework)' == 'net6.0-windows'">$(DefineConstants);TEST_XAML</DefineConstants>
<DefineConstants Condition="'$(TargetFramework)' != 'net6.0'">$(DefineConstants);SYSTEM_DRAWING</DefineConstants>
<DefineConstants Condition="'$(TargetFramework)' == 'net462' or '$(TargetFramework)' == 'net5.0-windows' or '$(TargetFramework)' == 'net6.0-windows'">$(DefineConstants);TEST_XAML</DefineConstants>
<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>
<DisableImplicitNuGetFallbackFolder>true</DisableImplicitNuGetFallbackFolder>
<NoWarn>$(NoWarn);NU1903</NoWarn>
<NoWarn>$(NoWarn);CA1416</NoWarn>
<SuppressTfmSupportBuildErrors>true</SuppressTfmSupportBuildErrors>
<CheckEolTargetFramework>false</CheckEolTargetFramework>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework)' == 'netcoreapp2.1'">
<RuntimeFrameworkVersion>2.1.30</RuntimeFrameworkVersion>
</PropertyGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net5.0' or '$(TargetFramework)' == 'net5.0-windows' or '$(TargetFramework)' == 'net6.0' or '$(TargetFramework)' == 'net6.0-windows' ">
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.4" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
<PackageReference Include="shouldly" Version="4.0.3" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net35' or '$(TargetFramework)' == 'net452' ">
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.0.1" />
<PackageReference Include="xunit" Version="1.9.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.0.1" />
<PackageReference Include="shouldly" Version="2.8.3" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netcoreapp1.1' or '$(TargetFramework)' == 'netcoreapp2.0'">
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.0.1" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" />
<PackageReference Include="shouldly" Version="3.0.2" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net35' ">
<Reference Include="PresentationCore, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
<Reference Include="WindowsBase, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net452' ">
<Reference Include="PresentationCore, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
<Reference Include="WindowsBase, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="coverlet.collector" Version="3.0.3">
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.3" />
<PackageReference Include="xunit" Version="2.9.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
<PackageReference Include="shouldly" Version="4.3.0" />
<PackageReference Include="System.Drawing.Common" Version="6.0.0" Condition="'$(TargetFramework)' == 'net6.0'" />
<PackageReference Include="System.Management" Version="6.0.1">
<ExcludeAssets>buildTransitive</ExcludeAssets>
</PackageReference>
<PackageReference Include="System.CodeDom" Version="6.0.0">
<ExcludeAssets>buildTransitive</ExcludeAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="6.0.4">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.msbuild" Version="3.0.3">
<PackageReference Include="coverlet.msbuild" Version="6.0.4">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="SshNet.Security.Cryptography" Version="1.3.0" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net462' ">
<Reference Include="PresentationCore, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
<Reference Include="WindowsBase, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\QRCoder\QRCoder.csproj" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net35' or '$(TargetFramework)' == 'net452' or '$(TargetFramework)' == 'net5.0-windows' or '$(TargetFramework)' == 'net6.0-windows' ">
<ItemGroup Condition=" '$(TargetFramework)' == 'net462' or '$(TargetFramework)' == 'net5.0-windows' or '$(TargetFramework)' == 'net6.0-windows' ">
<ProjectReference Include="..\QRCoder.Xaml\QRCoder.Xaml.csproj" />
</ItemGroup>
<ItemGroup>
<None Update="assets\noun_Scientist_2909361.svg">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="assets\noun_software engineer_2909346.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<EmbeddedResource Include="assets\noun_Scientist_2909361.svg" />
<EmbeddedResource Include="assets\noun_software engineer_2909346.png" />
</ItemGroup>
</Project>
Loading