diff --git a/.github/workflows/wf-build-test.yml b/.github/workflows/wf-build-test.yml index 383b23f3..571828c5 100644 --- a/.github/workflows/wf-build-test.yml +++ b/.github/workflows/wf-build-test.yml @@ -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" } diff --git a/QRCoder.sln b/QRCoder.sln index 67acb0c4..3afc8b4f 100644 --- a/QRCoder.sln +++ b/QRCoder.sln @@ -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 diff --git a/QRCoderTests/ArtQRCodeRendererTests.cs b/QRCoderTests/ArtQRCodeRendererTests.cs index 161f38a6..2cc91bec 100644 --- a/QRCoderTests/ArtQRCodeRendererTests.cs +++ b/QRCoderTests/ArtQRCodeRendererTests.cs @@ -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); diff --git a/QRCoderTests/Base64QRCodeRendererTests.cs b/QRCoderTests/Base64QRCodeRendererTests.cs index 797502b5..d66747b2 100644 --- a/QRCoderTests/Base64QRCodeRendererTests.cs +++ b/QRCoderTests/Base64QRCodeRendererTests.cs @@ -1,4 +1,3 @@ -#if !NETCOREAPP1_1 using System; using System.Drawing; using System.IO; @@ -66,5 +65,3 @@ public void can_render_base64_qrcode_jpeg() } #endif } - -#endif diff --git a/QRCoderTests/Helpers/HelperFunctions.cs b/QRCoderTests/Helpers/HelperFunctions.cs index 58e55a4e..8fb41ddf 100644 --- a/QRCoderTests/Helpers/HelperFunctions.cs +++ b/QRCoderTests/Helpers/HelperFunctions.cs @@ -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; @@ -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 /// /// Converts a bitmap to a hash string based on the pixel data /// using a deterministic algorithm that ignores compression algorithm @@ -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)); + + /// + /// Gets the embedded PNG icon as a Bitmap. + /// + 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); + } + } + + /// + /// Gets the embedded PNG icon as a byte array. + /// + 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(); + } + } + } + + /// + /// Gets the embedded SVG icon as a string. + /// + 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(); + } + } + } } diff --git a/QRCoderTests/PayloadGeneratorTests/BitcoinAddressTests.cs b/QRCoderTests/PayloadGeneratorTests/BitcoinAddressTests.cs index 297de536..dbd2e731 100644 --- a/QRCoderTests/PayloadGeneratorTests/BitcoinAddressTests.cs +++ b/QRCoderTests/PayloadGeneratorTests/BitcoinAddressTests.cs @@ -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; @@ -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 } } diff --git a/QRCoderTests/QRCodeRendererTests.cs b/QRCoderTests/QRCodeRendererTests.cs index c4f33b7a..a8db4e62 100644 --- a/QRCoderTests/QRCodeRendererTests.cs +++ b/QRCoderTests/QRCodeRendererTests.cs @@ -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"); @@ -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); @@ -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); @@ -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); @@ -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); diff --git a/QRCoderTests/QRCoderTests.csproj b/QRCoderTests/QRCoderTests.csproj index a31ba175..18a80723 100644 --- a/QRCoderTests/QRCoderTests.csproj +++ b/QRCoderTests/QRCoderTests.csproj @@ -1,64 +1,55 @@ - net35;net452;netcoreapp1.1;netcoreapp2.0;net5.0;net5.0-windows;net6.0;net6.0-windows + net462;netcoreapp2.1;netcoreapp3.1;net5.0;net5.0-windows;net6.0;net6.0-windows true true - $(DefineConstants);SYSTEM_DRAWING - $(DefineConstants);TEST_XAML + $(DefineConstants);SYSTEM_DRAWING + $(DefineConstants);TEST_XAML $(DefineConstants);NET5_0_WINDOWS $(DefineConstants);NET6_0_WINDOWS false true true - $(NoWarn);NU1903 + $(NoWarn);CA1416 + true + false + + + 2.1.30 - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + buildTransitive + + + buildTransitive + + runtime; build; native; contentfiles; analyzers; buildtransitive all - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + + + + + + - + - - Always - - - Always - + + diff --git a/QRCoderTests/SvgQRCodeRendererTests.cs b/QRCoderTests/SvgQRCodeRendererTests.cs index 54ff9fc1..7cc8ed08 100644 --- a/QRCoderTests/SvgQRCodeRendererTests.cs +++ b/QRCoderTests/SvgQRCodeRendererTests.cs @@ -92,7 +92,7 @@ public void can_render_svg_qrcode_with_png_logo_bitmap() var data = gen.CreateQrCode("This is a quick test! 123#?", QRCodeGenerator.ECCLevel.H); //Used logo is licensed under public domain. Ref.: https://thenounproject.com/Iconathon1/collection/redefining-women/?i=2909346 - var logoBitmap = (Bitmap)Image.FromFile(HelperFunctions.GetAssemblyPath() + "\\assets\\noun_software engineer_2909346.png"); + var logoBitmap = HelperFunctions.GetIconBitmap(); var logoObj = new SvgQRCode.SvgLogo(iconRasterized: logoBitmap, 15); logoObj.GetMediaType().ShouldBe(SvgQRCode.SvgLogo.MediaType.PNG); @@ -110,7 +110,7 @@ public void can_render_svg_qrcode_with_png_logo_bitmap_without_background() var data = gen.CreateQrCode("This is a quick test! 123#?", QRCodeGenerator.ECCLevel.H); //Used logo is licensed under public domain. Ref.: https://thenounproject.com/Iconathon1/collection/redefining-women/?i=2909346 - var logoBitmap = (Bitmap)Image.FromFile(HelperFunctions.GetAssemblyPath() + "\\assets\\noun_software engineer_2909346.png"); + var logoBitmap = HelperFunctions.GetIconBitmap(); var logoObj = new SvgQRCode.SvgLogo(iconRasterized: logoBitmap, 15, false); logoObj.GetMediaType().ShouldBe(SvgQRCode.SvgLogo.MediaType.PNG); @@ -128,7 +128,7 @@ public void can_render_svg_qrcode_with_png_logo_bitmap_without_quietzones() var data = gen.CreateQrCode("This is a quick test! 123#?", QRCodeGenerator.ECCLevel.H); //Used logo is licensed under public domain. Ref.: https://thenounproject.com/Iconathon1/collection/redefining-women/?i=2909346 - var logoBitmap = (Bitmap)Image.FromFile(HelperFunctions.GetAssemblyPath() + "\\assets\\noun_software engineer_2909346.png"); + var logoBitmap = HelperFunctions.GetIconBitmap(); var logoObj = new SvgQRCode.SvgLogo(iconRasterized: logoBitmap, 15); logoObj.GetMediaType().ShouldBe(SvgQRCode.SvgLogo.MediaType.PNG); @@ -147,7 +147,7 @@ public void can_render_svg_qrcode_with_png_logo_bytearray() var data = gen.CreateQrCode("This is a quick test! 123#?", QRCodeGenerator.ECCLevel.H); //Used logo is licensed under public domain. Ref.: https://thenounproject.com/Iconathon1/collection/redefining-women/?i=2909346 - var logoBitmap = System.IO.File.ReadAllBytes(HelperFunctions.GetAssemblyPath() + "\\assets\\noun_software engineer_2909346.png"); + var logoBitmap = HelperFunctions.GetIconBytes(); var logoObj = new SvgQRCode.SvgLogo(iconRasterized: logoBitmap, 15); logoObj.GetMediaType().ShouldBe(SvgQRCode.SvgLogo.MediaType.PNG); @@ -165,7 +165,7 @@ public void can_render_svg_qrcode_with_svg_logo_embedded() var data = gen.CreateQrCode("This is a quick test! 123#?", QRCodeGenerator.ECCLevel.H); //Used logo is licensed under public domain. Ref.: https://thenounproject.com/Iconathon1/collection/redefining-women/?i=2909361 - var logoSvg = File.ReadAllText(HelperFunctions.GetAssemblyPath() + "\\assets\\noun_Scientist_2909361.svg"); + var logoSvg = HelperFunctions.GetIconSvg(); var logoObj = new SvgQRCode.SvgLogo(logoSvg, 20); logoObj.GetMediaType().ShouldBe(SvgQRCode.SvgLogo.MediaType.SVG); @@ -183,7 +183,7 @@ public void can_render_svg_qrcode_with_svg_logo_image_tag() var data = gen.CreateQrCode("This is a quick test! 123#?", QRCodeGenerator.ECCLevel.H); //Used logo is licensed under public domain. Ref.: https://thenounproject.com/Iconathon1/collection/redefining-women/?i=2909361 - var logoSvg = File.ReadAllText(HelperFunctions.GetAssemblyPath() + "\\assets\\noun_Scientist_2909361.svg"); + var logoSvg = HelperFunctions.GetIconSvg(); var logoObj = new SvgQRCode.SvgLogo(logoSvg, 20, iconEmbedded: false); var svg = new SvgQRCode(data).GetGraphic(10, Color.DarkGray, Color.White, logo: logoObj);