diff --git a/tests/ImageSharp.Tests/Formats/Png/PngSmokeTests.cs b/tests/ImageSharp.Tests/Formats/Png/PngSmokeTests.cs index 90f994f36..05aa3c2d3 100644 --- a/tests/ImageSharp.Tests/Formats/Png/PngSmokeTests.cs +++ b/tests/ImageSharp.Tests/Formats/Png/PngSmokeTests.cs @@ -35,7 +35,7 @@ namespace ImageSharp.Tests.Formats.Png using (Image img2 = Image.Load(ms, new PngDecoder())) { // img2.Save(provider.Utility.GetTestOutputFileName("bmp", "_loaded"), new BmpEncoder()); - ImageComparer.CheckSimilarity(image, img2); + ImageComparer.VerifySimilarity(image, img2); } } } @@ -56,7 +56,7 @@ namespace ImageSharp.Tests.Formats.Png using (Image img2 = Image.Load(ms, new PngDecoder())) { // img2.Save(provider.Utility.GetTestOutputFileName("bmp", "_loaded"), new BmpEncoder()); - ImageComparer.CheckSimilarity(image, img2, 0.03f); + ImageComparer.VerifySimilarity(image, img2, 0.03f); } } } @@ -121,7 +121,7 @@ namespace ImageSharp.Tests.Formats.Png ms.Position = 0; using (Image img2 = Image.Load(ms, new PngDecoder())) { - ImageComparer.CheckSimilarity(image, img2); + ImageComparer.VerifySimilarity(image, img2); } } } diff --git a/tests/ImageSharp.Tests/ImageComparer.cs b/tests/ImageSharp.Tests/ImageComparer.cs index 4a37c6c45..30e89918c 100644 --- a/tests/ImageSharp.Tests/ImageComparer.cs +++ b/tests/ImageSharp.Tests/ImageComparer.cs @@ -17,9 +17,9 @@ namespace ImageSharp.Tests /// public static class ImageComparer { - const int DefaultScalingFactor = 32; // This is means the images get scaled into a 32x32 image to sample pixels - const int DefaultSegmentThreshold = 3; // The greyscale difference between 2 segements my be > 3 before it influences the overall difference - const float DefaultImageThreshold = 0.000F; // After segment thresholds the images must have no differences + internal const int DefaultScalingFactor = 32; // This is means the images get scaled into a 32x32 image to sample pixels + internal const int DefaultSegmentThreshold = 3; // The greyscale difference between 2 segements my be > 3 before it influences the overall difference + internal const float DefaultImageThreshold = 0.000F; // After segment thresholds the images must have no differences /// /// Fills the bounded area with a solid color and does a visual comparison between 2 images asserting the difference outwith @@ -50,7 +50,7 @@ namespace ImageSharp.Tests expected.Fill(NamedColors.HotPink, bounds); actual.Fill(NamedColors.HotPink, bounds); - CheckSimilarity(expected, actual, imageTheshold, segmentThreshold, scalingFactor); + VerifySimilarity(expected, actual, imageTheshold, segmentThreshold, scalingFactor); } /// @@ -72,7 +72,7 @@ namespace ImageSharp.Tests /// This is a sampling factor we sample a grid of average pixels width by high /// The default undefined value is /// - public static void CheckSimilarity( + public static void VerifySimilarity( Image expected, Image actual, float imageTheshold = DefaultImageThreshold, @@ -80,6 +80,9 @@ namespace ImageSharp.Tests int scalingFactor = DefaultScalingFactor) where TPixelA : struct, IPixel where TPixelB : struct, IPixel { + Assert.Equal(expected.Width, actual.Width); + Assert.Equal(expected.Height, actual.Height); + float percentage = expected.PercentageDifference(actual, segmentThreshold, scalingFactor); Assert.InRange(percentage, 0, imageTheshold); diff --git a/tests/ImageSharp.Tests/Processing/Transforms/ResizeTests.cs b/tests/ImageSharp.Tests/Processing/Transforms/ResizeTests.cs index fb195254e..9835a3e3a 100644 --- a/tests/ImageSharp.Tests/Processing/Transforms/ResizeTests.cs +++ b/tests/ImageSharp.Tests/Processing/Transforms/ResizeTests.cs @@ -40,7 +40,7 @@ namespace ImageSharp.Tests.Processing.Transforms using (Image image = provider.GetImage()) { image.Resize(image.Width / 2, image.Height / 2, sampler, true) - .DebugSave(provider, name, Extensions.Bmp); + .CompareToReferenceOutput(provider, name); } } diff --git a/tests/ImageSharp.Tests/ReferenceOutput/ResizeTests/ImageShouldResize_Rgba32_Calliphora_Bicubic.png b/tests/ImageSharp.Tests/ReferenceOutput/ResizeTests/ImageShouldResize_Rgba32_Calliphora_Bicubic.png new file mode 100644 index 000000000..938bfdd65 --- /dev/null +++ b/tests/ImageSharp.Tests/ReferenceOutput/ResizeTests/ImageShouldResize_Rgba32_Calliphora_Bicubic.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:70469b88029e09c8ae5342ffe0fdeaab640d6d5aec8f1e9c2e0c66fdc540ac95 +size 447170 diff --git a/tests/ImageSharp.Tests/ReferenceOutput/ResizeTests/ImageShouldResize_Rgba32_Calliphora_Box.png b/tests/ImageSharp.Tests/ReferenceOutput/ResizeTests/ImageShouldResize_Rgba32_Calliphora_Box.png new file mode 100644 index 000000000..83a009d1d --- /dev/null +++ b/tests/ImageSharp.Tests/ReferenceOutput/ResizeTests/ImageShouldResize_Rgba32_Calliphora_Box.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:66ea88b72f5281872f7745f8a9fc52524c56374134276320e33c7a1289a136b7 +size 450534 diff --git a/tests/ImageSharp.Tests/ReferenceOutput/ResizeTests/ImageShouldResize_Rgba32_Calliphora_Hermite.png b/tests/ImageSharp.Tests/ReferenceOutput/ResizeTests/ImageShouldResize_Rgba32_Calliphora_Hermite.png new file mode 100644 index 000000000..7db5bd010 --- /dev/null +++ b/tests/ImageSharp.Tests/ReferenceOutput/ResizeTests/ImageShouldResize_Rgba32_Calliphora_Hermite.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2caaf6c168c900dbfc1984cf4309032ced4f8c4b8274d2dacfdec8d29fdbd9d5 +size 431023 diff --git a/tests/ImageSharp.Tests/ReferenceOutput/ResizeTests/ImageShouldResize_Rgba32_Calliphora_Lanczos3.png b/tests/ImageSharp.Tests/ReferenceOutput/ResizeTests/ImageShouldResize_Rgba32_Calliphora_Lanczos3.png new file mode 100644 index 000000000..9602f3fb8 --- /dev/null +++ b/tests/ImageSharp.Tests/ReferenceOutput/ResizeTests/ImageShouldResize_Rgba32_Calliphora_Lanczos3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:de905f2be709c191fec7fdd659f4f36f65022ebc7286c291d91dab8980e24fb6 +size 458942 diff --git a/tests/ImageSharp.Tests/ReferenceOutput/ResizeTests/ImageShouldResize_Rgba32_Calliphora_Lanczos5.png b/tests/ImageSharp.Tests/ReferenceOutput/ResizeTests/ImageShouldResize_Rgba32_Calliphora_Lanczos5.png new file mode 100644 index 000000000..35d873e86 --- /dev/null +++ b/tests/ImageSharp.Tests/ReferenceOutput/ResizeTests/ImageShouldResize_Rgba32_Calliphora_Lanczos5.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c91056290a6fca55673c959540ee329de1f501e3943b7cd2c8b31be119f835ae +size 464896 diff --git a/tests/ImageSharp.Tests/ReferenceOutput/ResizeTests/ImageShouldResize_Rgba32_Calliphora_Lanczos8.png b/tests/ImageSharp.Tests/ReferenceOutput/ResizeTests/ImageShouldResize_Rgba32_Calliphora_Lanczos8.png new file mode 100644 index 000000000..15c10ea7f --- /dev/null +++ b/tests/ImageSharp.Tests/ReferenceOutput/ResizeTests/ImageShouldResize_Rgba32_Calliphora_Lanczos8.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f31d0e0e35c19812dfdaecb400e2a3348f8ebd19ae61b6f4310bdab2fdf8ed8c +size 469121 diff --git a/tests/ImageSharp.Tests/ReferenceOutput/ResizeTests/ImageShouldResize_Rgba32_Calliphora_MitchellNetravali.png b/tests/ImageSharp.Tests/ReferenceOutput/ResizeTests/ImageShouldResize_Rgba32_Calliphora_MitchellNetravali.png new file mode 100644 index 000000000..97cd15327 --- /dev/null +++ b/tests/ImageSharp.Tests/ReferenceOutput/ResizeTests/ImageShouldResize_Rgba32_Calliphora_MitchellNetravali.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ff82fe20b547f5e20c6d4c40266b856a38a94e1ef5e870478fcf9a81221aaa2d +size 429460 diff --git a/tests/ImageSharp.Tests/ReferenceOutput/ResizeTests/ImageShouldResize_Rgba32_Calliphora_NearestNeighbor.png b/tests/ImageSharp.Tests/ReferenceOutput/ResizeTests/ImageShouldResize_Rgba32_Calliphora_NearestNeighbor.png new file mode 100644 index 000000000..317c0e88f --- /dev/null +++ b/tests/ImageSharp.Tests/ReferenceOutput/ResizeTests/ImageShouldResize_Rgba32_Calliphora_NearestNeighbor.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4f84095fde69319ec1e2b052ad62228e46565b0e3aa99ebcc635f4be9349d8e9 +size 467253 diff --git a/tests/ImageSharp.Tests/ReferenceOutput/ResizeTests/ImageShouldResize_Rgba32_Calliphora_Robidoux.png b/tests/ImageSharp.Tests/ReferenceOutput/ResizeTests/ImageShouldResize_Rgba32_Calliphora_Robidoux.png new file mode 100644 index 000000000..701e5005a --- /dev/null +++ b/tests/ImageSharp.Tests/ReferenceOutput/ResizeTests/ImageShouldResize_Rgba32_Calliphora_Robidoux.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a723e94408e446fffc44ce80016fbb463c7014ca90bf352bfe5da425572fbc77 +size 426904 diff --git a/tests/ImageSharp.Tests/ReferenceOutput/ResizeTests/ImageShouldResize_Rgba32_Calliphora_RobidouxSharp.png b/tests/ImageSharp.Tests/ReferenceOutput/ResizeTests/ImageShouldResize_Rgba32_Calliphora_RobidouxSharp.png new file mode 100644 index 000000000..13bb10318 --- /dev/null +++ b/tests/ImageSharp.Tests/ReferenceOutput/ResizeTests/ImageShouldResize_Rgba32_Calliphora_RobidouxSharp.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f7c190fc65290277ed7805961fc8625b68ca98bbd1445802c104e990901ebcbc +size 432999 diff --git a/tests/ImageSharp.Tests/ReferenceOutput/ResizeTests/ImageShouldResize_Rgba32_Calliphora_Spline.png b/tests/ImageSharp.Tests/ReferenceOutput/ResizeTests/ImageShouldResize_Rgba32_Calliphora_Spline.png new file mode 100644 index 000000000..8a50dcd76 --- /dev/null +++ b/tests/ImageSharp.Tests/ReferenceOutput/ResizeTests/ImageShouldResize_Rgba32_Calliphora_Spline.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8bb323798907fe4b0145a64b57d06ea42726b7acbb7f03fdff9b59e0d572941c +size 390539 diff --git a/tests/ImageSharp.Tests/ReferenceOutput/ResizeTests/ImageShouldResize_Rgba32_Calliphora_Triangle.png b/tests/ImageSharp.Tests/ReferenceOutput/ResizeTests/ImageShouldResize_Rgba32_Calliphora_Triangle.png new file mode 100644 index 000000000..d4751bb1d --- /dev/null +++ b/tests/ImageSharp.Tests/ReferenceOutput/ResizeTests/ImageShouldResize_Rgba32_Calliphora_Triangle.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:214df91833d4fdf8f0940a62645070093bf00b13fcb3748407526414a9c504bb +size 418080 diff --git a/tests/ImageSharp.Tests/ReferenceOutput/ResizeTests/ImageShouldResize_Rgba32_Calliphora_Welch.png b/tests/ImageSharp.Tests/ReferenceOutput/ResizeTests/ImageShouldResize_Rgba32_Calliphora_Welch.png new file mode 100644 index 000000000..5fb0d9d58 --- /dev/null +++ b/tests/ImageSharp.Tests/ReferenceOutput/ResizeTests/ImageShouldResize_Rgba32_Calliphora_Welch.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:78b9122639130418d8589718674b979315dd21d7fe25c07794f9cd8475ac99e0 +size 460956 diff --git a/tests/ImageSharp.Tests/TestUtilities/ImagingTestCaseUtility.cs b/tests/ImageSharp.Tests/TestUtilities/ImagingTestCaseUtility.cs index 290123885..59c5813ad 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ImagingTestCaseUtility.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ImagingTestCaseUtility.cs @@ -112,6 +112,9 @@ namespace ImageSharp.Tests } } + internal string GetReferenceOutputFileName(string extension = null, string tag = null) + => this.GetTestOutputFileName(extension, tag).Replace("TestOutput", "ReferenceOutput"); + internal void Init(string typeName, string methodName) { this.TestGroupName = typeName; diff --git a/tests/ImageSharp.Tests/TestUtilities/Integration/IntegrationTestUtils.cs b/tests/ImageSharp.Tests/TestUtilities/Integration/IntegrationTestUtils.cs index 53986e64a..1bf90ac7d 100644 --- a/tests/ImageSharp.Tests/TestUtilities/Integration/IntegrationTestUtils.cs +++ b/tests/ImageSharp.Tests/TestUtilities/Integration/IntegrationTestUtils.cs @@ -57,6 +57,11 @@ var fullRect = new System.Drawing.Rectangle(0, 0, w, h); + if (bmp.PixelFormat != PixelFormat.Format32bppArgb) + { + throw new ArgumentException("FromSystemDrawingBitmap(): pixel format not supported", nameof(bmp)); + } + BitmapData data = bmp.LockBits(fullRect, ImageLockMode.ReadWrite, bmp.PixelFormat); byte* sourcePtrBase = (byte*)data.Scan0; diff --git a/tests/ImageSharp.Tests/TestUtilities/Integration/ReferenceDecoder.cs b/tests/ImageSharp.Tests/TestUtilities/Integration/ReferenceDecoder.cs new file mode 100644 index 000000000..3e905cc07 --- /dev/null +++ b/tests/ImageSharp.Tests/TestUtilities/Integration/ReferenceDecoder.cs @@ -0,0 +1,40 @@ +namespace ImageSharp.Tests.TestUtilities.Integration +{ + using System; + using System.Drawing; + using System.IO; + + using ImageSharp.Formats; + using ImageSharp.PixelFormats; + + public class ReferenceDecoder : IImageDecoder + { + public static ReferenceDecoder Instance { get; } = new ReferenceDecoder(); + + public Image Decode(Configuration configuration, Stream stream, IDecoderOptions options) + where TPixel : struct, IPixel + { + using (var sourceBitmap = new System.Drawing.Bitmap(stream)) + { + if (sourceBitmap.PixelFormat == System.Drawing.Imaging.PixelFormat.Format32bppArgb) + { + return IntegrationTestUtils.FromSystemDrawingBitmap(sourceBitmap); + } + + using (var convertedBitmap = new System.Drawing.Bitmap( + sourceBitmap.Width, + sourceBitmap.Height, + System.Drawing.Imaging.PixelFormat.Format32bppArgb)) + { + using (var g = Graphics.FromImage(convertedBitmap)) + { + g.DrawImage(sourceBitmap, new PointF(0, 0)); + } + return IntegrationTestUtils.FromSystemDrawingBitmap(convertedBitmap); + } + + + } + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/TestUtilities/Integration/ReferencePngDecoder.cs b/tests/ImageSharp.Tests/TestUtilities/Integration/ReferencePngDecoder.cs deleted file mode 100644 index f2ac69fd4..000000000 --- a/tests/ImageSharp.Tests/TestUtilities/Integration/ReferencePngDecoder.cs +++ /dev/null @@ -1,31 +0,0 @@ -namespace ImageSharp.Tests.TestUtilities.Integration -{ - using System; - using System.IO; - - using ImageSharp.Formats; - using ImageSharp.PixelFormats; - - public class ReferencePngDecoder : IImageDecoder - { - public static ReferencePngDecoder Instance { get; } = new ReferencePngDecoder(); - - public Image Decode(Configuration configuration, Stream stream, IDecoderOptions options) - where TPixel : struct, IPixel - { - using (var sdBitmap = new System.Drawing.Bitmap(stream)) - { - if (!sdBitmap.RawFormat.Equals(System.Drawing.Imaging.ImageFormat.Png)) - { - throw new Exception("Reference image should be a Png!"); - } - if (sdBitmap.PixelFormat != System.Drawing.Imaging.PixelFormat.Format32bppArgb) - { - throw new Exception("Reference image pixel format should be PixelFormat.Format32bppArgb!"); - } - - return IntegrationTestUtils.FromSystemDrawingBitmap(sdBitmap); - } - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs index bb97daaa4..e1edfbe8a 100644 --- a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs +++ b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs @@ -7,10 +7,12 @@ namespace ImageSharp.Tests { using System; using System.Collections.Generic; + using System.IO; using System.Linq; using System.Reflection; using ImageSharp.PixelFormats; + using ImageSharp.Tests.TestUtilities.Integration; public static class TestImageExtensions { @@ -57,5 +59,60 @@ namespace ImageSharp.Tests provider.Utility.SaveTestOutputFile(image, extension, tag: tag); return image; } + + public static Image CompareToReferenceOutput( + this Image image, + ITestImageProvider provider, + object settings = null, + string extension = "png", + float imageTheshold = ImageComparer.DefaultImageThreshold, + byte segmentThreshold = ImageComparer.DefaultSegmentThreshold, + int scalingFactor = ImageComparer.DefaultScalingFactor) + where TPixel : struct, IPixel + { + // We are running locally then we want to save it out + string tag = null; + string s = settings as string; + + if (s != null) + { + tag = s; + } + else if (settings != null) + { + Type type = settings.GetType(); + TypeInfo info = type.GetTypeInfo(); + if (info.IsPrimitive || info.IsEnum || type == typeof(decimal)) + { + tag = settings.ToString(); + } + else + { + IEnumerable properties = settings.GetType().GetRuntimeProperties(); + + tag = string.Join("_", properties.ToDictionary(x => x.Name, x => x.GetValue(settings)).Select(x => $"{x.Key}-{x.Value}")); + } + } + + string referenceOutputFile = provider.Utility.GetReferenceOutputFileName(extension, tag); + + if (!(bool.TryParse(Environment.GetEnvironmentVariable("CI"), out bool isCi) && isCi)) + { + provider.Utility.SaveTestOutputFile(image, extension, tag: tag); + } + + if (!File.Exists(referenceOutputFile)) + { + throw new Exception("Reference output file missing: " + referenceOutputFile); + } + + using (Image referenceImage = Image.Load(referenceOutputFile, ReferenceDecoder.Instance)) + { + ImageComparer.VerifySimilarity(referenceImage, image, imageTheshold, segmentThreshold, scalingFactor); + } + + + return image; + } } } diff --git a/tests/ImageSharp.Tests/TestUtilities/Tests/IntegrationTestUtilsTests.cs b/tests/ImageSharp.Tests/TestUtilities/Tests/IntegrationTestUtilsTests.cs index d1ceef03b..54dbd682d 100644 --- a/tests/ImageSharp.Tests/TestUtilities/Tests/IntegrationTestUtilsTests.cs +++ b/tests/ImageSharp.Tests/TestUtilities/Tests/IntegrationTestUtilsTests.cs @@ -52,7 +52,7 @@ namespace ImageSharp.Tests where TPixel : struct, IPixel { string path = TestFile.GetPath(TestImages.Png.Splash); - using (Image image = Image.Load(path, ReferencePngDecoder.Instance)) + using (Image image = Image.Load(path, ReferenceDecoder.Instance)) { image.DebugSave(dummyProvider); }