diff --git a/src/ImageSharp/Processing/Processors/Transforms/ResizeKernel.cs b/src/ImageSharp/Processing/Processors/Transforms/ResizeKernel.cs index a69ceea5c..eeb4aef19 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/ResizeKernel.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/ResizeKernel.cs @@ -78,7 +78,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms /// The source row position. /// The weighted sum [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Vector4 ConvolveRows(Span rowSpan, int sourceX) + public Vector4 Convolve(Span rowSpan, int sourceX) { ref float horizontalValues = ref this.GetStartReference(); int left = this.Left; @@ -105,7 +105,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms /// The source row position. /// The weighted sum [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Vector4 ConvolveExpandRows(Span rowSpan, int sourceX) + public Vector4 ConvolveExpand(Span rowSpan, int sourceX) { ref float horizontalValues = ref this.GetStartReference(); int left = this.Left; @@ -123,32 +123,5 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms return result; } - - /// - /// Computes the sum of vectors in 'firstPassPixels' at a row pointed by 'x', - /// weighted by weight values, pointed by this instance. - /// - /// The buffer of input vectors in row first order - /// The row position - /// The source column position. - /// The weighted sum - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Vector4 ConvolveColumnsAndUnPremultiply(Buffer2D firstPassPixels, int x, int sourceY) - { - ref float verticalValues = ref this.GetStartReference(); - int left = this.Left; - - // Destination color components - Vector4 result = Vector4.Zero; - - for (int i = 0; i < this.Length; i++) - { - float yw = Unsafe.Add(ref verticalValues, i); - int index = left + i + sourceY; - result += firstPassPixels[x, index] * yw; - } - - return result.UnPremultiply(); - } } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs index 2643206b4..3c13d781e 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs @@ -233,10 +233,9 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms // A 2-pass 1D algorithm appears to be faster than splitting a 1-pass 2D algorithm // First process the columns. Since we are not using multiple threads startY and endY // are the upper and lower bounds of the source rectangle. - // TODO: Using a transposed variant of 'firstPassPixels' could eliminate the need for the WeightsWindow.ComputeWeightedColumnSum() method, and improve speed! - using (Buffer2D firstPassPixels = source.MemoryAllocator.Allocate2D(width, source.Height)) + using (Buffer2D firstPassPixelsTransposed = source.MemoryAllocator.Allocate2D(source.Height, width)) { - firstPassPixels.MemorySource.Clear(); + firstPassPixelsTransposed.MemorySource.Clear(); var processColsRect = new Rectangle(0, 0, source.Width, sourceRectangle.Bottom); @@ -247,8 +246,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms { for (int y = rows.Min; y < rows.Max; y++) { - ref Vector4 firstPassRow = - ref MemoryMarshal.GetReference(firstPassPixels.GetRowSpan(y)); Span sourceRow = source.GetPixelRowSpan(y); Span tempRowSpan = tempRowBuffer.Span; @@ -260,8 +257,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms for (int x = minX; x < maxX; x++) { ResizeKernel window = this.horizontalKernelMap.Kernels[x - startX]; - Unsafe.Add(ref firstPassRow, x) = - window.ConvolveExpandRows(tempRowSpan, sourceX).UnPremultiply(); + firstPassPixelsTransposed[y, x] = window.ConvolveExpand(tempRowSpan, sourceX).UnPremultiply(); } } else @@ -269,8 +265,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms for (int x = minX; x < maxX; x++) { ResizeKernel window = this.horizontalKernelMap.Kernels[x - startX]; - Unsafe.Add(ref firstPassRow, x) = - window.ConvolveRows(tempRowSpan, sourceX); + firstPassPixelsTransposed[y, x] = + window.Convolve(tempRowSpan, sourceX); } } } @@ -294,12 +290,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms { for (int x = 0; x < width; x++) { + Span firstPassColumn = firstPassPixelsTransposed.GetRowSpan(x); + // Destination color components - Vector4 destinationVector = window.ConvolveColumnsAndUnPremultiply( - firstPassPixels, - x, - sourceY); - destinationVector = destinationVector.Compress(); + Vector4 destinationVector = window.Convolve(firstPassColumn, sourceY); + destinationVector = destinationVector.UnPremultiply().Compress(); ref TPixel pixel = ref Unsafe.Add(ref targetRow, x); pixel.PackFromVector4(destinationVector); @@ -309,12 +304,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms { for (int x = 0; x < width; x++) { - // Destination color components - Vector4 destinationVector = window.ConvolveColumnsAndUnPremultiply( - firstPassPixels, - x, - sourceY); + Span firstPassColumn = firstPassPixelsTransposed.GetRowSpan(x); + // Destination color components + Vector4 destinationVector = window.Convolve(firstPassColumn, sourceY).UnPremultiply(); ref TPixel pixel = ref Unsafe.Add(ref targetRow, x); pixel.PackFromVector4(destinationVector); }