From dc0982f1864b0c41fcc1a79853b3d16746906835 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 14 Apr 2021 16:09:25 +0100 Subject: [PATCH 1/6] Faster Linear Transforms (#1591) * Attempt to use same weight generation algorithm as resize. * tests pass * Identical output * Update LinearTransformKernelFactory{TResampler}.cs * Use new low allocation iterator * Migrate projective transforms. * Optimizations * Smaller kernel * Fix sampling accuracy * Finalize and update refs * Revert unnecessary changes * Remove enumerator * Actually save output for debugging. * Use custom test png encoder for reduced memory environments * Convolution should use scaled vectors * Update TestEnvironmentTests.cs * Try using doubles * Moar double precision * Fix radius calculation * Test if issue is SIMD related. * Detect runtime to determine pipeline. * Fix stack overflow * fix condition * Try simplified scalar run * Simplify unpremultiply scalar * Update Numerics.cs * Fix runtime environment * Update ImageSharp.csproj * Duplicate the caller with scalar versions * Update method name, exclude from coverage. * Don't save output during coverage tests for perf. * Update src/ImageSharp/Common/Helpers/RuntimeEnvironment.cs Co-authored-by: Anton Firszov Co-authored-by: Anton Firszov --- .gitattributes | 3 +- .../Common/Helpers/RuntimeEnvironment.cs | 32 +++ .../AffineTransformProcessor{TPixel}.cs | 210 ++++++++++++------ .../Linear/LinearTransformUtility.cs | 60 +++++ .../Transforms/Linear/LinearTransformUtils.cs | 104 --------- .../ProjectiveTransformProcessor{TPixel}.cs | 209 +++++++++++------ .../Transforms/Resize/ResizeKernel.cs | 4 +- .../Processing/Rotate.cs | 28 ++- .../ImageSharp.Benchmarks/Processing/Skew.cs | 28 ++- .../Helpers/RuntimeEnvironmentTests.cs | 41 ++++ .../Transforms/AffineTransformTests.cs | 5 +- .../TestUtilities/ImagingTestCaseUtility.cs | 2 +- ...SharpPngEncoderWithDefaultConfiguration.cs | 94 ++++++++ .../TestUtilities/TestEnvironment.Formats.cs | 4 +- .../TestUtilities/TestEnvironment.cs | 7 + .../TestUtilities/TestImageExtensions.cs | 61 ++--- .../Tests/TestEnvironmentTests.cs | 3 +- ...tPattern100x50_R(50)_S(1,1)_T(-20,-10).png | 4 +- ...ate_Rgba32_TestPattern100x50__original.png | 4 +- ...pler_Rgba32_TestPattern150x150_Bicubic.png | 4 +- ...r_Rgba32_TestPattern150x150_CatmullRom.png | 4 +- ...ler_Rgba32_TestPattern150x150_Lanczos2.png | 4 +- ...ler_Rgba32_TestPattern150x150_Lanczos3.png | 4 +- ...ler_Rgba32_TestPattern150x150_Lanczos5.png | 4 +- ...ler_Rgba32_TestPattern150x150_Lanczos8.png | 4 +- ...2_TestPattern150x150_MitchellNetravali.png | 4 +- ...ler_Rgba32_TestPattern150x150_Robidoux.png | 4 +- ...gba32_TestPattern150x150_RobidouxSharp.png | 4 +- ...mpler_Rgba32_TestPattern150x150_Spline.png | 4 +- ...ler_Rgba32_TestPattern150x150_Triangle.png | 4 +- ...ampler_Rgba32_TestPattern150x150_Welch.png | 4 +- .../DrawImageTests/DrawTransformed.png | 4 +- 32 files changed, 604 insertions(+), 351 deletions(-) create mode 100644 src/ImageSharp/Common/Helpers/RuntimeEnvironment.cs create mode 100644 src/ImageSharp/Processing/Processors/Transforms/Linear/LinearTransformUtility.cs delete mode 100644 src/ImageSharp/Processing/Processors/Transforms/Linear/LinearTransformUtils.cs create mode 100644 tests/ImageSharp.Tests/Helpers/RuntimeEnvironmentTests.cs create mode 100644 tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/ImageSharpPngEncoderWithDefaultConfiguration.cs diff --git a/.gitattributes b/.gitattributes index 416dd0d06f..70ced69033 100644 --- a/.gitattributes +++ b/.gitattributes @@ -86,7 +86,6 @@ *.dll binary *.eot binary *.exe binary -*.ktx binary *.otf binary *.pbm binary *.pdf binary @@ -125,3 +124,5 @@ *.tga filter=lfs diff=lfs merge=lfs -text *.webp filter=lfs diff=lfs merge=lfs -text *.dds filter=lfs diff=lfs merge=lfs -text +*.ktx filter=lfs diff=lfs merge=lfs -text +*.ktx2 filter=lfs diff=lfs merge=lfs -text diff --git a/src/ImageSharp/Common/Helpers/RuntimeEnvironment.cs b/src/ImageSharp/Common/Helpers/RuntimeEnvironment.cs new file mode 100644 index 0000000000..5525d3de50 --- /dev/null +++ b/src/ImageSharp/Common/Helpers/RuntimeEnvironment.cs @@ -0,0 +1,32 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Runtime.InteropServices; + +namespace SixLabors.ImageSharp +{ + /// + /// Provides information about the .NET runtime installation. + /// Many methods defer to when available. + /// + internal static class RuntimeEnvironment + { + private static readonly Lazy IsNetCoreLazy = new Lazy(() => FrameworkDescription.StartsWith(".NET Core", StringComparison.OrdinalIgnoreCase)); + + /// + /// Gets a value indicating whether the .NET installation is .NET Core 3.1 or lower. + /// + public static bool IsNetCore => IsNetCoreLazy.Value; + + /// + /// Gets the name of the .NET installation on which an app is running. + /// + public static string FrameworkDescription => RuntimeInformation.FrameworkDescription; + + /// + /// Indicates whether the current application is running on the specified platform. + /// + public static bool IsOSPlatform(OSPlatform osPlatform) => RuntimeInformation.IsOSPlatform(osPlatform); + } +} diff --git a/src/ImageSharp/Processing/Processors/Transforms/Linear/AffineTransformProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/Linear/AffineTransformProcessor{TPixel}.cs index c08f5d3d3b..5f04918e09 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Linear/AffineTransformProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Linear/AffineTransformProcessor{TPixel}.cs @@ -2,6 +2,8 @@ // Licensed under the Apache License, Version 2.0. using System; +using System.Buffers; +using System.Diagnostics.CodeAnalysis; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -80,32 +82,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms return; } - int yRadius = LinearTransformUtils.GetSamplingRadius(in sampler, source.Height, destination.Height); - int xRadius = LinearTransformUtils.GetSamplingRadius(in sampler, source.Width, destination.Width); - var radialExtents = new Vector2(xRadius, yRadius); - int yLength = (yRadius * 2) + 1; - int xLength = (xRadius * 2) + 1; - - // We use 2D buffers so that we can access the weight spans per row in parallel. - using Buffer2D yKernelBuffer = configuration.MemoryAllocator.Allocate2D(yLength, destination.Height); - using Buffer2D xKernelBuffer = configuration.MemoryAllocator.Allocate2D(xLength, destination.Height); - - int maxX = source.Width - 1; - int maxY = source.Height - 1; - var maxSourceExtents = new Vector4(maxX, maxY, maxX, maxY); - var operation = new AffineOperation( configuration, source, destination, - yKernelBuffer, - xKernelBuffer, in sampler, - matrix, - radialExtents, - maxSourceExtents); + matrix); - ParallelRowIterator.IterateRows, Vector4>( + ParallelRowIterator.IterateRowIntervals, Vector4>( configuration, destination.Bounds(), in operation); @@ -117,7 +101,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms private readonly ImageFrame destination; private readonly Rectangle bounds; private readonly Matrix3x2 matrix; - private readonly int maxX; [MethodImpl(InliningOptions.ShortMethod)] public NNAffineOperation( @@ -129,15 +112,15 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms this.destination = destination; this.bounds = source.Bounds(); this.matrix = matrix; - this.maxX = destination.Width; } [MethodImpl(InliningOptions.ShortMethod)] public void Invoke(int y) { + Buffer2D sourceBuffer = this.source.PixelBuffer; Span destRow = this.destination.GetPixelRowSpan(y); - for (int x = 0; x < this.maxX; x++) + for (int x = 0; x < destRow.Length; x++) { var point = Vector2.Transform(new Vector2(x, y), this.matrix); int px = (int)MathF.Round(point.X); @@ -145,84 +128,181 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms if (this.bounds.Contains(px, py)) { - destRow[x] = this.source[px, py]; + destRow[x] = sourceBuffer.GetElementUnsafe(px, py); } } } } - private readonly struct AffineOperation : IRowOperation + private readonly struct AffineOperation : IRowIntervalOperation where TResampler : struct, IResampler { private readonly Configuration configuration; private readonly ImageFrame source; private readonly ImageFrame destination; - private readonly Buffer2D yKernelBuffer; - private readonly Buffer2D xKernelBuffer; private readonly TResampler sampler; private readonly Matrix3x2 matrix; - private readonly Vector2 radialExtents; - private readonly Vector4 maxSourceExtents; - private readonly int maxX; + private readonly float yRadius; + private readonly float xRadius; [MethodImpl(InliningOptions.ShortMethod)] public AffineOperation( Configuration configuration, ImageFrame source, ImageFrame destination, - Buffer2D yKernelBuffer, - Buffer2D xKernelBuffer, in TResampler sampler, - Matrix3x2 matrix, - Vector2 radialExtents, - Vector4 maxSourceExtents) + Matrix3x2 matrix) { this.configuration = configuration; this.source = source; this.destination = destination; - this.yKernelBuffer = yKernelBuffer; - this.xKernelBuffer = xKernelBuffer; this.sampler = sampler; this.matrix = matrix; - this.radialExtents = radialExtents; - this.maxSourceExtents = maxSourceExtents; - this.maxX = destination.Width; + + this.yRadius = LinearTransformUtility.GetSamplingRadius(in sampler, source.Height, destination.Height); + this.xRadius = LinearTransformUtility.GetSamplingRadius(in sampler, source.Width, destination.Width); } [MethodImpl(InliningOptions.ShortMethod)] - public void Invoke(int y, Span span) + public void Invoke(in RowInterval rows, Span span) { - Buffer2D sourceBuffer = this.source.PixelBuffer; + if (RuntimeEnvironment.IsOSPlatform(OSPlatform.OSX) + && RuntimeEnvironment.IsNetCore) + { + // There's something wrong with the JIT in .NET Core 3.1 on certain + // MacOSX machines so we have to use different pipelines. + // It's: + // - Not reproducable locally + // - Doesn't seem to be triggered by the bulk Numerics.UnPremultiply method but by caller. + // https://github.com/SixLabors/ImageSharp/pull/1591 + this.InvokeMacOSX(in rows, span); + return; + } - PixelOperations.Instance.ToVector4( - this.configuration, - this.destination.GetPixelRowSpan(y), - span); + Matrix3x2 matrix = this.matrix; + TResampler sampler = this.sampler; + float yRadius = this.yRadius; + float xRadius = this.xRadius; + int maxY = this.source.Height - 1; + int maxX = this.source.Width - 1; - ref float yKernelSpanRef = ref MemoryMarshal.GetReference(this.yKernelBuffer.GetRowSpan(y)); - ref float xKernelSpanRef = ref MemoryMarshal.GetReference(this.xKernelBuffer.GetRowSpan(y)); + Buffer2D sourceBuffer = this.source.PixelBuffer; - for (int x = 0; x < this.maxX; x++) + for (int y = rows.Min; y < rows.Max; y++) { - // Use the single precision position to calculate correct bounding pixels - // otherwise we get rogue pixels outside of the bounds. - var point = Vector2.Transform(new Vector2(x, y), this.matrix); - LinearTransformUtils.Convolve( - in this.sampler, - point, - sourceBuffer, + Span rowSpan = this.destination.GetPixelRowSpan(y); + PixelOperations.Instance.ToVector4( + this.configuration, + rowSpan, + span, + PixelConversionModifiers.Scale); + + for (int x = 0; x < span.Length; x++) + { + var point = Vector2.Transform(new Vector2(x, y), matrix); + float pY = point.Y; + float pX = point.X; + + int top = LinearTransformUtility.GetRangeStart(yRadius, pY, maxY); + int bottom = LinearTransformUtility.GetRangeEnd(yRadius, pY, maxY); + int left = LinearTransformUtility.GetRangeStart(xRadius, pX, maxX); + int right = LinearTransformUtility.GetRangeEnd(xRadius, pX, maxX); + + if (bottom == top || right == left) + { + continue; + } + + Vector4 sum = Vector4.Zero; + for (int yK = top; yK <= bottom; yK++) + { + float yWeight = sampler.GetValue(yK - pY); + + for (int xK = left; xK <= right; xK++) + { + float xWeight = sampler.GetValue(xK - pX); + + Vector4 current = sourceBuffer.GetElementUnsafe(xK, yK).ToScaledVector4(); + Numerics.Premultiply(ref current); + sum += current * xWeight * yWeight; + } + } + + span[x] = sum; + } + + Numerics.UnPremultiply(span); + PixelOperations.Instance.FromVector4Destructive( + this.configuration, span, - x, - ref yKernelSpanRef, - ref xKernelSpanRef, - this.radialExtents, - this.maxSourceExtents); + rowSpan, + PixelConversionModifiers.Scale); } + } + + [ExcludeFromCodeCoverage] + [MethodImpl(InliningOptions.ShortMethod)] + private void InvokeMacOSX(in RowInterval rows, Span span) + { + Matrix3x2 matrix = this.matrix; + TResampler sampler = this.sampler; + float yRadius = this.yRadius; + float xRadius = this.xRadius; + int maxY = this.source.Height - 1; + int maxX = this.source.Width - 1; - PixelOperations.Instance.FromVector4Destructive( - this.configuration, - span, - this.destination.GetPixelRowSpan(y)); + Buffer2D sourceBuffer = this.source.PixelBuffer; + + for (int y = rows.Min; y < rows.Max; y++) + { + Span rowSpan = this.destination.GetPixelRowSpan(y); + PixelOperations.Instance.ToVector4( + this.configuration, + rowSpan, + span, + PixelConversionModifiers.Scale); + + for (int x = 0; x < span.Length; x++) + { + var point = Vector2.Transform(new Vector2(x, y), matrix); + float pY = point.Y; + float pX = point.X; + + int top = LinearTransformUtility.GetRangeStart(yRadius, pY, maxY); + int bottom = LinearTransformUtility.GetRangeEnd(yRadius, pY, maxY); + int left = LinearTransformUtility.GetRangeStart(xRadius, pX, maxX); + int right = LinearTransformUtility.GetRangeEnd(xRadius, pX, maxX); + + if (bottom == top || right == left) + { + continue; + } + + Vector4 sum = Vector4.Zero; + for (int yK = top; yK <= bottom; yK++) + { + float yWeight = sampler.GetValue(yK - pY); + + for (int xK = left; xK <= right; xK++) + { + float xWeight = sampler.GetValue(xK - pX); + + Vector4 current = sourceBuffer.GetElementUnsafe(xK, yK).ToScaledVector4(); + Numerics.Premultiply(ref current); + sum += current * xWeight * yWeight; + } + } + + Numerics.UnPremultiply(ref sum); + span[x] = sum; + } + + PixelOperations.Instance.FromVector4Destructive( + this.configuration, + span, + rowSpan, + PixelConversionModifiers.Scale); + } } } } diff --git a/src/ImageSharp/Processing/Processors/Transforms/Linear/LinearTransformUtility.cs b/src/ImageSharp/Processing/Processors/Transforms/Linear/LinearTransformUtility.cs new file mode 100644 index 0000000000..c6168b4619 --- /dev/null +++ b/src/ImageSharp/Processing/Processors/Transforms/Linear/LinearTransformUtility.cs @@ -0,0 +1,60 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Runtime.CompilerServices; + +namespace SixLabors.ImageSharp.Processing.Processors.Transforms +{ + /// + /// Utility methods for linear transforms. + /// + internal static class LinearTransformUtility + { + /// + /// Returns the sampling radius for the given sampler and dimensions. + /// + /// The type of resampler. + /// The resampler sampler. + /// The source size. + /// The destination size. + /// The . + [MethodImpl(InliningOptions.ShortMethod)] + public static float GetSamplingRadius(in TResampler sampler, int sourceSize, int destinationSize) + where TResampler : struct, IResampler + { + float scale = (float)sourceSize / destinationSize; + + if (scale < 1F) + { + scale = 1F; + } + + return MathF.Ceiling(sampler.Radius * scale); + } + + /// + /// Gets the start position (inclusive) for a sampling range given + /// the radius, center position and max constraint. + /// + /// The radius. + /// The center position. + /// The max allowed amouunt. + /// The . + [MethodImpl(InliningOptions.ShortMethod)] + public static int GetRangeStart(float radius, float center, int max) + => Numerics.Clamp((int)MathF.Ceiling(center - radius), 0, max); + + /// + /// Gets the end position (inclusive) for a sampling range given + /// the radius, center position and max constraint. + /// + /// The radius. + /// The center position. + /// The max allowed amouunt. + /// The . + [MethodImpl(InliningOptions.ShortMethod)] + public static int GetRangeEnd(float radius, float center, int max) + => Numerics.Clamp((int)MathF.Floor(center + radius), 0, max); + } +} diff --git a/src/ImageSharp/Processing/Processors/Transforms/Linear/LinearTransformUtils.cs b/src/ImageSharp/Processing/Processors/Transforms/Linear/LinearTransformUtils.cs deleted file mode 100644 index e65b2cbe92..0000000000 --- a/src/ImageSharp/Processing/Processors/Transforms/Linear/LinearTransformUtils.cs +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright (c) Six Labors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Numerics; -using System.Runtime.CompilerServices; -using SixLabors.ImageSharp.Memory; -using SixLabors.ImageSharp.PixelFormats; - -namespace SixLabors.ImageSharp.Processing.Processors.Transforms -{ - /// - /// Utility methods for affine and projective transforms. - /// - internal static class LinearTransformUtils - { - [MethodImpl(InliningOptions.ShortMethod)] - internal static int GetSamplingRadius(in TResampler sampler, int sourceSize, int destinationSize) - where TResampler : struct, IResampler - { - double scale = sourceSize / destinationSize; - if (scale < 1) - { - scale = 1; - } - - return (int)Math.Ceiling(scale * sampler.Radius); - } - - [MethodImpl(InliningOptions.ShortMethod)] - internal static void Convolve( - in TResampler sampler, - Vector2 transformedPoint, - Buffer2D sourcePixels, - Span targetRow, - int column, - ref float yKernelSpanRef, - ref float xKernelSpanRef, - Vector2 radialExtents, - Vector4 maxSourceExtents) - where TResampler : struct, IResampler - where TPixel : unmanaged, IPixel - { - // Clamp sampling pixel radial extents to the source image edges - Vector2 minXY = transformedPoint - radialExtents; - Vector2 maxXY = transformedPoint + radialExtents; - - // left, top, right, bottom - var sourceExtents = new Vector4( - MathF.Ceiling(minXY.X), - MathF.Ceiling(minXY.Y), - MathF.Floor(maxXY.X), - MathF.Floor(maxXY.Y)); - - sourceExtents = Numerics.Clamp(sourceExtents, Vector4.Zero, maxSourceExtents); - - int left = (int)sourceExtents.X; - int top = (int)sourceExtents.Y; - int right = (int)sourceExtents.Z; - int bottom = (int)sourceExtents.W; - - if (left == right || top == bottom) - { - return; - } - - CalculateWeights(in sampler, top, bottom, transformedPoint.Y, ref yKernelSpanRef); - CalculateWeights(in sampler, left, right, transformedPoint.X, ref xKernelSpanRef); - - Vector4 sum = Vector4.Zero; - for (int kernelY = 0, y = top; y <= bottom; y++, kernelY++) - { - float yWeight = Unsafe.Add(ref yKernelSpanRef, kernelY); - - for (int kernelX = 0, x = left; x <= right; x++, kernelX++) - { - float xWeight = Unsafe.Add(ref xKernelSpanRef, kernelX); - - // Values are first premultiplied to prevent darkening of edge pixels. - var current = sourcePixels[x, y].ToVector4(); - Numerics.Premultiply(ref current); - sum += current * xWeight * yWeight; - } - } - - // Reverse the premultiplication - Numerics.UnPremultiply(ref sum); - targetRow[column] = sum; - } - - [MethodImpl(InliningOptions.ShortMethod)] - private static void CalculateWeights(in TResampler sampler, int min, int max, float point, ref float weightsRef) - where TResampler : struct, IResampler - { - float sum = 0; - for (int x = 0, i = min; i <= max; i++, x++) - { - float weight = sampler.GetValue(i - point); - sum += weight; - Unsafe.Add(ref weightsRef, x) = weight; - } - } - } -} diff --git a/src/ImageSharp/Processing/Processors/Transforms/Linear/ProjectiveTransformProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/Linear/ProjectiveTransformProcessor{TPixel}.cs index f16a495b14..9396a018d3 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Linear/ProjectiveTransformProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Linear/ProjectiveTransformProcessor{TPixel}.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. using System; +using System.Diagnostics.CodeAnalysis; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -80,32 +81,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms return; } - int yRadius = LinearTransformUtils.GetSamplingRadius(in sampler, source.Height, destination.Height); - int xRadius = LinearTransformUtils.GetSamplingRadius(in sampler, source.Width, destination.Width); - var radialExtents = new Vector2(xRadius, yRadius); - int yLength = (yRadius * 2) + 1; - int xLength = (xRadius * 2) + 1; - - // We use 2D buffers so that we can access the weight spans per row in parallel. - using Buffer2D yKernelBuffer = configuration.MemoryAllocator.Allocate2D(yLength, destination.Height); - using Buffer2D xKernelBuffer = configuration.MemoryAllocator.Allocate2D(xLength, destination.Height); - - int maxX = source.Width - 1; - int maxY = source.Height - 1; - var maxSourceExtents = new Vector4(maxX, maxY, maxX, maxY); - var operation = new ProjectiveOperation( configuration, source, destination, - yKernelBuffer, - xKernelBuffer, in sampler, - matrix, - radialExtents, - maxSourceExtents); + matrix); - ParallelRowIterator.IterateRows, Vector4>( + ParallelRowIterator.IterateRowIntervals, Vector4>( configuration, destination.Bounds(), in operation); @@ -117,7 +100,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms private readonly ImageFrame destination; private readonly Rectangle bounds; private readonly Matrix4x4 matrix; - private readonly int maxX; [MethodImpl(InliningOptions.ShortMethod)] public NNProjectiveOperation( @@ -129,15 +111,15 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms this.destination = destination; this.bounds = source.Bounds(); this.matrix = matrix; - this.maxX = destination.Width; } [MethodImpl(InliningOptions.ShortMethod)] public void Invoke(int y) { + Buffer2D sourceBuffer = this.source.PixelBuffer; Span destRow = this.destination.GetPixelRowSpan(y); - for (int x = 0; x < this.maxX; x++) + for (int x = 0; x < destRow.Length; x++) { Vector2 point = TransformUtils.ProjectiveTransform2D(x, y, this.matrix); int px = (int)MathF.Round(point.X); @@ -145,84 +127,181 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms if (this.bounds.Contains(px, py)) { - destRow[x] = this.source[px, py]; + destRow[x] = sourceBuffer.GetElementUnsafe(px, py); } } } } - private readonly struct ProjectiveOperation : IRowOperation + private readonly struct ProjectiveOperation : IRowIntervalOperation where TResampler : struct, IResampler { private readonly Configuration configuration; private readonly ImageFrame source; private readonly ImageFrame destination; - private readonly Buffer2D yKernelBuffer; - private readonly Buffer2D xKernelBuffer; private readonly TResampler sampler; private readonly Matrix4x4 matrix; - private readonly Vector2 radialExtents; - private readonly Vector4 maxSourceExtents; - private readonly int maxX; + private readonly float yRadius; + private readonly float xRadius; [MethodImpl(InliningOptions.ShortMethod)] public ProjectiveOperation( Configuration configuration, ImageFrame source, ImageFrame destination, - Buffer2D yKernelBuffer, - Buffer2D xKernelBuffer, in TResampler sampler, - Matrix4x4 matrix, - Vector2 radialExtents, - Vector4 maxSourceExtents) + Matrix4x4 matrix) { this.configuration = configuration; this.source = source; this.destination = destination; - this.yKernelBuffer = yKernelBuffer; - this.xKernelBuffer = xKernelBuffer; this.sampler = sampler; this.matrix = matrix; - this.radialExtents = radialExtents; - this.maxSourceExtents = maxSourceExtents; - this.maxX = destination.Width; + + this.yRadius = LinearTransformUtility.GetSamplingRadius(in sampler, source.Height, destination.Height); + this.xRadius = LinearTransformUtility.GetSamplingRadius(in sampler, source.Width, destination.Width); } [MethodImpl(InliningOptions.ShortMethod)] - public void Invoke(int y, Span span) + public void Invoke(in RowInterval rows, Span span) { - Buffer2D sourceBuffer = this.source.PixelBuffer; + if (RuntimeEnvironment.IsOSPlatform(OSPlatform.OSX) + && RuntimeEnvironment.IsNetCore) + { + // There's something wrong with the JIT in .NET Core 3.1 on certain + // MacOSX machines so we have to use different pipelines. + // It's: + // - Not reproducable locally + // - Doesn't seem to be triggered by the bulk Numerics.UnPremultiply method but by caller. + // https://github.com/SixLabors/ImageSharp/pull/1591 + this.InvokeMacOSX(in rows, span); + return; + } - PixelOperations.Instance.ToVector4( - this.configuration, - this.destination.GetPixelRowSpan(y), - span); + Matrix4x4 matrix = this.matrix; + TResampler sampler = this.sampler; + float yRadius = this.yRadius; + float xRadius = this.xRadius; + int maxY = this.source.Height - 1; + int maxX = this.source.Width - 1; - ref float yKernelSpanRef = ref MemoryMarshal.GetReference(this.yKernelBuffer.GetRowSpan(y)); - ref float xKernelSpanRef = ref MemoryMarshal.GetReference(this.xKernelBuffer.GetRowSpan(y)); + Buffer2D sourceBuffer = this.source.PixelBuffer; - for (int x = 0; x < this.maxX; x++) + for (int y = rows.Min; y < rows.Max; y++) { - // Use the single precision position to calculate correct bounding pixels - // otherwise we get rogue pixels outside of the bounds. - Vector2 point = TransformUtils.ProjectiveTransform2D(x, y, this.matrix); - LinearTransformUtils.Convolve( - in this.sampler, - point, - sourceBuffer, + Span rowSpan = this.destination.GetPixelRowSpan(y); + PixelOperations.Instance.ToVector4( + this.configuration, + rowSpan, + span, + PixelConversionModifiers.Scale); + + for (int x = 0; x < span.Length; x++) + { + Vector2 point = TransformUtils.ProjectiveTransform2D(x, y, matrix); + float pY = point.Y; + float pX = point.X; + + int top = LinearTransformUtility.GetRangeStart(yRadius, pY, maxY); + int bottom = LinearTransformUtility.GetRangeEnd(yRadius, pY, maxY); + int left = LinearTransformUtility.GetRangeStart(xRadius, pX, maxX); + int right = LinearTransformUtility.GetRangeEnd(xRadius, pX, maxX); + + if (bottom <= top || right <= left) + { + continue; + } + + Vector4 sum = Vector4.Zero; + for (int yK = top; yK <= bottom; yK++) + { + float yWeight = sampler.GetValue(yK - pY); + + for (int xK = left; xK <= right; xK++) + { + float xWeight = sampler.GetValue(xK - pX); + + Vector4 current = sourceBuffer.GetElementUnsafe(xK, yK).ToScaledVector4(); + Numerics.Premultiply(ref current); + sum += current * xWeight * yWeight; + } + } + + span[x] = sum; + } + + Numerics.UnPremultiply(span); + PixelOperations.Instance.FromVector4Destructive( + this.configuration, span, - x, - ref yKernelSpanRef, - ref xKernelSpanRef, - this.radialExtents, - this.maxSourceExtents); + rowSpan, + PixelConversionModifiers.Scale); } + } + + [ExcludeFromCodeCoverage] + [MethodImpl(InliningOptions.ShortMethod)] + public void InvokeMacOSX(in RowInterval rows, Span span) + { + Matrix4x4 matrix = this.matrix; + TResampler sampler = this.sampler; + float yRadius = this.yRadius; + float xRadius = this.xRadius; + int maxY = this.source.Height - 1; + int maxX = this.source.Width - 1; - PixelOperations.Instance.FromVector4Destructive( - this.configuration, - span, - this.destination.GetPixelRowSpan(y)); + Buffer2D sourceBuffer = this.source.PixelBuffer; + + for (int y = rows.Min; y < rows.Max; y++) + { + Span rowSpan = this.destination.GetPixelRowSpan(y); + PixelOperations.Instance.ToVector4( + this.configuration, + rowSpan, + span, + PixelConversionModifiers.Scale); + + for (int x = 0; x < span.Length; x++) + { + Vector2 point = TransformUtils.ProjectiveTransform2D(x, y, matrix); + float pY = point.Y; + float pX = point.X; + + int top = LinearTransformUtility.GetRangeStart(yRadius, pY, maxY); + int bottom = LinearTransformUtility.GetRangeEnd(yRadius, pY, maxY); + int left = LinearTransformUtility.GetRangeStart(xRadius, pX, maxX); + int right = LinearTransformUtility.GetRangeEnd(xRadius, pX, maxX); + + if (bottom <= top || right <= left) + { + continue; + } + + Vector4 sum = Vector4.Zero; + for (int yK = top; yK <= bottom; yK++) + { + float yWeight = sampler.GetValue(yK - pY); + + for (int xK = left; xK <= right; xK++) + { + float xWeight = sampler.GetValue(xK - pX); + + Vector4 current = sourceBuffer.GetElementUnsafe(xK, yK).ToScaledVector4(); + Numerics.Premultiply(ref current); + sum += current * xWeight * yWeight; + } + } + + Numerics.UnPremultiply(ref sum); + span[x] = sum; + } + + PixelOperations.Instance.FromVector4Destructive( + this.configuration, + span, + rowSpan, + PixelConversionModifiers.Scale); + } } } } diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernel.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernel.cs index 66f885f23a..a67ed92a56 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernel.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernel.cs @@ -13,7 +13,7 @@ using System.Runtime.Intrinsics.X86; namespace SixLabors.ImageSharp.Processing.Processors.Transforms { /// - /// Points to a collection of of weights allocated in . + /// Points to a collection of weights allocated in . /// internal readonly unsafe struct ResizeKernel { @@ -40,7 +40,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms } /// - /// Gets the the length of the kernel. + /// Gets the length of the kernel. /// public int Length { diff --git a/tests/ImageSharp.Benchmarks/Processing/Rotate.cs b/tests/ImageSharp.Benchmarks/Processing/Rotate.cs index 107c47f062..1b8aed0068 100644 --- a/tests/ImageSharp.Benchmarks/Processing/Rotate.cs +++ b/tests/ImageSharp.Benchmarks/Processing/Rotate.cs @@ -21,21 +21,19 @@ namespace SixLabors.ImageSharp.Benchmarks.Processing } } -// #### 21th February 2020 #### +// #### 2021-04-06 #### // -// BenchmarkDotNet=v0.12.0, OS=Windows 10.0.18363 -// Intel Core i7-8650U CPU 1.90GHz(Kaby Lake R), 1 CPU, 8 logical and 4 physical cores -// .NET Core SDK = 3.1.101 +// BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19042 +// Intel Core i7-8650U CPU 1.90GHz (Kaby Lake R), 1 CPU, 8 logical and 4 physical cores +// .NET Core SDK=5.0.201 +// [Host] : .NET Core 5.0.4 (CoreCLR 5.0.421.11614, CoreFX 5.0.421.11614), X64 RyuJIT +// Job-HQWHDJ : .NET Framework 4.8 (4.8.4341.0), X64 RyuJIT +// Job-RPXLFC : .NET Core 2.1.26 (CoreCLR 4.6.29812.02, CoreFX 4.6.29812.01), X64 RyuJIT +// Job-YMSKIM : .NET Core 3.1.13 (CoreCLR 4.700.21.11102, CoreFX 4.700.21.11602), X64 RyuJIT // -// [Host] : .NET Core 3.1.1 (CoreCLR 4.700.19.60701, CoreFX 4.700.19.60801), X64 RyuJIT -// Job-HOGSNT : .NET Framework 4.8 (4.8.4121.0), X64 RyuJIT -// Job-FKDHXC : .NET Core 2.1.15 (CoreCLR 4.6.28325.01, CoreFX 4.6.28327.02), X64 RyuJIT -// Job-ODABAZ : .NET Core 3.1.1 (CoreCLR 4.700.19.60701, CoreFX 4.700.19.60801), X64 RyuJIT // -// IterationCount=3 LaunchCount=1 WarmupCount=3 -// -// | Method | Runtime | Mean | Error | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated | -// |--------- |-------------- |---------:|---------:|---------:|------:|------:|------:|----------:| -// | DoRotate | .NET 4.7.2 | 28.77 ms | 3.304 ms | 0.181 ms | - | - | - | 6.5 KB | -// | DoRotate | .NET Core 2.1 | 16.27 ms | 1.044 ms | 0.057 ms | - | - | - | 5.25 KB | -// | DoRotate | .NET Core 3.1 | 17.12 ms | 4.352 ms | 0.239 ms | - | - | - | 6.57 KB | +// | Method | Job | Runtime | Mean | Error | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated | +// |--------- |----------- |-------------- |---------:|---------:|---------:|------:|------:|------:|----------:| +// | DoRotate | Job-BAUEPW | .NET 4.7.2 | 30.73 ms | 0.397 ms | 0.331 ms | - | - | - | 6.75 KB | +// | DoRotate | Job-SNWMCN | .NET Core 2.1 | 16.31 ms | 0.317 ms | 0.352 ms | - | - | - | 5.25 KB | +// | DoRotate | Job-MRMBJZ | .NET Core 3.1 | 12.21 ms | 0.239 ms | 0.245 ms | - | - | - | 6.61 KB | diff --git a/tests/ImageSharp.Benchmarks/Processing/Skew.cs b/tests/ImageSharp.Benchmarks/Processing/Skew.cs index b77f0dcd6b..1c92b9f3c5 100644 --- a/tests/ImageSharp.Benchmarks/Processing/Skew.cs +++ b/tests/ImageSharp.Benchmarks/Processing/Skew.cs @@ -21,21 +21,19 @@ namespace SixLabors.ImageSharp.Benchmarks.Processing } } -// #### 21th February 2020 #### +// #### 2021-04-06 #### // -// BenchmarkDotNet=v0.12.0, OS=Windows 10.0.18363 -// Intel Core i7-8650U CPU 1.90GHz(Kaby Lake R), 1 CPU, 8 logical and 4 physical cores -// .NET Core SDK = 3.1.101 +// BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19042 +// Intel Core i7-8650U CPU 1.90GHz (Kaby Lake R), 1 CPU, 8 logical and 4 physical cores +// .NET Core SDK=5.0.201 +// [Host] : .NET Core 5.0.4 (CoreCLR 5.0.421.11614, CoreFX 5.0.421.11614), X64 RyuJIT +// Job-HQWHDJ : .NET Framework 4.8 (4.8.4341.0), X64 RyuJIT +// Job-RPXLFC : .NET Core 2.1.26 (CoreCLR 4.6.29812.02, CoreFX 4.6.29812.01), X64 RyuJIT +// Job-YMSKIM : .NET Core 3.1.13 (CoreCLR 4.700.21.11102, CoreFX 4.700.21.11602), X64 RyuJIT // -// [Host] : .NET Core 3.1.1 (CoreCLR 4.700.19.60701, CoreFX 4.700.19.60801), X64 RyuJIT -// Job-VKKTMF : .NET Framework 4.8 (4.8.4121.0), X64 RyuJIT -// Job-KTVRKR : .NET Core 2.1.15 (CoreCLR 4.6.28325.01, CoreFX 4.6.28327.02), X64 RyuJIT -// Job-EONWDB : .NET Core 3.1.1 (CoreCLR 4.700.19.60701, CoreFX 4.700.19.60801), X64 RyuJIT // -// IterationCount=3 LaunchCount=1 WarmupCount=3 -// -// | Method | Runtime | Mean | Error | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated | -// |------- |-------------- |---------:|----------:|---------:|------:|------:|------:|----------:| -// | DoSkew | .NET 4.7.2 | 24.60 ms | 33.971 ms | 1.862 ms | - | - | - | 6.5 KB | -// | DoSkew | .NET Core 2.1 | 12.13 ms | 2.256 ms | 0.124 ms | - | - | - | 5.21 KB | -// | DoSkew | .NET Core 3.1 | 12.83 ms | 1.442 ms | 0.079 ms | - | - | - | 6.57 KB | +// | Method | Job | Runtime | Mean | Error | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated | +// |------- |----------- |-------------- |----------:|----------:|----------:|------:|------:|------:|----------:| +// | DoSkew | Job-YEGFRQ | .NET 4.7.2 | 23.563 ms | 0.0731 ms | 0.0570 ms | - | - | - | 6.75 KB | +// | DoSkew | Job-HZHOGR | .NET Core 2.1 | 13.700 ms | 0.2727 ms | 0.5122 ms | - | - | - | 5.25 KB | +// | DoSkew | Job-LTEUKY | .NET Core 3.1 | 9.971 ms | 0.0254 ms | 0.0225 ms | - | - | - | 6.61 KB | diff --git a/tests/ImageSharp.Tests/Helpers/RuntimeEnvironmentTests.cs b/tests/ImageSharp.Tests/Helpers/RuntimeEnvironmentTests.cs new file mode 100644 index 0000000000..8074b8b150 --- /dev/null +++ b/tests/ImageSharp.Tests/Helpers/RuntimeEnvironmentTests.cs @@ -0,0 +1,41 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using System.Runtime.InteropServices; +using Xunit; + +#pragma warning disable IDE0022 // Use expression body for methods +namespace SixLabors.ImageSharp.Tests.Helpers +{ + public class RuntimeEnvironmentTests + { + [Fact] + public void CanDetectNetCore() + { +#if NET5_0_OR_GREATER + Assert.False(RuntimeEnvironment.IsNetCore); +#elif NETCOREAPP + Assert.True(RuntimeEnvironment.IsNetCore); +#else + Assert.False(RuntimeEnvironment.IsNetCore); +#endif + } + + [Fact] + public void CanDetectOSPlatform() + { + if (TestEnvironment.IsLinux) + { + Assert.True(RuntimeEnvironment.IsOSPlatform(OSPlatform.Linux)); + } + else if (TestEnvironment.IsOSX) + { + Assert.True(RuntimeEnvironment.IsOSPlatform(OSPlatform.OSX)); + } + else if (TestEnvironment.IsWindows) + { + Assert.True(RuntimeEnvironment.IsOSPlatform(OSPlatform.Windows)); + } + } + } +} diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/AffineTransformTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/AffineTransformTests.cs index 379f74d094..49a443d927 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Transforms/AffineTransformTests.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/AffineTransformTests.cs @@ -4,7 +4,6 @@ using System; using System.Numerics; using System.Reflection; -using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Processing.Processors.Transforms; @@ -18,9 +17,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Transforms public class AffineTransformTests { private readonly ITestOutputHelper output; - - // 1 byte difference on one color component. - private static readonly ImageComparer ValidatorComparer = ImageComparer.TolerantPercentage(0.0134F, 3); + private static readonly ImageComparer ValidatorComparer = ImageComparer.TolerantPercentage(0.033F, 3); /// /// angleDeg, sx, sy, tx, ty diff --git a/tests/ImageSharp.Tests/TestUtilities/ImagingTestCaseUtility.cs b/tests/ImageSharp.Tests/TestUtilities/ImagingTestCaseUtility.cs index fcde6273f5..8a038a6912 100644 --- a/tests/ImageSharp.Tests/TestUtilities/ImagingTestCaseUtility.cs +++ b/tests/ImageSharp.Tests/TestUtilities/ImagingTestCaseUtility.cs @@ -174,7 +174,7 @@ namespace SixLabors.ImageSharp.Tests appendPixelTypeToFileName, appendSourceFileOrDescription); - encoder = encoder ?? TestEnvironment.GetReferenceEncoder(path); + encoder ??= TestEnvironment.GetReferenceEncoder(path); using (FileStream stream = File.OpenWrite(path)) { diff --git a/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/ImageSharpPngEncoderWithDefaultConfiguration.cs b/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/ImageSharpPngEncoderWithDefaultConfiguration.cs new file mode 100644 index 0000000000..f0a01e45e8 --- /dev/null +++ b/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/ImageSharpPngEncoderWithDefaultConfiguration.cs @@ -0,0 +1,94 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using SixLabors.ImageSharp.Formats; +using SixLabors.ImageSharp.Formats.Png; +using SixLabors.ImageSharp.Memory; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing.Processors.Quantization; + +namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs +{ + /// + /// A Png encoder that uses the ImageSharp core encoder but the default configuration. + /// This allows encoding under environments with restricted memory. + /// + public sealed class ImageSharpPngEncoderWithDefaultConfiguration : IImageEncoder, IPngEncoderOptions + { + /// + public PngBitDepth? BitDepth { get; set; } + + /// + public PngColorType? ColorType { get; set; } + + /// + public PngFilterMethod? FilterMethod { get; set; } + + /// + public PngCompressionLevel CompressionLevel { get; set; } = PngCompressionLevel.DefaultCompression; + + /// + public int TextCompressionThreshold { get; set; } = 1024; + + /// + public float? Gamma { get; set; } + + /// + public IQuantizer Quantizer { get; set; } + + /// + public byte Threshold { get; set; } = byte.MaxValue; + + /// + public PngInterlaceMode? InterlaceMethod { get; set; } + + /// + public PngChunkFilter? ChunkFilter { get; set; } + + /// + public bool IgnoreMetadata { get; set; } + + /// + public PngTransparentColorMode TransparentColorMode { get; set; } + + /// + /// Encodes the image to the specified stream from the . + /// + /// The pixel format. + /// The to encode from. + /// The to encode the image data to. + public void Encode(Image image, Stream stream) + where TPixel : unmanaged, IPixel + { + Configuration configuration = Configuration.Default; + MemoryAllocator allocator = configuration.MemoryAllocator; + + using var encoder = new PngEncoderCore(allocator, configuration, new PngEncoderOptions(this)); + encoder.Encode(image, stream); + } + + /// + /// Encodes the image to the specified stream from the . + /// + /// The pixel format. + /// The to encode from. + /// The to encode the image data to. + /// The token to monitor for cancellation requests. + /// A representing the asynchronous operation. + public async Task EncodeAsync(Image image, Stream stream, CancellationToken cancellationToken) + where TPixel : unmanaged, IPixel + { + Configuration configuration = Configuration.Default; + MemoryAllocator allocator = configuration.MemoryAllocator; + + // The introduction of a local variable that refers to an object the implements + // IDisposable means you must use async/await, where the compiler generates the + // state machine and a continuation. + using var encoder = new PngEncoderCore(allocator, configuration, new PngEncoderOptions(this)); + await encoder.EncodeAsync(image, stream, cancellationToken).ConfigureAwait(false); + } + } +} diff --git a/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Formats.cs b/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Formats.cs index 6e204e2d48..ea5b2f6652 100644 --- a/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Formats.cs +++ b/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Formats.cs @@ -57,10 +57,10 @@ namespace SixLabors.ImageSharp.Tests new GifConfigurationModule(), new TgaConfigurationModule()); - // Magick codecs should work on all platforms - IImageEncoder pngEncoder = IsWindows ? (IImageEncoder)SystemDrawingReferenceEncoder.Png : new PngEncoder(); + IImageEncoder pngEncoder = IsWindows ? (IImageEncoder)SystemDrawingReferenceEncoder.Png : new ImageSharpPngEncoderWithDefaultConfiguration(); IImageEncoder bmpEncoder = IsWindows ? (IImageEncoder)SystemDrawingReferenceEncoder.Bmp : new BmpEncoder(); + // Magick codecs should work on all platforms cfg.ConfigureCodecs( PngFormat.Instance, MagickReferenceDecoder.Instance, diff --git a/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.cs b/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.cs index cb8a0df42f..587b274a10 100644 --- a/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.cs +++ b/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.cs @@ -26,6 +26,8 @@ namespace SixLabors.ImageSharp.Tests private static readonly Lazy RunsOnCiLazy = new Lazy(() => bool.TryParse(Environment.GetEnvironmentVariable("CI"), out bool isCi) && isCi); + private static readonly Lazy RunsWithCodeCoverageLazy = new Lazy(() => bool.TryParse(Environment.GetEnvironmentVariable("codecov"), out bool isCodeCov) && isCodeCov); + private static readonly Lazy NetCoreVersionLazy = new Lazy(GetNetCoreVersion); static TestEnvironment() => PrepareRemoteExecutor(); @@ -42,6 +44,11 @@ namespace SixLabors.ImageSharp.Tests /// internal static bool RunsOnCI => RunsOnCiLazy.Value; + /// + /// Gets a value indicating whether test execution is running with code coverage testing enabled. + /// + internal static bool RunsWithCodeCoverage => RunsWithCodeCoverageLazy.Value; + internal static string SolutionDirectoryFullPath => SolutionDirectoryFullPathLazy.Value; private static readonly FileInfo TestAssemblyFile = diff --git a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs index 073db1efed..1c5aedd9b7 100644 --- a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs +++ b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs @@ -34,18 +34,16 @@ namespace SixLabors.ImageSharp.Tests bool appendPixelTypeToFileName = true, bool appendSourceFileOrDescription = true, IImageEncoder encoder = null) - { - image.DebugSave( + => image.DebugSave( provider, (object)testOutputDetails, extension, appendPixelTypeToFileName, appendSourceFileOrDescription, encoder); - } /// - /// Saves the image only when not running in the CI server. + /// Saves the image for debugging purpose. /// /// The image. /// The image provider. @@ -64,12 +62,11 @@ namespace SixLabors.ImageSharp.Tests bool appendSourceFileOrDescription = true, IImageEncoder encoder = null) { - if (TestEnvironment.RunsOnCI) + if (TestEnvironment.RunsWithCodeCoverage) { return image; } - // We are running locally then we want to save it out provider.Utility.SaveTestOutputFile( image, extension, @@ -86,12 +83,10 @@ namespace SixLabors.ImageSharp.Tests IImageEncoder encoder, FormattableString testOutputDetails, bool appendPixelTypeToFileName = true) - { - image.DebugSave(provider, encoder, (object)testOutputDetails, appendPixelTypeToFileName); - } + => image.DebugSave(provider, encoder, (object)testOutputDetails, appendPixelTypeToFileName); /// - /// Saves the image only when not running in the CI server. + /// Saves the image for debugging purpose. /// /// The image /// The image provider @@ -104,19 +99,11 @@ namespace SixLabors.ImageSharp.Tests IImageEncoder encoder, object testOutputDetails = null, bool appendPixelTypeToFileName = true) - { - if (TestEnvironment.RunsOnCI) - { - return; - } - - // We are running locally then we want to save it out - provider.Utility.SaveTestOutputFile( + => provider.Utility.SaveTestOutputFile( image, encoder: encoder, testOutputDetails: testOutputDetails, appendPixelTypeToFileName: appendPixelTypeToFileName); - } public static Image DebugSaveMultiFrame( this Image image, @@ -126,17 +113,17 @@ namespace SixLabors.ImageSharp.Tests bool appendPixelTypeToFileName = true) where TPixel : unmanaged, IPixel { - if (TestEnvironment.RunsOnCI) + if (TestEnvironment.RunsWithCodeCoverage) { return image; } - // We are running locally then we want to save it out provider.Utility.SaveTestOutputFileMultiFrame( image, extension, testOutputDetails: testOutputDetails, appendPixelTypeToFileName: appendPixelTypeToFileName); + return image; } @@ -149,15 +136,13 @@ namespace SixLabors.ImageSharp.Tests bool appendPixelTypeToFileName = true, bool appendSourceFileOrDescription = true) where TPixel : unmanaged, IPixel - { - return image.CompareToReferenceOutput( + => image.CompareToReferenceOutput( provider, (object)testOutputDetails, extension, grayscale, appendPixelTypeToFileName, appendSourceFileOrDescription); - } /// /// Compares the image against the expected Reference output, throws an exception if the images are not similar enough. @@ -181,8 +166,7 @@ namespace SixLabors.ImageSharp.Tests bool appendPixelTypeToFileName = true, bool appendSourceFileOrDescription = true) where TPixel : unmanaged, IPixel - { - return CompareToReferenceOutput( + => CompareToReferenceOutput( image, ImageComparer.Tolerant(), provider, @@ -191,7 +175,6 @@ namespace SixLabors.ImageSharp.Tests grayscale, appendPixelTypeToFileName, appendSourceFileOrDescription); - } public static Image CompareToReferenceOutput( this Image image, @@ -202,15 +185,13 @@ namespace SixLabors.ImageSharp.Tests bool grayscale = false, bool appendPixelTypeToFileName = true) where TPixel : unmanaged, IPixel - { - return image.CompareToReferenceOutput( + => image.CompareToReferenceOutput( comparer, provider, (object)testOutputDetails, extension, grayscale, appendPixelTypeToFileName); - } /// /// Compares the image against the expected Reference output, throws an exception if the images are not similar enough. @@ -263,8 +244,7 @@ namespace SixLabors.ImageSharp.Tests bool appendPixelTypeToFileName = true, bool appendSourceFileOrDescription = true) where TPixel : unmanaged, IPixel - { - return image.CompareFirstFrameToReferenceOutput( + => image.CompareFirstFrameToReferenceOutput( comparer, provider, (object)testOutputDetails, @@ -272,7 +252,6 @@ namespace SixLabors.ImageSharp.Tests grayscale, appendPixelTypeToFileName, appendSourceFileOrDescription); - } public static Image CompareFirstFrameToReferenceOutput( this Image image, @@ -508,9 +487,7 @@ namespace SixLabors.ImageSharp.Tests ITestImageProvider provider, IImageDecoder referenceDecoder = null) where TPixel : unmanaged, IPixel - { - return CompareToOriginal(image, provider, ImageComparer.Tolerant(), referenceDecoder); - } + => CompareToOriginal(image, provider, ImageComparer.Tolerant(), referenceDecoder); public static Image CompareToOriginal( this Image image, @@ -584,14 +561,12 @@ namespace SixLabors.ImageSharp.Tests bool appendPixelTypeToFileName = true, bool appendSourceFileOrDescription = true) where TPixel : unmanaged, IPixel - { - provider.VerifyOperation( + => provider.VerifyOperation( ImageComparer.Tolerant(), operation, testOutputDetails, appendPixelTypeToFileName, appendSourceFileOrDescription); - } /// /// Utility method for doing the following in one step: @@ -606,14 +581,12 @@ namespace SixLabors.ImageSharp.Tests bool appendPixelTypeToFileName = true, bool appendSourceFileOrDescription = true) where TPixel : unmanaged, IPixel - { - provider.VerifyOperation( + => provider.VerifyOperation( comparer, operation, $"", appendPixelTypeToFileName, appendSourceFileOrDescription); - } /// /// Utility method for doing the following in one step: @@ -627,9 +600,7 @@ namespace SixLabors.ImageSharp.Tests bool appendPixelTypeToFileName = true, bool appendSourceFileOrDescription = true) where TPixel : unmanaged, IPixel - { - provider.VerifyOperation(operation, $"", appendPixelTypeToFileName, appendSourceFileOrDescription); - } + => provider.VerifyOperation(operation, $"", appendPixelTypeToFileName, appendSourceFileOrDescription); /// /// Loads the expected image with a reference decoder + compares it to . diff --git a/tests/ImageSharp.Tests/TestUtilities/Tests/TestEnvironmentTests.cs b/tests/ImageSharp.Tests/TestUtilities/Tests/TestEnvironmentTests.cs index 67f11e8978..84b9297295 100644 --- a/tests/ImageSharp.Tests/TestUtilities/Tests/TestEnvironmentTests.cs +++ b/tests/ImageSharp.Tests/TestUtilities/Tests/TestEnvironmentTests.cs @@ -8,7 +8,6 @@ using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.Formats.Bmp; using SixLabors.ImageSharp.Formats.Gif; using SixLabors.ImageSharp.Formats.Jpeg; -using SixLabors.ImageSharp.Formats.Png; using SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs; using Xunit; @@ -85,7 +84,7 @@ namespace SixLabors.ImageSharp.Tests } [Theory] - [InlineData("lol/foo.png", typeof(PngEncoder))] + [InlineData("lol/foo.png", typeof(ImageSharpPngEncoderWithDefaultConfiguration))] [InlineData("lol/Rofl.bmp", typeof(BmpEncoder))] [InlineData("lol/Baz.JPG", typeof(JpegEncoder))] [InlineData("lol/Baz.gif", typeof(GifEncoder))] diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(50)_S(1,1)_T(-20,-10).png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(50)_S(1,1)_T(-20,-10).png index ec3bfb5d11..49c7795fe5 100644 --- a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(50)_S(1,1)_T(-20,-10).png +++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50_R(50)_S(1,1)_T(-20,-10).png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:57376aa4446fc2d034d2a0cb627163ac416d1b6768b063b2c11ccf8517443bda -size 10135 +oid sha256:2ef489dc0837b382ad7c7ead6b7c7042dfbfba39902d4cc81b5f3805d5b03967 +size 9175 diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50__original.png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50__original.png index bdad18d1dc..a6ff73cf83 100644 --- a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50__original.png +++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_RotateScaleTranslate_Rgba32_TestPattern100x50__original.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9c83b59471a50df9e1d7b8f0e35c50aa417cd3be1730d6369f47f5cc99b87cef -size 6405 +oid sha256:99d6c1d6b092a2feba2aebe2e09c521c3cc9682f3d748927cdc3cbaa38448b28 +size 710 diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Bicubic.png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Bicubic.png index 526096e7c0..a909194b0b 100644 --- a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Bicubic.png +++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Bicubic.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f9f149093c5d9d487f3e16cb59e6807ea6ce581b5c307e57aeb4edaf921de9ca -size 15138 +oid sha256:04a3b84c668758b586f4d998f080ef96b09f726b0298b28f5dd3d739b0e90744 +size 13138 diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_CatmullRom.png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_CatmullRom.png index 526096e7c0..a909194b0b 100644 --- a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_CatmullRom.png +++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_CatmullRom.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f9f149093c5d9d487f3e16cb59e6807ea6ce581b5c307e57aeb4edaf921de9ca -size 15138 +oid sha256:04a3b84c668758b586f4d998f080ef96b09f726b0298b28f5dd3d739b0e90744 +size 13138 diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos2.png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos2.png index b3439a5c88..e248b6d918 100644 --- a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos2.png +++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos2.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0c7467702a784807a3a5813a75d5f643655ed5ad427e978d6ee079da67b05961 -size 15363 +oid sha256:6ea7ca66c31474c0bb9673a0d85c1c7465e387ebabf4e2d1e8f9daebfc7c8f34 +size 13956 diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos3.png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos3.png index 4622adab47..5c81a5f5da 100644 --- a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos3.png +++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos3.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a836c63c0912f69683bc9c8f59687b11e6b84f257816a01ff979ad0b6f4ab656 -size 19059 +oid sha256:6dd98ac441f3c20ea999f058c7b21601d5981d46e9b77709c25f2930a64edb93 +size 17148 diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos5.png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos5.png index 753764631b..1647aae60d 100644 --- a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos5.png +++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos5.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:05de30dc282a0b8a096a476f689a1d2b6bb298098692a2f665c59c3d14902aa6 -size 20426 +oid sha256:d5c4772d9b9dc57c4b5d47450ec9d02d96e40656cf2015f171b5425945f8a598 +size 18726 diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos8.png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos8.png index c0840e5f76..3949197248 100644 --- a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos8.png +++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Lanczos8.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8892179d8edf96583900048bdd895eff24e57be0105e91efafe1de971414db0e -size 22457 +oid sha256:bb025c4470cec1b0d6544924e46b84cbdb90d75da5d0f879f2c7d7ec9875dee2 +size 20574 diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_MitchellNetravali.png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_MitchellNetravali.png index 094777eec3..da8413be52 100644 --- a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_MitchellNetravali.png +++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_MitchellNetravali.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2f351ec6ae6df56537e383494984c2fbcf35a66c44a6ce53d6fd8d6d74a330f3 -size 15342 +oid sha256:c4abaa06827cb779026f8fbb655692bdd8adab37ae5b00c3ae18ebea456eb8d9 +size 13459 diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Robidoux.png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Robidoux.png index c580f0cffd..5bdf261405 100644 --- a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Robidoux.png +++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Robidoux.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b0fb38dbdded32a1518d62ac79f4aa88133aaddad947f23c1066dc33d6938e0b -size 15372 +oid sha256:3435ade8f7988779280820342e16881b049f717735d2218ac5a971a1bd807db1 +size 13448 diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_RobidouxSharp.png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_RobidouxSharp.png index 4c0bb37bc3..0e2dbf2565 100644 --- a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_RobidouxSharp.png +++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_RobidouxSharp.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0be42a5fd4ff10680af74a99ed1e0561ae38181f4efe4641bd63891222dcdf3c -size 15283 +oid sha256:f0098aa45e820544dd16a58396fa70860886b7d79900916ed97376a8328a5ff2 +size 13367 diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Spline.png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Spline.png index 7527157d50..27ed945dc8 100644 --- a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Spline.png +++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Spline.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1eabaf35e0dda3eccd5e8866ddd65e0c45557c8d5cc29423a99e2f377ee1bfa9 -size 16271 +oid sha256:7729495277b80a42e24dd8f40cdd8a280443575710fb4e199e4871c28b558271 +size 14253 diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Triangle.png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Triangle.png index 1ee2a15ff6..90c47e96d7 100644 --- a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Triangle.png +++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Triangle.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5ab9bea8f45e7d29d7a8c5e3d0182c0f3f3aa7014aa358883dee53db6dfeb3f7 -size 14076 +oid sha256:a2304c234b93bdabaa018263dec70e62090ad1bbb7005ef62643b88600a863fb +size 12157 diff --git a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Welch.png b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Welch.png index d3b8938091..581b229500 100644 --- a/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Welch.png +++ b/tests/Images/External/ReferenceOutput/AffineTransformTests/Transform_WithSampler_Rgba32_TestPattern150x150_Welch.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ea452bc46c508f6990870a34d908224a58aa350c4ccebabd4fa6ba138e8034a0 -size 18383 +oid sha256:54b0da9646b7f4cf83df784d69dfbec48e0bdc1788d70a9872817543f72f57c1 +size 16829 diff --git a/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/DrawTransformed.png b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/DrawTransformed.png index bfb9ab5edf..c04521ebc7 100644 --- a/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/DrawTransformed.png +++ b/tests/Images/External/ReferenceOutput/Drawing/DrawImageTests/DrawTransformed.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2c83df7a2f70aec8f150799055ce42db09568b47b95216c91a79233ce69381d5 -size 191563 +oid sha256:233d8c6c9e101dddf5d210d47c7a20807f8f956738289068ea03b774258ef8c6 +size 182754 From 06f9e2483a41f2cfc0313352976d76b05b34af21 Mon Sep 17 00:00:00 2001 From: Clinton Ingram Date: Thu, 15 Apr 2021 15:52:25 -0700 Subject: [PATCH 2/6] Update PULL_REQUEST_TEMPLATE.md --- .github/PULL_REQUEST_TEMPLATE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 4be3511650..8709e1318d 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -2,7 +2,7 @@ - [ ] I have written a descriptive pull-request title - [ ] I have verified that there are no overlapping [pull-requests](https://github.com/SixLabors/ImageSharp/pulls) open -- [ ] I have verified that I am following matches the existing coding patterns and practice as demonstrated in the repository. These follow strict Stylecop rules :cop:. +- [ ] I have verified that I am following the existing coding patterns and practice as demonstrated in the repository. These follow strict Stylecop rules :cop:. - [ ] I have provided test coverage for my change (where applicable) ### Description From 14954cf5f240c7a12a4ddeaae17058abe930d2db Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Fri, 16 Apr 2021 17:42:05 +0100 Subject: [PATCH 3/6] Update to latest config/ruleset --- .editorconfig | 143 +++++++++++++++++++++++------------------- shared-infrastructure | 2 +- 2 files changed, 80 insertions(+), 65 deletions(-) diff --git a/.editorconfig b/.editorconfig index 83670fa830..03036f8a53 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,5 +1,5 @@ -# Version: 1.6.2 (Using https://semver.org/) -# Updated: 2020-11-02 +# Version: 2.1.0 (Using https://semver.org/) +# Updated: 2021-03-03 # See https://github.com/RehanSaeed/EditorConfig/releases for release notes. # See https://github.com/RehanSaeed/EditorConfig for updates to this file. # See http://EditorConfig.org for more information about .editorconfig files. @@ -60,87 +60,84 @@ indent_size = 2 [*.{cmd,bat}] end_of_line = crlf +# Bash Files +[*.sh] +end_of_line = lf + # Makefiles [Makefile] indent_style = tab ########################################## -# File Header (Uncomment to support file headers) -# https://docs.microsoft.com/visualstudio/ide/reference/add-file-header +# Default .NET Code Style Severities +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/configuration-options#scope ########################################## -# [*.{cs,csx,cake,vb,vbx,tt,ttinclude}] -file_header_template = Copyright (c) Six Labors.\nLicensed under the Apache License, Version 2.0. - -# SA1636: File header copyright text should match -# Justification: .editorconfig supports file headers. If this is changed to a value other than "none", a stylecop.json file will need to added to the project. -# dotnet_diagnostic.SA1636.severity = none +[*.{cs,csx,cake,vb,vbx}] +# Default Severity for all .NET Code Style rules below +dotnet_analyzer_diagnostic.severity = warning ########################################## -# .NET Language Conventions -# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions +# Language Rules +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/language-rules ########################################## -# .NET Code Style Settings -# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#net-code-style-settings +# .NET Style Rules +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/language-rules#net-style-rules [*.{cs,csx,cake,vb,vbx}] # "this." and "Me." qualifiers -# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#this-and-me dotnet_style_qualification_for_field = true:warning dotnet_style_qualification_for_property = true:warning dotnet_style_qualification_for_method = true:warning dotnet_style_qualification_for_event = true:warning # Language keywords instead of framework type names for type references -# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#language-keywords dotnet_style_predefined_type_for_locals_parameters_members = true:warning dotnet_style_predefined_type_for_member_access = true:warning # Modifier preferences -# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#normalize-modifiers dotnet_style_require_accessibility_modifiers = always:warning csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:warning visual_basic_preferred_modifier_order = Partial,Default,Private,Protected,Public,Friend,NotOverridable,Overridable,MustOverride,Overloads,Overrides,MustInherit,NotInheritable,Static,Shared,Shadows,ReadOnly,WriteOnly,Dim,Const,WithEvents,Widening,Narrowing,Custom,Async:warning dotnet_style_readonly_field = true:warning # Parentheses preferences -# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#parentheses-preferences dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:warning dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:warning dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:warning -dotnet_style_parentheses_in_other_operators = never_if_unnecessary:suggestion +dotnet_style_parentheses_in_other_operators = always_for_clarity:suggestion # Expression-level preferences -# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#expression-level-preferences dotnet_style_object_initializer = true:warning dotnet_style_collection_initializer = true:warning dotnet_style_explicit_tuple_names = true:warning dotnet_style_prefer_inferred_tuple_names = true:warning dotnet_style_prefer_inferred_anonymous_type_member_names = true:warning dotnet_style_prefer_auto_properties = true:warning -dotnet_style_prefer_is_null_check_over_reference_equality_method = true:warning dotnet_style_prefer_conditional_expression_over_assignment = false:suggestion +dotnet_diagnostic.IDE0045.severity = suggestion dotnet_style_prefer_conditional_expression_over_return = false:suggestion +dotnet_diagnostic.IDE0046.severity = suggestion dotnet_style_prefer_compound_assignment = true:warning +dotnet_style_prefer_simplified_interpolation = true:warning +dotnet_style_prefer_simplified_boolean_expressions = true:warning # Null-checking preferences -# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#null-checking-preferences dotnet_style_coalesce_expression = true:warning dotnet_style_null_propagation = true:warning -# Parameter preferences -# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#parameter-preferences -dotnet_code_quality_unused_parameters = all:warning -# More style options (Undocumented) -# https://github.com/MicrosoftDocs/visualstudio-docs/issues/3641 +dotnet_style_prefer_is_null_check_over_reference_equality_method = true:warning +# File header preferences +file_header_template = Copyright (c) Six Labors.\nLicensed under the Apache License, Version 2.0. +# SA1636: File header copyright text should match +# Justification: .editorconfig supports file headers. If this is changed to a value other than "none", a stylecop.json file will need to added to the project. +# dotnet_diagnostic.SA1636.severity = none + +# Undocumented dotnet_style_operator_placement_when_wrapping = end_of_line -# https://github.com/dotnet/roslyn/pull/40070 -dotnet_style_prefer_simplified_interpolation = true:warning -# C# Code Style Settings -# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#c-code-style-settings +# C# Style Rules +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/language-rules#c-style-rules [*.{cs,csx,cake}] -# Implicit and explicit types -# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#implicit-and-explicit-types +# 'var' preferences csharp_style_var_for_built_in_types = never csharp_style_var_when_type_is_apparent = true:warning csharp_style_var_elsewhere = false:warning # Expression-bodied members -# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#expression-bodied-members csharp_style_expression_bodied_methods = true:warning csharp_style_expression_bodied_constructors = true:warning csharp_style_expression_bodied_operators = true:warning @@ -149,47 +146,64 @@ csharp_style_expression_bodied_indexers = true:warning csharp_style_expression_bodied_accessors = true:warning csharp_style_expression_bodied_lambdas = true:warning csharp_style_expression_bodied_local_functions = true:warning -# Pattern matching -# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#pattern-matching +# Pattern matching preferences csharp_style_pattern_matching_over_is_with_cast_check = true:warning csharp_style_pattern_matching_over_as_with_null_check = true:warning -# Inlined variable declarations -# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#inlined-variable-declarations -csharp_style_inlined_variable_declaration = true:warning +csharp_style_prefer_switch_expression = true:warning +csharp_style_prefer_pattern_matching = true:warning +csharp_style_prefer_not_pattern = true:warning # Expression-level preferences -# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#expression-level-preferences +csharp_style_inlined_variable_declaration = true:warning csharp_prefer_simple_default_expression = true:warning +csharp_style_pattern_local_over_anonymous_function = true:warning +csharp_style_deconstructed_variable_declaration = true:warning +csharp_style_prefer_index_operator = true:warning +csharp_style_prefer_range_operator = true:warning +csharp_style_implicit_object_creation_when_type_is_apparent = true:warning # "Null" checking preferences -# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#c-null-checking-preferences csharp_style_throw_expression = true:warning csharp_style_conditional_delegate_call = true:warning # Code block preferences -# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#code-block-preferences csharp_prefer_braces = true:warning -# Unused value preferences -# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#unused-value-preferences -csharp_style_unused_value_expression_statement_preference = discard_variable:suggestion -csharp_style_unused_value_assignment_preference = discard_variable:suggestion -# Index and range preferences -# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#index-and-range-preferences -csharp_style_prefer_index_operator = true:warning -csharp_style_prefer_range_operator = true:warning -# Miscellaneous preferences -# https://docs.microsoft.com/visualstudio/ide/editorconfig-language-conventions#miscellaneous-preferences -csharp_style_deconstructed_variable_declaration = true:warning -csharp_style_pattern_local_over_anonymous_function = true:warning +csharp_prefer_simple_using_statement = true:suggestion +dotnet_diagnostic.IDE0063.severity = suggestion +# 'using' directive preferences csharp_using_directive_placement = outside_namespace:warning +# Modifier preferences csharp_prefer_static_local_function = true:warning -csharp_prefer_simple_using_statement = true:suggestion ########################################## -# .NET Formatting Conventions -# https://docs.microsoft.com/visualstudio/ide/editorconfig-code-style-settings-reference#formatting-conventions +# Unnecessary Code Rules +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/unnecessary-code-rules ########################################## -# Organize usings -# https://docs.microsoft.com/visualstudio/ide/editorconfig-formatting-conventions#organize-using-directives +# .NET Unnecessary code rules +[*.{cs,csx,cake,vb,vbx}] +dotnet_code_quality_unused_parameters = all:warning +dotnet_remove_unnecessary_suppression_exclusions = none:warning + +# C# Unnecessary code rules +[*.{cs,csx,cake}] +csharp_style_unused_value_expression_statement_preference = discard_variable:suggestion +dotnet_diagnostic.IDE0058.severity = suggestion +csharp_style_unused_value_assignment_preference = discard_variable:suggestion +dotnet_diagnostic.IDE0059.severity = suggestion + +########################################## +# Formatting Rules +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/formatting-rules +########################################## + +# .NET formatting rules +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/formatting-rules#net-formatting-rules +[*.{cs,csx,cake,vb,vbx}] +# Organize using directives dotnet_sort_system_directives_first = true +dotnet_separate_import_directive_groups = false + +# C# formatting rules +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/formatting-rules#c-formatting-rules +[*.{cs,csx,cake}] # Newline options # https://docs.microsoft.com/visualstudio/ide/editorconfig-formatting-conventions#new-line-options csharp_new_line_before_open_brace = all @@ -231,14 +245,14 @@ csharp_space_around_declaration_statements = false csharp_space_before_open_square_brackets = false csharp_space_between_empty_square_brackets = false csharp_space_between_square_brackets = false -# Wrapping options +# Wrap options # https://docs.microsoft.com/visualstudio/ide/editorconfig-formatting-conventions#wrap-options csharp_preserve_single_line_statements = false csharp_preserve_single_line_blocks = true ########################################## -# .NET Naming Conventions -# https://docs.microsoft.com/visualstudio/ide/editorconfig-naming-conventions +# .NET Naming Rules +# https://docs.microsoft.com/dotnet/fundamentals/code-analysis/style-rules/naming-rules ########################################## [*.{cs,csx,cake,vb,vbx}] @@ -261,8 +275,9 @@ dotnet_naming_style.prefix_type_parameters_with_t_style.capitalization = pascal_ dotnet_naming_style.prefix_type_parameters_with_t_style.required_prefix = T # disallowed_style - Anything that has this style applied is marked as disallowed dotnet_naming_style.disallowed_style.capitalization = pascal_case -dotnet_naming_style.disallowed_style.required_prefix = ____RULE_VIOLATION____ -dotnet_naming_style.disallowed_style.required_suffix = ____RULE_VIOLATION____ +# Disabled while we investigate compatibility with VS 16.10 +#dotnet_naming_style.disallowed_style.required_prefix = ____RULE_VIOLATION____ +#dotnet_naming_style.disallowed_style.required_suffix = ____RULE_VIOLATION____ # internal_error_style - This style should never occur... if it does, it indicates a bug in file or in the parser using the file dotnet_naming_style.internal_error_style.capitalization = pascal_case dotnet_naming_style.internal_error_style.required_prefix = ____INTERNAL_ERROR____ diff --git a/shared-infrastructure b/shared-infrastructure index 9b1179f0eb..462f789c52 160000 --- a/shared-infrastructure +++ b/shared-infrastructure @@ -1 +1 @@ -Subproject commit 9b1179f0ebe6a4dfed998252b860fa07fee54363 +Subproject commit 462f789c52809728505833d101b9a96022e0fc3b From a4d05f5fd2d5cd3a6e8845bc609a191a9aa75a85 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Fri, 16 Apr 2021 22:17:57 +0100 Subject: [PATCH 4/6] Add faster InnerLoop build configurations --- Directory.Build.props | 9 ++++ ImageSharp.sln | 54 +++++++++++++++++++ src/ImageSharp/ImageSharp.csproj | 6 +++ .../ImageSharp.Benchmarks.csproj | 15 +++++- .../ImageSharp.Tests.ProfilingSandbox.csproj | 15 +++++- .../app.config | 6 +-- .../ImageSharp.Tests/ImageSharp.Tests.csproj | 15 +++++- 7 files changed, 114 insertions(+), 6 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 3a133efe7a..3df93fcd40 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -18,4 +18,13 @@ + + + false + + + + true + + diff --git a/ImageSharp.sln b/ImageSharp.sln index 8dfab6033c..83208994cb 100644 --- a/ImageSharp.sln +++ b/ImageSharp.sln @@ -482,9 +482,15 @@ Global Debug|Any CPU = Debug|Any CPU Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 + Debug-InnerLoop|Any CPU = Debug-InnerLoop|Any CPU + Debug-InnerLoop|x64 = Debug-InnerLoop|x64 + Debug-InnerLoop|x86 = Debug-InnerLoop|x86 Release|Any CPU = Release|Any CPU Release|x64 = Release|x64 Release|x86 = Release|x86 + Release-InnerLoop|Any CPU = Release-InnerLoop|Any CPU + Release-InnerLoop|x64 = Release-InnerLoop|x64 + Release-InnerLoop|x86 = Release-InnerLoop|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {2AA31A1F-142C-43F4-8687-09ABCA4B3A26}.Debug|Any CPU.ActiveCfg = Debug|Any CPU @@ -493,48 +499,96 @@ Global {2AA31A1F-142C-43F4-8687-09ABCA4B3A26}.Debug|x64.Build.0 = Debug|Any CPU {2AA31A1F-142C-43F4-8687-09ABCA4B3A26}.Debug|x86.ActiveCfg = Debug|Any CPU {2AA31A1F-142C-43F4-8687-09ABCA4B3A26}.Debug|x86.Build.0 = Debug|Any CPU + {2AA31A1F-142C-43F4-8687-09ABCA4B3A26}.Debug-InnerLoop|Any CPU.ActiveCfg = Debug-InnerLoop|Any CPU + {2AA31A1F-142C-43F4-8687-09ABCA4B3A26}.Debug-InnerLoop|Any CPU.Build.0 = Debug-InnerLoop|Any CPU + {2AA31A1F-142C-43F4-8687-09ABCA4B3A26}.Debug-InnerLoop|x64.ActiveCfg = Debug-InnerLoop|Any CPU + {2AA31A1F-142C-43F4-8687-09ABCA4B3A26}.Debug-InnerLoop|x64.Build.0 = Debug-InnerLoop|Any CPU + {2AA31A1F-142C-43F4-8687-09ABCA4B3A26}.Debug-InnerLoop|x86.ActiveCfg = Debug-InnerLoop|Any CPU + {2AA31A1F-142C-43F4-8687-09ABCA4B3A26}.Debug-InnerLoop|x86.Build.0 = Debug-InnerLoop|Any CPU {2AA31A1F-142C-43F4-8687-09ABCA4B3A26}.Release|Any CPU.ActiveCfg = Release|Any CPU {2AA31A1F-142C-43F4-8687-09ABCA4B3A26}.Release|Any CPU.Build.0 = Release|Any CPU {2AA31A1F-142C-43F4-8687-09ABCA4B3A26}.Release|x64.ActiveCfg = Release|Any CPU {2AA31A1F-142C-43F4-8687-09ABCA4B3A26}.Release|x64.Build.0 = Release|Any CPU {2AA31A1F-142C-43F4-8687-09ABCA4B3A26}.Release|x86.ActiveCfg = Release|Any CPU {2AA31A1F-142C-43F4-8687-09ABCA4B3A26}.Release|x86.Build.0 = Release|Any CPU + {2AA31A1F-142C-43F4-8687-09ABCA4B3A26}.Release-InnerLoop|Any CPU.ActiveCfg = Release-InnerLoop|Any CPU + {2AA31A1F-142C-43F4-8687-09ABCA4B3A26}.Release-InnerLoop|Any CPU.Build.0 = Release-InnerLoop|Any CPU + {2AA31A1F-142C-43F4-8687-09ABCA4B3A26}.Release-InnerLoop|x64.ActiveCfg = Release-InnerLoop|Any CPU + {2AA31A1F-142C-43F4-8687-09ABCA4B3A26}.Release-InnerLoop|x64.Build.0 = Release-InnerLoop|Any CPU + {2AA31A1F-142C-43F4-8687-09ABCA4B3A26}.Release-InnerLoop|x86.ActiveCfg = Release-InnerLoop|Any CPU + {2AA31A1F-142C-43F4-8687-09ABCA4B3A26}.Release-InnerLoop|x86.Build.0 = Release-InnerLoop|Any CPU {EA3000E9-2A91-4EC4-8A68-E566DEBDC4F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {EA3000E9-2A91-4EC4-8A68-E566DEBDC4F6}.Debug|Any CPU.Build.0 = Debug|Any CPU {EA3000E9-2A91-4EC4-8A68-E566DEBDC4F6}.Debug|x64.ActiveCfg = Debug|Any CPU {EA3000E9-2A91-4EC4-8A68-E566DEBDC4F6}.Debug|x64.Build.0 = Debug|Any CPU {EA3000E9-2A91-4EC4-8A68-E566DEBDC4F6}.Debug|x86.ActiveCfg = Debug|Any CPU {EA3000E9-2A91-4EC4-8A68-E566DEBDC4F6}.Debug|x86.Build.0 = Debug|Any CPU + {EA3000E9-2A91-4EC4-8A68-E566DEBDC4F6}.Debug-InnerLoop|Any CPU.ActiveCfg = Debug-InnerLoop|Any CPU + {EA3000E9-2A91-4EC4-8A68-E566DEBDC4F6}.Debug-InnerLoop|Any CPU.Build.0 = Debug-InnerLoop|Any CPU + {EA3000E9-2A91-4EC4-8A68-E566DEBDC4F6}.Debug-InnerLoop|x64.ActiveCfg = Debug-InnerLoop|x64 + {EA3000E9-2A91-4EC4-8A68-E566DEBDC4F6}.Debug-InnerLoop|x64.Build.0 = Debug-InnerLoop|x64 + {EA3000E9-2A91-4EC4-8A68-E566DEBDC4F6}.Debug-InnerLoop|x86.ActiveCfg = Debug-InnerLoop|x86 + {EA3000E9-2A91-4EC4-8A68-E566DEBDC4F6}.Debug-InnerLoop|x86.Build.0 = Debug-InnerLoop|x86 {EA3000E9-2A91-4EC4-8A68-E566DEBDC4F6}.Release|Any CPU.ActiveCfg = Release|Any CPU {EA3000E9-2A91-4EC4-8A68-E566DEBDC4F6}.Release|Any CPU.Build.0 = Release|Any CPU {EA3000E9-2A91-4EC4-8A68-E566DEBDC4F6}.Release|x64.ActiveCfg = Release|Any CPU {EA3000E9-2A91-4EC4-8A68-E566DEBDC4F6}.Release|x64.Build.0 = Release|Any CPU {EA3000E9-2A91-4EC4-8A68-E566DEBDC4F6}.Release|x86.ActiveCfg = Release|Any CPU {EA3000E9-2A91-4EC4-8A68-E566DEBDC4F6}.Release|x86.Build.0 = Release|Any CPU + {EA3000E9-2A91-4EC4-8A68-E566DEBDC4F6}.Release-InnerLoop|Any CPU.ActiveCfg = Release-InnerLoop|Any CPU + {EA3000E9-2A91-4EC4-8A68-E566DEBDC4F6}.Release-InnerLoop|Any CPU.Build.0 = Release-InnerLoop|Any CPU + {EA3000E9-2A91-4EC4-8A68-E566DEBDC4F6}.Release-InnerLoop|x64.ActiveCfg = Release-InnerLoop|x64 + {EA3000E9-2A91-4EC4-8A68-E566DEBDC4F6}.Release-InnerLoop|x64.Build.0 = Release-InnerLoop|x64 + {EA3000E9-2A91-4EC4-8A68-E566DEBDC4F6}.Release-InnerLoop|x86.ActiveCfg = Release-InnerLoop|x86 + {EA3000E9-2A91-4EC4-8A68-E566DEBDC4F6}.Release-InnerLoop|x86.Build.0 = Release-InnerLoop|x86 {2BF743D8-2A06-412D-96D7-F448F00C5EA5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2BF743D8-2A06-412D-96D7-F448F00C5EA5}.Debug|Any CPU.Build.0 = Debug|Any CPU {2BF743D8-2A06-412D-96D7-F448F00C5EA5}.Debug|x64.ActiveCfg = Debug|Any CPU {2BF743D8-2A06-412D-96D7-F448F00C5EA5}.Debug|x64.Build.0 = Debug|Any CPU {2BF743D8-2A06-412D-96D7-F448F00C5EA5}.Debug|x86.ActiveCfg = Debug|Any CPU {2BF743D8-2A06-412D-96D7-F448F00C5EA5}.Debug|x86.Build.0 = Debug|Any CPU + {2BF743D8-2A06-412D-96D7-F448F00C5EA5}.Debug-InnerLoop|Any CPU.ActiveCfg = Debug-InnerLoop|Any CPU + {2BF743D8-2A06-412D-96D7-F448F00C5EA5}.Debug-InnerLoop|Any CPU.Build.0 = Debug-InnerLoop|Any CPU + {2BF743D8-2A06-412D-96D7-F448F00C5EA5}.Debug-InnerLoop|x64.ActiveCfg = Debug-InnerLoop|Any CPU + {2BF743D8-2A06-412D-96D7-F448F00C5EA5}.Debug-InnerLoop|x64.Build.0 = Debug-InnerLoop|Any CPU + {2BF743D8-2A06-412D-96D7-F448F00C5EA5}.Debug-InnerLoop|x86.ActiveCfg = Debug-InnerLoop|Any CPU + {2BF743D8-2A06-412D-96D7-F448F00C5EA5}.Debug-InnerLoop|x86.Build.0 = Debug-InnerLoop|Any CPU {2BF743D8-2A06-412D-96D7-F448F00C5EA5}.Release|Any CPU.ActiveCfg = Release|Any CPU {2BF743D8-2A06-412D-96D7-F448F00C5EA5}.Release|Any CPU.Build.0 = Release|Any CPU {2BF743D8-2A06-412D-96D7-F448F00C5EA5}.Release|x64.ActiveCfg = Release|Any CPU {2BF743D8-2A06-412D-96D7-F448F00C5EA5}.Release|x64.Build.0 = Release|Any CPU {2BF743D8-2A06-412D-96D7-F448F00C5EA5}.Release|x86.ActiveCfg = Release|Any CPU {2BF743D8-2A06-412D-96D7-F448F00C5EA5}.Release|x86.Build.0 = Release|Any CPU + {2BF743D8-2A06-412D-96D7-F448F00C5EA5}.Release-InnerLoop|Any CPU.ActiveCfg = Release-InnerLoop|Any CPU + {2BF743D8-2A06-412D-96D7-F448F00C5EA5}.Release-InnerLoop|Any CPU.Build.0 = Release-InnerLoop|Any CPU + {2BF743D8-2A06-412D-96D7-F448F00C5EA5}.Release-InnerLoop|x64.ActiveCfg = Release-InnerLoop|Any CPU + {2BF743D8-2A06-412D-96D7-F448F00C5EA5}.Release-InnerLoop|x64.Build.0 = Release-InnerLoop|Any CPU + {2BF743D8-2A06-412D-96D7-F448F00C5EA5}.Release-InnerLoop|x86.ActiveCfg = Release-InnerLoop|Any CPU + {2BF743D8-2A06-412D-96D7-F448F00C5EA5}.Release-InnerLoop|x86.Build.0 = Release-InnerLoop|Any CPU {FC527290-2F22-432C-B77B-6E815726B02C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {FC527290-2F22-432C-B77B-6E815726B02C}.Debug|Any CPU.Build.0 = Debug|Any CPU {FC527290-2F22-432C-B77B-6E815726B02C}.Debug|x64.ActiveCfg = Debug|Any CPU {FC527290-2F22-432C-B77B-6E815726B02C}.Debug|x64.Build.0 = Debug|Any CPU {FC527290-2F22-432C-B77B-6E815726B02C}.Debug|x86.ActiveCfg = Debug|Any CPU {FC527290-2F22-432C-B77B-6E815726B02C}.Debug|x86.Build.0 = Debug|Any CPU + {FC527290-2F22-432C-B77B-6E815726B02C}.Debug-InnerLoop|Any CPU.ActiveCfg = Debug-InnerLoop|Any CPU + {FC527290-2F22-432C-B77B-6E815726B02C}.Debug-InnerLoop|Any CPU.Build.0 = Debug-InnerLoop|Any CPU + {FC527290-2F22-432C-B77B-6E815726B02C}.Debug-InnerLoop|x64.ActiveCfg = Debug-InnerLoop|Any CPU + {FC527290-2F22-432C-B77B-6E815726B02C}.Debug-InnerLoop|x64.Build.0 = Debug-InnerLoop|Any CPU + {FC527290-2F22-432C-B77B-6E815726B02C}.Debug-InnerLoop|x86.ActiveCfg = Debug-InnerLoop|Any CPU + {FC527290-2F22-432C-B77B-6E815726B02C}.Debug-InnerLoop|x86.Build.0 = Debug-InnerLoop|Any CPU {FC527290-2F22-432C-B77B-6E815726B02C}.Release|Any CPU.ActiveCfg = Release|Any CPU {FC527290-2F22-432C-B77B-6E815726B02C}.Release|Any CPU.Build.0 = Release|Any CPU {FC527290-2F22-432C-B77B-6E815726B02C}.Release|x64.ActiveCfg = Release|Any CPU {FC527290-2F22-432C-B77B-6E815726B02C}.Release|x64.Build.0 = Release|Any CPU {FC527290-2F22-432C-B77B-6E815726B02C}.Release|x86.ActiveCfg = Release|Any CPU {FC527290-2F22-432C-B77B-6E815726B02C}.Release|x86.Build.0 = Release|Any CPU + {FC527290-2F22-432C-B77B-6E815726B02C}.Release-InnerLoop|Any CPU.ActiveCfg = Release-InnerLoop|Any CPU + {FC527290-2F22-432C-B77B-6E815726B02C}.Release-InnerLoop|Any CPU.Build.0 = Release-InnerLoop|Any CPU + {FC527290-2F22-432C-B77B-6E815726B02C}.Release-InnerLoop|x64.ActiveCfg = Release-InnerLoop|Any CPU + {FC527290-2F22-432C-B77B-6E815726B02C}.Release-InnerLoop|x64.Build.0 = Release-InnerLoop|Any CPU + {FC527290-2F22-432C-B77B-6E815726B02C}.Release-InnerLoop|x86.ActiveCfg = Release-InnerLoop|Any CPU + {FC527290-2F22-432C-B77B-6E815726B02C}.Release-InnerLoop|x86.Build.0 = Release-InnerLoop|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/ImageSharp/ImageSharp.csproj b/src/ImageSharp/ImageSharp.csproj index 832d551fd7..510f34dc7d 100644 --- a/src/ImageSharp/ImageSharp.csproj +++ b/src/ImageSharp/ImageSharp.csproj @@ -12,6 +12,7 @@ $(RepositoryUrl) Image Resize Crop Gif Jpg Jpeg Bitmap Png Tga NetCore A new, fully featured, fully managed, cross-platform, 2D graphics API for .NET + Debug;Release;Release-InnerLoop;Debug-InnerLoop @@ -20,6 +21,11 @@ net5.0;netcoreapp3.1;netcoreapp2.1;netstandard2.1;netstandard2.0;netstandard1.3;net472 + + + netcoreapp3.1 + + netcoreapp3.1;netcoreapp2.1;netstandard2.1;netstandard2.0;netstandard1.3;net472 diff --git a/tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj b/tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj index d89cf79fc9..a146dc03ee 100644 --- a/tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj +++ b/tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj @@ -5,15 +5,28 @@ ImageSharp.Benchmarks Exe SixLabors.ImageSharp.Benchmarks - net5.0;netcoreapp3.1;netcoreapp2.1;net472 false false + Debug;Release;Release-InnerLoop;Debug-InnerLoop + + + + netcoreapp3.1 + + + + + net5.0;netcoreapp3.1;netcoreapp2.1;net472 + + + + diff --git a/tests/ImageSharp.Tests.ProfilingSandbox/ImageSharp.Tests.ProfilingSandbox.csproj b/tests/ImageSharp.Tests.ProfilingSandbox/ImageSharp.Tests.ProfilingSandbox.csproj index 220780c58e..9159475326 100644 --- a/tests/ImageSharp.Tests.ProfilingSandbox/ImageSharp.Tests.ProfilingSandbox.csproj +++ b/tests/ImageSharp.Tests.ProfilingSandbox/ImageSharp.Tests.ProfilingSandbox.csproj @@ -8,13 +8,26 @@ false SixLabors.ImageSharp.Tests.ProfilingSandbox win7-x64 - net5.0;netcoreapp3.1;netcoreapp2.1;net472 SixLabors.ImageSharp.Tests.ProfilingSandbox.Program false false + Debug;Release;Release-InnerLoop;Debug-InnerLoop + + + + netcoreapp3.1 + + + + + net5.0;netcoreapp3.1;netcoreapp2.1;net472 + + + + diff --git a/tests/ImageSharp.Tests.ProfilingSandbox/app.config b/tests/ImageSharp.Tests.ProfilingSandbox/app.config index 3328297a54..a74fa13156 100644 --- a/tests/ImageSharp.Tests.ProfilingSandbox/app.config +++ b/tests/ImageSharp.Tests.ProfilingSandbox/app.config @@ -1,4 +1,4 @@ - + @@ -12,8 +12,8 @@ - + - \ No newline at end of file + diff --git a/tests/ImageSharp.Tests/ImageSharp.Tests.csproj b/tests/ImageSharp.Tests/ImageSharp.Tests.csproj index ebbe2cbdfa..b6482455e0 100644 --- a/tests/ImageSharp.Tests/ImageSharp.Tests.csproj +++ b/tests/ImageSharp.Tests/ImageSharp.Tests.csproj @@ -2,13 +2,26 @@ - net5.0;netcoreapp3.1;netcoreapp2.1;net472 True SixLabors.ImageSharp.Tests AnyCPU;x64;x86 SixLabors.ImageSharp.Tests + Debug;Release;Release-InnerLoop;Debug-InnerLoop + + + + netcoreapp3.1 + + + + + net5.0;netcoreapp3.1;netcoreapp2.1;net472 + + + + From c4d417ab6649e31e4cb0aef499b7bd3886d710fe Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Fri, 16 Apr 2021 22:24:59 +0100 Subject: [PATCH 5/6] Fix codecov test environment identification --- .../TestUtilities/TestEnvironment.cs | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.cs b/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.cs index 587b274a10..b14c2bf782 100644 --- a/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.cs +++ b/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.cs @@ -24,10 +24,6 @@ namespace SixLabors.ImageSharp.Tests private static readonly Lazy SolutionDirectoryFullPathLazy = new Lazy(GetSolutionDirectoryFullPathImpl); - private static readonly Lazy RunsOnCiLazy = new Lazy(() => bool.TryParse(Environment.GetEnvironmentVariable("CI"), out bool isCi) && isCi); - - private static readonly Lazy RunsWithCodeCoverageLazy = new Lazy(() => bool.TryParse(Environment.GetEnvironmentVariable("codecov"), out bool isCodeCov) && isCodeCov); - private static readonly Lazy NetCoreVersionLazy = new Lazy(GetNetCoreVersion); static TestEnvironment() => PrepareRemoteExecutor(); @@ -42,12 +38,20 @@ namespace SixLabors.ImageSharp.Tests /// /// Gets a value indicating whether test execution runs on CI. /// - internal static bool RunsOnCI => RunsOnCiLazy.Value; +#if ENV_CI + internal static bool RunsOnCI => true; +#else + internal static bool RunsOnCI => false; +#endif /// /// Gets a value indicating whether test execution is running with code coverage testing enabled. /// - internal static bool RunsWithCodeCoverage => RunsWithCodeCoverageLazy.Value; +#if ENV_CODECOV + internal static bool RunsWithCodeCoverage => true; +#else + internal static bool RunsWithCodeCoverage => false; +#endif internal static string SolutionDirectoryFullPath => SolutionDirectoryFullPathLazy.Value; @@ -66,14 +70,14 @@ namespace SixLabors.ImageSharp.Tests } catch (Exception ex) { - throw new Exception( + throw new DirectoryNotFoundException( $"Unable to find ImageSharp solution directory from {TestAssemblyFile} because of {ex.GetType().Name}!", ex); } if (directory == null) { - throw new Exception($"Unable to find ImageSharp solution directory from {TestAssemblyFile}!"); + throw new DirectoryNotFoundException($"Unable to find ImageSharp solution directory from {TestAssemblyFile}!"); } } From 9f0515f27b4032106e45c6ecb266126e4e537650 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Sat, 17 Apr 2021 22:21:18 +0100 Subject: [PATCH 6/6] Update shared-infrastructure --- shared-infrastructure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared-infrastructure b/shared-infrastructure index 462f789c52..41fff7bf7d 160000 --- a/shared-infrastructure +++ b/shared-infrastructure @@ -1 +1 @@ -Subproject commit 462f789c52809728505833d101b9a96022e0fc3b +Subproject commit 41fff7bf7ddb1d118898db1ddba43b95ba6ed0bb