From 2eb849957c2b57e68508b33ddeeb02dcfdb4575a Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Wed, 24 May 2017 17:30:14 +1000 Subject: [PATCH] Optimize Resize --- .../ResamplingWeightedProcessor.Weights.cs | 5 ++ .../Transforms/ResamplingWeightedProcessor.cs | 4 +- .../Processors/Transforms/ResizeProcessor.cs | 66 +++++++++---------- 3 files changed, 36 insertions(+), 39 deletions(-) diff --git a/src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.Weights.cs b/src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.Weights.cs index d49f37803..b5266c9bd 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.Weights.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.Weights.cs @@ -1,3 +1,8 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + namespace ImageSharp.Processing.Processors { using System; diff --git a/src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.cs index e2f77d812..757b0889a 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.cs @@ -6,9 +6,7 @@ namespace ImageSharp.Processing.Processors { using System; - using System.Buffers; using System.Runtime.CompilerServices; - using System.Runtime.InteropServices; using ImageSharp.PixelFormats; @@ -90,7 +88,7 @@ namespace ImageSharp.Processing.Processors IResampler sampler = this.Sampler; float radius = MathF.Ceiling(scale * sampler.Radius); - WeightsBuffer result = new WeightsBuffer(sourceSize, destinationSize); + var result = new WeightsBuffer(sourceSize, destinationSize); for (int i = 0; i < destinationSize; i++) { diff --git a/src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs index 61a64f60f..68ff1397d 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs @@ -73,26 +73,24 @@ namespace ImageSharp.Processing.Processors float widthFactor = sourceRectangle.Width / (float)this.ResizeRectangle.Width; float heightFactor = sourceRectangle.Height / (float)this.ResizeRectangle.Height; - using (PixelAccessor targetPixels = new PixelAccessor(width, height)) + using (var targetPixels = new PixelAccessor(width, height)) { - using (PixelAccessor sourcePixels = source.Lock()) - { - Parallel.For( - minY, - maxY, - this.ParallelOptions, - y => - { - // Y coordinates of source points - int originY = (int)(((y - startY) * heightFactor) + sourceY); + Parallel.For( + minY, + maxY, + this.ParallelOptions, + y => + { + // Y coordinates of source points + Span sourceRow = source.GetRowSpan((int)(((y - startY) * heightFactor) + sourceY)); + Span targetRow = targetPixels.GetRowSpan(y); - for (int x = minX; x < maxX; x++) - { - // X coordinates of source points - targetPixels[x, y] = sourcePixels[(int)(((x - startX) * widthFactor) + sourceX), originY]; - } - }); - } + for (int x = minX; x < maxX; x++) + { + // X coordinates of source points + targetRow[x] = sourceRow[(int)(((x - startX) * widthFactor) + sourceX)]; + } + }); // Break out now. source.SwapPixelsBuffers(targetPixels); @@ -106,10 +104,9 @@ namespace ImageSharp.Processing.Processors // 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 (PixelAccessor targetPixels = new PixelAccessor(width, height)) + using (var targetPixels = new PixelAccessor(width, height)) { - using (PixelAccessor sourcePixels = source.Lock()) - using (Buffer2D firstPassPixels = new Buffer2D(width, source.Height)) + using (var firstPassPixels = new Buffer2D(width, source.Height)) { firstPassPixels.Clear(); @@ -120,21 +117,18 @@ namespace ImageSharp.Processing.Processors y => { // TODO: Without Parallel.For() this buffer object could be reused: - using (Buffer tempRowBuffer = new Buffer(sourcePixels.Width)) + using (var tempRowBuffer = new Buffer(source.Width)) { - Span sourceRow = sourcePixels.GetRowSpan(y); - - PixelOperations.Instance.ToVector4( - sourceRow, - tempRowBuffer, - sourceRow.Length); + Span firstPassRow = firstPassPixels.GetRowSpan(y); + Span sourceRow = source.GetRowSpan(y); + PixelOperations.Instance.ToVector4(sourceRow, tempRowBuffer, sourceRow.Length); if (this.Compand) { for (int x = minX; x < maxX; x++) { WeightsWindow window = this.HorizontalWeights.Weights[x - startX]; - firstPassPixels[x, y] = window.ComputeExpandedWeightedRowSum(tempRowBuffer, sourceX); + firstPassRow[x] = window.ComputeExpandedWeightedRowSum(tempRowBuffer, sourceX); } } else @@ -142,7 +136,7 @@ namespace ImageSharp.Processing.Processors for (int x = minX; x < maxX; x++) { WeightsWindow window = this.HorizontalWeights.Weights[x - startX]; - firstPassPixels[x, y] = window.ComputeWeightedRowSum(tempRowBuffer, sourceX); + firstPassRow[x] = window.ComputeWeightedRowSum(tempRowBuffer, sourceX); } } } @@ -157,6 +151,7 @@ namespace ImageSharp.Processing.Processors { // Ensure offsets are normalised for cropping and padding. WeightsWindow window = this.VerticalWeights.Weights[y - startY]; + Span targetRow = targetPixels.GetRowSpan(y); if (this.Compand) { @@ -165,9 +160,9 @@ namespace ImageSharp.Processing.Processors // Destination color components Vector4 destination = window.ComputeWeightedColumnSum(firstPassPixels, x, sourceY); destination = destination.Compress(); - TPixel d = default(TPixel); - d.PackFromVector4(destination); - targetPixels[x, y] = d; + + ref TPixel pixel = ref targetRow[x]; + pixel.PackFromVector4(destination); } } else @@ -177,9 +172,8 @@ namespace ImageSharp.Processing.Processors // Destination color components Vector4 destination = window.ComputeWeightedColumnSum(firstPassPixels, x, sourceY); - TPixel d = default(TPixel); - d.PackFromVector4(destination); - targetPixels[x, y] = d; + ref TPixel pixel = ref targetRow[x]; + pixel.PackFromVector4(destination); } } });