diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResamplerExtensions.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResamplerExtensions.cs index b681a436c..2cd903924 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResamplerExtensions.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResamplerExtensions.cs @@ -78,13 +78,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms // Since all image frame dimensions have to be the same we can calculate // the kernel maps and reuse for all frames. MemoryAllocator allocator = configuration.MemoryAllocator; - using var horizontalKernelMap = ResizeKernelMap.Calculate( + using var horizontalKernelMap = ResizeKernelMap.Calculate( in sampler, destinationRectangle.Width, sourceRectangle.Width, allocator); - using var verticalKernelMap = ResizeKernelMap.Calculate( + using var verticalKernelMap = ResizeKernelMap.Calculate( in sampler, destinationRectangle.Height, sourceRectangle.Height, @@ -135,17 +135,16 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms in operation); } - private static void ApplyResizeFrameTransform( + private static void ApplyResizeFrameTransform( Configuration configuration, ImageFrame source, ImageFrame destination, - ResizeKernelMap horizontalKernelMap, - ResizeKernelMap verticalKernelMap, + ResizeKernelMap horizontalKernelMap, + ResizeKernelMap verticalKernelMap, Rectangle sourceRectangle, Rectangle destinationRectangle, Rectangle interest, bool compand) - where TResampler : unmanaged, IResampler where TPixel : struct, IPixel { PixelConversionModifiers conversionModifiers = @@ -155,7 +154,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms // To reintroduce parallel processing, we would launch multiple workers // for different row intervals of the image. - using (var worker = new ResizeWorker( + using (var worker = new ResizeWorker( configuration, sourceArea, conversionModifiers, diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernel.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernel.cs index 83bee9111..f3521ebed 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernel.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernel.cs @@ -8,7 +8,7 @@ using System.Runtime.CompilerServices; namespace SixLabors.ImageSharp.Processing.Processors.Transforms { /// - /// Points to a collection of of weights allocated in . + /// Points to a collection of of weights allocated in . /// internal readonly unsafe struct ResizeKernel { @@ -44,7 +44,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms } /// - /// Gets the span representing the portion of the that this window covers. + /// Gets the span representing the portion of the that this window covers. /// /// The . /// diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernelMap.PeriodicKernelMap.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernelMap.PeriodicKernelMap.cs index 52a308cf2..a79f60339 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernelMap.PeriodicKernelMap.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernelMap.PeriodicKernelMap.cs @@ -5,13 +5,12 @@ using SixLabors.ImageSharp.Memory; namespace SixLabors.ImageSharp.Processing.Processors.Transforms { - internal partial class ResizeKernelMap - where TResampler : unmanaged, IResampler + internal partial class ResizeKernelMap { /// - /// Memory-optimized where repeating rows are stored only once. + /// Memory-optimized where repeating rows are stored only once. /// - private sealed class PeriodicKernelMap : ResizeKernelMap + private sealed class PeriodicKernelMap : ResizeKernelMap { private readonly int period; @@ -19,7 +18,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms public PeriodicKernelMap( MemoryAllocator memoryAllocator, - TResampler sampler, int sourceLength, int destinationLength, double ratio, @@ -29,7 +27,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms int cornerInterval) : base( memoryAllocator, - sampler, sourceLength, destinationLength, (cornerInterval * 2) + period, @@ -43,14 +40,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms internal override string Info => base.Info + $"|period:{this.period}|cornerInterval:{this.cornerInterval}"; - protected internal override void Initialize() + protected internal override void Initialize(in TResampler sampler) { // Build top corner data + one period of the mosaic data: int startOfFirstRepeatedMosaic = this.cornerInterval + this.period; for (int i = 0; i < startOfFirstRepeatedMosaic; i++) { - this.kernels[i] = this.BuildKernel(i, i); + this.kernels[i] = this.BuildKernel(in sampler, i, i); } // Copy the mosaics: @@ -67,7 +64,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms int bottomStartData = this.cornerInterval + this.period; for (int i = 0; i < this.cornerInterval; i++) { - this.kernels[bottomStartDest + i] = this.BuildKernel(bottomStartDest + i, bottomStartData + i); + this.kernels[bottomStartDest + i] = this.BuildKernel(in sampler, bottomStartDest + i, bottomStartData + i); } } } diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernelMap.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernelMap.cs index 8432eb654..a6e6bf612 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernelMap.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernelMap.cs @@ -12,14 +12,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms /// /// Provides resize kernel values from an optimized contiguous memory region. /// - /// The type of sampler. - internal partial class ResizeKernelMap : IDisposable - where TResampler : unmanaged, IResampler + internal partial class ResizeKernelMap : IDisposable { private static readonly TolerantMath TolerantMath = TolerantMath.Default; - private readonly TResampler sampler; - private readonly int sourceLength; private readonly double ratio; @@ -41,7 +37,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms private ResizeKernelMap( MemoryAllocator memoryAllocator, - TResampler sampler, int sourceLength, int destinationLength, int bufferHeight, @@ -49,7 +44,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms double scale, int radius) { - this.sampler = sampler; this.ratio = ratio; this.scale = scale; this.radius = radius; @@ -79,7 +73,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms $"radius:{this.radius}|sourceSize:{this.sourceLength}|destinationSize:{this.DestinationLength}|ratio:{this.ratio}|scale:{this.scale}"; /// - /// Disposes instance releasing it's backing buffer. + /// Disposes instance releasing it's backing buffer. /// public void Dispose() => this.Dispose(true); @@ -111,16 +105,18 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms /// /// Computes the weights to apply at each pixel when resizing. /// + /// The type of sampler. /// The /// The destination size /// The source size /// The to use for buffer allocations - /// The - public static ResizeKernelMap Calculate( + /// The + public static ResizeKernelMap Calculate( in TResampler sampler, int destinationSize, int sourceSize, MemoryAllocator memoryAllocator) + where TResampler : unmanaged, IResampler { double ratio = (double)sourceSize / destinationSize; double scale = ratio; @@ -158,10 +154,9 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms // If we don't have at least 2 periods, we go with the basic implementation: bool hasAtLeast2Periods = 2 * (cornerInterval + period) < destinationSize; - ResizeKernelMap result = hasAtLeast2Periods + ResizeKernelMap result = hasAtLeast2Periods ? new PeriodicKernelMap( memoryAllocator, - sampler, sourceSize, destinationSize, ratio, @@ -169,9 +164,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms radius, period, cornerInterval) - : new ResizeKernelMap( + : new ResizeKernelMap( memoryAllocator, - sampler, sourceSize, destinationSize, destinationSize, @@ -179,7 +173,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms scale, radius); - result.Initialize(); + result.Initialize(in sampler); return result; } @@ -187,11 +181,12 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms /// /// Initializes the kernel map. /// - protected internal virtual void Initialize() + protected internal virtual void Initialize(in TResampler sampler) + where TResampler : unmanaged, IResampler { for (int i = 0; i < this.DestinationLength; i++) { - this.kernels[i] = this.BuildKernel(i, i); + this.kernels[i] = this.BuildKernel(in sampler, i, i); } } @@ -200,7 +195,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms /// referencing the data at row within , /// so the data reusable by other data rows. /// - private ResizeKernel BuildKernel(int destRowIndex, int dataRowIndex) + private ResizeKernel BuildKernel(in TResampler sampler, int destRowIndex, int dataRowIndex) + where TResampler : unmanaged, IResampler { double center = ((destRowIndex + .5) * this.ratio) - .5; @@ -224,7 +220,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms for (int j = left; j <= right; j++) { - double value = this.sampler.GetValue((float)((j - center) / this.scale)); + double value = sampler.GetValue((float)((j - center) / this.scale)); sum += value; kernelValues[j - left] = value; diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs index cbec5242c..5ba204135 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeWorker.cs @@ -6,7 +6,6 @@ using System.Buffers; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; - using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; @@ -19,8 +18,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms /// When sliding the window, the contents of the bottom window band are copied to the new top band. /// For more details, and visual explanation, see "ResizeWorker.pptx". /// - internal sealed class ResizeWorker : IDisposable - where TResampler : unmanaged, IResampler + internal sealed class ResizeWorker : IDisposable where TPixel : struct, IPixel { private readonly Buffer2D transposedFirstPassBuffer; @@ -29,7 +27,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms private readonly PixelConversionModifiers conversionModifiers; - private readonly ResizeKernelMap horizontalKernelMap; + private readonly ResizeKernelMap horizontalKernelMap; private readonly BufferArea source; @@ -39,7 +37,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms private readonly IMemoryOwner tempColumnBuffer; - private readonly ResizeKernelMap verticalKernelMap; + private readonly ResizeKernelMap verticalKernelMap; private readonly int destWidth; @@ -57,8 +55,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms Configuration configuration, BufferArea source, PixelConversionModifiers conversionModifiers, - ResizeKernelMap horizontalKernelMap, - ResizeKernelMap verticalKernelMap, + ResizeKernelMap horizontalKernelMap, + ResizeKernelMap verticalKernelMap, int destWidth, Rectangle targetWorkingRect, Point targetOrigin) diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeKernelMapTests.ReferenceKernelMap.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeKernelMapTests.ReferenceKernelMap.cs index d6fa07536..17477c83b 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeKernelMapTests.ReferenceKernelMap.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeKernelMapTests.ReferenceKernelMap.cs @@ -13,8 +13,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms /// /// Simplified reference implementation for functionality. /// - internal class ReferenceKernelMap - where TResampler : unmanaged, IResampler + internal class ReferenceKernelMap { private readonly ReferenceKernel[] kernels; @@ -27,7 +26,8 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms public ReferenceKernel GetKernel(int destinationIndex) => this.kernels[destinationIndex]; - public static ReferenceKernelMap Calculate(TResampler sampler, int destinationSize, int sourceSize, bool normalize = true) + public static ReferenceKernelMap Calculate(in TResampler sampler, int destinationSize, int sourceSize, bool normalize = true) + where TResampler : unmanaged, IResampler { double ratio = (double)sourceSize / destinationSize; double scale = ratio; @@ -85,7 +85,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms result.Add(new ReferenceKernel(left, floatVals)); } - return new ReferenceKernelMap(result.ToArray()); + return new ReferenceKernelMap(result.ToArray()); } } diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeKernelMapTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeKernelMapTests.cs index 6ca3c3bee..e404c6460 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeKernelMapTests.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeKernelMapTests.cs @@ -89,7 +89,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms public void PrintNonNormalizedKernelMap(TResampler resampler, int srcSize, int destSize) where TResampler : unmanaged, IResampler { - var kernelMap = ReferenceKernelMap.Calculate(resampler, destSize, srcSize, false); + var kernelMap = ReferenceKernelMap.Calculate(in resampler, destSize, srcSize, false); this.Output.WriteLine($"Actual KernelMap:\n{PrintKernelMap(kernelMap)}\n"); } @@ -117,8 +117,8 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms private void VerifyKernelMapContentIsCorrect(TResampler resampler, int srcSize, int destSize) where TResampler : unmanaged, IResampler { - var referenceMap = ReferenceKernelMap.Calculate(resampler, destSize, srcSize); - var kernelMap = ResizeKernelMap.Calculate(resampler, destSize, srcSize, Configuration.Default.MemoryAllocator); + var referenceMap = ReferenceKernelMap.Calculate(in resampler, destSize, srcSize); + var kernelMap = ResizeKernelMap.Calculate(in resampler, destSize, srcSize, Configuration.Default.MemoryAllocator); #if DEBUG this.Output.WriteLine(kernelMap.Info); @@ -153,23 +153,20 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms } } - private static string PrintKernelMap(ResizeKernelMap kernelMap) - where TResampler : unmanaged, IResampler - => PrintKernelMap>(kernelMap, km => km.DestinationLength, (km, i) => km.GetKernel(i)); + private static string PrintKernelMap(ResizeKernelMap kernelMap) + => PrintKernelMap(kernelMap, km => km.DestinationLength, (km, i) => km.GetKernel(i)); - private static string PrintKernelMap(ReferenceKernelMap kernelMap) - where TResampler : unmanaged, IResampler - => PrintKernelMap>(kernelMap, km => km.DestinationSize, (km, i) => km.GetKernel(i)); + private static string PrintKernelMap(ReferenceKernelMap kernelMap) + => PrintKernelMap(kernelMap, km => km.DestinationSize, (km, i) => km.GetKernel(i)); - private static string PrintKernelMap( + private static string PrintKernelMap( TKernelMap kernelMap, Func getDestinationSize, Func getKernel) - where TResampler : unmanaged, IResampler { var bld = new StringBuilder(); - if (kernelMap is ResizeKernelMap actualMap) + if (kernelMap is ResizeKernelMap actualMap) { bld.AppendLine(actualMap.Info); } diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs index 63c93596f..7086bfeb3 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs @@ -121,7 +121,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms configuration.MemoryAllocator = allocator; configuration.WorkingBufferSizeHintInBytes = workingBufferSizeHintInBytes; - var verticalKernelMap = ResizeKernelMap.Calculate( + var verticalKernelMap = ResizeKernelMap.Calculate( default, destSize.Height, image0.Height,