From 248c07555f8b2fd7cf2b5a7858cefa93a5de10b5 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Wed, 27 Nov 2019 13:04:05 +0100 Subject: [PATCH 1/7] Memory usage reduction, sequential mode disabled --- .../Common/Helpers/Buffer2DUtils.cs | 15 ++- .../Convolution/BokehBlurProcessor{TPixel}.cs | 101 ++++-------------- 2 files changed, 28 insertions(+), 88 deletions(-) diff --git a/src/ImageSharp/Common/Helpers/Buffer2DUtils.cs b/src/ImageSharp/Common/Helpers/Buffer2DUtils.cs index 0c22aa68f..b678e798f 100644 --- a/src/ImageSharp/Common/Helpers/Buffer2DUtils.cs +++ b/src/ImageSharp/Common/Helpers/Buffer2DUtils.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. using System; +using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -62,7 +63,7 @@ namespace SixLabors.ImageSharp } /// - /// Computes the sum of vectors in weighted by the kernel weight values. + /// Computes the sum of vectors in weighted by the kernel weight values and accumulates the partial results. /// /// The 1D convolution kernel. /// The source frame. @@ -73,16 +74,20 @@ namespace SixLabors.ImageSharp /// The maximum working area row. /// The minimum working area column. /// The maximum working area column. - public static void Convolve4( + /// The weight factor for the real component of the complex pixel values. + /// The weight factor for the imaginary component of the complex pixel values. + public static void Convolve4AndAccumulatePartials( Span kernel, Buffer2D sourceValues, - Span targetRow, + Span targetRow, int row, int column, int minRow, int maxRow, int minColumn, - int maxColumn) + int maxColumn, + float z, + float w) { ComplexVector4 vector = default; int kernelLength = kernel.Length; @@ -99,7 +104,7 @@ namespace SixLabors.ImageSharp vector.Sum(Unsafe.Add(ref baseRef, x) * Unsafe.Add(ref sourceRef, offsetX)); } - targetRow[column] = vector; + targetRow[column] += vector.WeightedSum(z, w); } } } diff --git a/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor{TPixel}.cs index f8fb3f796..9c784099c 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor{TPixel}.cs @@ -281,26 +281,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution // Create a 0-filled buffer to use to store the result of the component convolutions using (Buffer2D processing = this.Configuration.MemoryAllocator.Allocate2D(source.Size(), AllocationOptions.Clean)) + using (Buffer2D firstPassValues = this.Configuration.MemoryAllocator.Allocate2D(source.Size())) { - if (this.executionMode == BokehBlurExecutionMode.PreferLowMemoryUsage) - { - // Memory usage priority: allocate a shared buffer and execute the second convolution in sequential mode - using (Buffer2D buffer = this.Configuration.MemoryAllocator.Allocate2D(source.Width, source.Height + this.radius)) - using (Buffer2D firstPassBuffer = buffer.Slice(this.radius, source.Height)) - using (Buffer2D secondPassBuffer = buffer.Slice(0, source.Height)) - { - this.OnFrameApplyCore(source, this.SourceRectangle, this.Configuration, processing, firstPassBuffer, secondPassBuffer); - } - } - else - { - // Performance priority: allocate two independent buffers and execute both convolutions in parallel mode - using (Buffer2D firstPassValues = this.Configuration.MemoryAllocator.Allocate2D(source.Size())) - using (Buffer2D secondPassBuffer = this.Configuration.MemoryAllocator.Allocate2D(source.Size())) - { - this.OnFrameApplyCore(source, this.SourceRectangle, this.Configuration, processing, firstPassValues, secondPassBuffer); - } - } + // Perform the 1D convolutions on all the kernel components and accumulate the results + this.OnFrameApplyCore(source, this.SourceRectangle, this.Configuration, processing, firstPassValues); // Apply the inverse gamma exposure pass, and write the final pixel data this.ApplyInverseGammaExposure(source.PixelBuffer, processing, this.SourceRectangle, this.Configuration); @@ -315,14 +299,12 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// The configuration. /// The buffer with the raw pixel data to use to aggregate the results of each convolution. /// The complex buffer to use for the first 1D convolution pass for each kernel. - /// The complex buffer to use for the second 1D convolution pass for each kernel. private void OnFrameApplyCore( ImageFrame source, Rectangle sourceRectangle, Configuration configuration, Buffer2D processingBuffer, - Buffer2D firstPassBuffer, - Buffer2D secondPassBuffer) + Buffer2D firstPassBuffer) { // Perform two 1D convolutions for each component in the current instance ref Complex64[] baseRef = ref MemoryMarshal.GetReference(this.kernels.AsSpan()); @@ -331,12 +313,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution // Compute the resulting complex buffer for the current component var interest = Rectangle.Intersect(sourceRectangle, source.Bounds()); Complex64[] kernel = Unsafe.Add(ref baseRef, i); - this.ApplyConvolution(firstPassBuffer, source.PixelBuffer, interest, kernel, configuration); - this.ApplyConvolution(secondPassBuffer, firstPassBuffer, interest, kernel, configuration); - - // Add the results of the convolution with the current kernel Vector4 parameters = this.kernelParameters[i]; - this.SumProcessingPartials(processingBuffer, secondPassBuffer, sourceRectangle, configuration, parameters.Z, parameters.W); + + // Compute the two 1D convolutions and accumulate the partial results on the target buffer + this.ApplyConvolution(firstPassBuffer, source.PixelBuffer, interest, kernel, configuration); + this.ApplyConvolution(processingBuffer, firstPassBuffer, interest, kernel, configuration, parameters.Z, parameters.W); } } @@ -389,19 +370,21 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// Applies the process to the specified portion of the specified buffer at the specified location /// and with the specified size. /// - /// The target values to use to store the results. + /// The target values to use to store the results. /// The source complex values. Cannot be null. - /// - /// The structure that specifies the portion of the image object to draw. - /// + /// The structure that specifies the portion of the image object to draw. /// The 1D kernel. /// The + /// The weight factor for the real component of the complex pixel values. + /// The weight factor for the imaginary component of the complex pixel values. private void ApplyConvolution( - Buffer2D targetValues, + Buffer2D targetValues, Buffer2D sourceValues, Rectangle sourceRectangle, Complex64[] kernel, - Configuration configuration) + Configuration configuration, + float z, + float w) { int startY = sourceRectangle.Y; int endY = sourceRectangle.Bottom; @@ -426,11 +409,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution { for (int y = rows.Min; y < rows.Max; y++) { - Span targetRowSpan = targetValues.GetRowSpan(y).Slice(startX); + Span targetRowSpan = targetValues.GetRowSpan(y).Slice(startX); for (int x = 0; x < width; x++) { - Buffer2DUtils.Convolve4(kernel, sourceValues, targetRowSpan, y, x, startY, maxY, startX, maxX); + Buffer2DUtils.Convolve4AndAccumulatePartials(kernel, sourceValues, targetRowSpan, y, x, startY, maxY, startX, maxX, z, w); } } }); @@ -536,53 +519,5 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution } }); } - - /// - /// Applies the process to the specified portion of the specified at the specified location - /// and with the specified size. - /// - /// The target instance to use to store the results. - /// The source complex pixels. Cannot be null. - /// - /// The structure that specifies the portion of the image object to draw. - /// - /// The - /// The weight factor for the real component of the complex pixel values. - /// The weight factor for the imaginary component of the complex pixel values. - private void SumProcessingPartials( - Buffer2D targetValues, - Buffer2D sourceValues, - Rectangle sourceRectangle, - Configuration configuration, - float z, - float w) - { - int startY = sourceRectangle.Y; - int endY = sourceRectangle.Bottom; - int startX = sourceRectangle.X; - int endX = sourceRectangle.Right; - - var workingRectangle = Rectangle.FromLTRB(startX, startY, endX, endY); - int width = workingRectangle.Width; - - ParallelHelper.IterateRows( - workingRectangle, - configuration, - rows => - { - for (int y = rows.Min; y < rows.Max; y++) - { - Span targetRowSpan = targetValues.GetRowSpan(y).Slice(startX); - Span sourceRowSpan = sourceValues.GetRowSpan(y).Slice(startX); - ref Vector4 baseTargetRef = ref MemoryMarshal.GetReference(targetRowSpan); - ref ComplexVector4 baseSourceRef = ref MemoryMarshal.GetReference(sourceRowSpan); - - for (int x = 0; x < width; x++) - { - Unsafe.Add(ref baseTargetRef, x) += Unsafe.Add(ref baseSourceRef, x).WeightedSum(z, w); - } - } - }); - } } } From 3cb81c3b40ba46606737d8aa0783684e79a175e8 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Wed, 27 Nov 2019 13:05:16 +0100 Subject: [PATCH 2/7] Removed execution mode field in pixel specific processor --- .../Convolution/BokehBlurProcessor{TPixel}.cs | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor{TPixel}.cs index 9c784099c..e6525cc8a 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor{TPixel}.cs @@ -36,11 +36,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// private readonly float gamma; - /// - /// The execution mode to use when applying the effect - /// - private readonly BokehBlurExecutionMode executionMode; - /// /// The maximum size of the kernel in either direction /// @@ -84,7 +79,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution this.kernelSize = (this.radius * 2) + 1; this.componentsCount = definition.Components; this.gamma = definition.Gamma; - this.executionMode = definition.ExecutionMode; // Reuse the initialized values from the cache, if possible var parameters = new BokehBlurParameters(this.radius, this.componentsCount); @@ -396,12 +390,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution var workingRectangle = Rectangle.FromLTRB(startX, startY, endX, endY); int width = workingRectangle.Width; - if (this.executionMode == BokehBlurExecutionMode.PreferLowMemoryUsage) - { - configuration = configuration.Clone(); - configuration.MaxDegreeOfParallelism = 1; - } - ParallelHelper.IterateRows( workingRectangle, configuration, From 2f68f0ded016891fbd59c51268b73ab9672ccbe8 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Wed, 27 Nov 2019 13:07:53 +0100 Subject: [PATCH 3/7] Removed execution mode options --- .../Extensions/BokehBlurExtensions.cs | 48 ------------------- .../Convolution/BokehBlurProcessor.cs | 44 +---------------- 2 files changed, 1 insertion(+), 91 deletions(-) diff --git a/src/ImageSharp/Processing/Extensions/BokehBlurExtensions.cs b/src/ImageSharp/Processing/Extensions/BokehBlurExtensions.cs index ef20f940a..2bbdd03b0 100644 --- a/src/ImageSharp/Processing/Extensions/BokehBlurExtensions.cs +++ b/src/ImageSharp/Processing/Extensions/BokehBlurExtensions.cs @@ -19,15 +19,6 @@ namespace SixLabors.ImageSharp.Processing public static IImageProcessingContext BokehBlur(this IImageProcessingContext source) => source.ApplyProcessor(new BokehBlurProcessor()); - /// - /// Applies a bokeh blur to the image. - /// - /// The image this method extends. - /// The execution mode to use when applying the processor. - /// The to allow chaining of operations. - public static IImageProcessingContext BokehBlur(this IImageProcessingContext source, BokehBlurExecutionMode executionMode) - => source.ApplyProcessor(new BokehBlurProcessor(executionMode)); - /// /// Applies a bokeh blur to the image. /// @@ -39,18 +30,6 @@ namespace SixLabors.ImageSharp.Processing public static IImageProcessingContext BokehBlur(this IImageProcessingContext source, int radius, int components, float gamma) => source.ApplyProcessor(new BokehBlurProcessor(radius, components, gamma)); - /// - /// Applies a bokeh blur to the image. - /// - /// The image this method extends. - /// The 'radius' value representing the size of the area to sample. - /// The 'components' value representing the number of kernels to use to approximate the bokeh effect. - /// The gamma highlight factor to use to emphasize bright spots in the source image - /// The execution mode to use when applying the processor. - /// The to allow chaining of operations. - public static IImageProcessingContext BokehBlur(this IImageProcessingContext source, int radius, int components, float gamma, BokehBlurExecutionMode executionMode) - => source.ApplyProcessor(new BokehBlurProcessor(radius, components, gamma, executionMode)); - /// /// Applies a bokeh blur to the image. /// @@ -62,18 +41,6 @@ namespace SixLabors.ImageSharp.Processing public static IImageProcessingContext BokehBlur(this IImageProcessingContext source, Rectangle rectangle) => source.ApplyProcessor(new BokehBlurProcessor(), rectangle); - /// - /// Applies a bokeh blur to the image. - /// - /// The image this method extends. - /// - /// The structure that specifies the portion of the image object to alter. - /// - /// The execution mode to use when applying the processor. - /// The to allow chaining of operations. - public static IImageProcessingContext BokehBlur(this IImageProcessingContext source, Rectangle rectangle, BokehBlurExecutionMode executionMode) - => source.ApplyProcessor(new BokehBlurProcessor(executionMode), rectangle); - /// /// Applies a bokeh blur to the image. /// @@ -87,20 +54,5 @@ namespace SixLabors.ImageSharp.Processing /// The to allow chaining of operations. public static IImageProcessingContext BokehBlur(this IImageProcessingContext source, int radius, int components, float gamma, Rectangle rectangle) => source.ApplyProcessor(new BokehBlurProcessor(radius, components, gamma), rectangle); - - /// - /// Applies a bokeh blur to the image. - /// - /// The image this method extends. - /// The 'radius' value representing the size of the area to sample. - /// The 'components' value representing the number of kernels to use to approximate the bokeh effect. - /// The gamma highlight factor to use to emphasize bright spots in the source image - /// The execution mode to use when applying the processor. - /// - /// The structure that specifies the portion of the image object to alter. - /// - /// The to allow chaining of operations. - public static IImageProcessingContext BokehBlur(this IImageProcessingContext source, int radius, int components, float gamma, BokehBlurExecutionMode executionMode, Rectangle rectangle) - => source.ApplyProcessor(new BokehBlurProcessor(radius, components, gamma, executionMode), rectangle); } } diff --git a/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor.cs index b7e102deb..1812884b8 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor.cs @@ -26,27 +26,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// public const float DefaultGamma = 3F; - /// - /// The default execution mode used by the parameterless constructor. - /// - public const BokehBlurExecutionMode DefaultExecutionMode = BokehBlurExecutionMode.PreferLowMemoryUsage; - /// /// Initializes a new instance of the class. /// public BokehBlurProcessor() - : this(DefaultRadius, DefaultComponents, DefaultGamma, DefaultExecutionMode) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// - /// The execution mode to use when applying the processor. - /// - public BokehBlurProcessor(BokehBlurExecutionMode executionMode) - : this(DefaultRadius, DefaultComponents, DefaultGamma, executionMode) + : this(DefaultRadius, DefaultComponents, DefaultGamma) { } @@ -63,33 +47,12 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// The gamma highlight factor to use to further process the image. /// public BokehBlurProcessor(int radius, int components, float gamma) - : this(radius, components, gamma, DefaultExecutionMode) - { - } - - /// - /// Initializes a new instance of the class. - /// - /// - /// The 'radius' value representing the size of the area to sample. - /// - /// - /// The number of components to use to approximate the original 2D bokeh blur convolution kernel. - /// - /// - /// The gamma highlight factor to use to further process the image. - /// - /// - /// The execution mode to use when applying the processor. - /// - public BokehBlurProcessor(int radius, int components, float gamma, BokehBlurExecutionMode executionMode) { Guard.MustBeGreaterThanOrEqualTo(gamma, 1, nameof(gamma)); this.Radius = radius; this.Components = components; this.Gamma = gamma; - this.ExecutionMode = executionMode; } /// @@ -107,11 +70,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// public float Gamma { get; } - /// - /// Gets the execution mode to use when applying the effect. - /// - public BokehBlurExecutionMode ExecutionMode { get; } - /// public IImageProcessor CreatePixelSpecificProcessor(Image source, Rectangle sourceRectangle) where TPixel : struct, IPixel From 626b26a63597db27ec9fe4a475558b483c831de1 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Wed, 27 Nov 2019 13:08:44 +0100 Subject: [PATCH 4/7] Removed BokehBlurExecutionMode enum --- .../Processing/BokehBlurExecutionMode.cs | 23 ------------------- 1 file changed, 23 deletions(-) delete mode 100644 src/ImageSharp/Processing/BokehBlurExecutionMode.cs diff --git a/src/ImageSharp/Processing/BokehBlurExecutionMode.cs b/src/ImageSharp/Processing/BokehBlurExecutionMode.cs deleted file mode 100644 index bc44dca03..000000000 --- a/src/ImageSharp/Processing/BokehBlurExecutionMode.cs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using SixLabors.ImageSharp.Processing.Processors.Convolution; - -namespace SixLabors.ImageSharp.Processing -{ - /// - /// An that indicates execution options for the . - /// - public enum BokehBlurExecutionMode - { - /// - /// Indicates that the maximum performance should be prioritized over memory usage. - /// - PreferMaximumPerformance, - - /// - /// Indicates that the memory usage should be prioritized over raw performance. - /// - PreferLowMemoryUsage - } -} From 0d7034debe8af2ed4f2a48826c5d69f26431cd89 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Wed, 27 Nov 2019 13:11:25 +0100 Subject: [PATCH 5/7] Minor code tweaks --- .../Convolution/BokehBlurProcessor{TPixel}.cs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor{TPixel}.cs index e6525cc8a..684aa07a7 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor{TPixel}.cs @@ -274,14 +274,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution this.ApplyGammaExposure(source.PixelBuffer, this.SourceRectangle, this.Configuration); // Create a 0-filled buffer to use to store the result of the component convolutions - using (Buffer2D processing = this.Configuration.MemoryAllocator.Allocate2D(source.Size(), AllocationOptions.Clean)) - using (Buffer2D firstPassValues = this.Configuration.MemoryAllocator.Allocate2D(source.Size())) + using (Buffer2D processingBuffer = this.Configuration.MemoryAllocator.Allocate2D(source.Size(), AllocationOptions.Clean)) + using (Buffer2D firstPassBuffer = this.Configuration.MemoryAllocator.Allocate2D(source.Size())) { // Perform the 1D convolutions on all the kernel components and accumulate the results - this.OnFrameApplyCore(source, this.SourceRectangle, this.Configuration, processing, firstPassValues); + this.OnFrameApplyCore(source, this.SourceRectangle, this.Configuration, processingBuffer, firstPassBuffer); // Apply the inverse gamma exposure pass, and write the final pixel data - this.ApplyInverseGammaExposure(source.PixelBuffer, processing, this.SourceRectangle, this.Configuration); + this.ApplyInverseGammaExposure(source.PixelBuffer, processingBuffer, this.SourceRectangle, this.Configuration); } } @@ -302,12 +302,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution { // Perform two 1D convolutions for each component in the current instance ref Complex64[] baseRef = ref MemoryMarshal.GetReference(this.kernels.AsSpan()); + ref Vector4 paramsRef = ref MemoryMarshal.GetReference(this.kernelParameters.AsSpan()); for (int i = 0; i < this.kernels.Length; i++) { // Compute the resulting complex buffer for the current component var interest = Rectangle.Intersect(sourceRectangle, source.Bounds()); Complex64[] kernel = Unsafe.Add(ref baseRef, i); - Vector4 parameters = this.kernelParameters[i]; + Vector4 parameters = Unsafe.Add(ref paramsRef, i); // Compute the two 1D convolutions and accumulate the partial results on the target buffer this.ApplyConvolution(firstPassBuffer, source.PixelBuffer, interest, kernel, configuration); From ef04d2f7180e332ed98f33db672921efbce5b4e9 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Wed, 27 Nov 2019 14:38:40 +0100 Subject: [PATCH 6/7] Minor code refactoring --- .../Convolution/BokehBlurProcessor{TPixel}.cs | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor{TPixel}.cs index 684aa07a7..efd18dafb 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor{TPixel}.cs @@ -275,10 +275,9 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution // Create a 0-filled buffer to use to store the result of the component convolutions using (Buffer2D processingBuffer = this.Configuration.MemoryAllocator.Allocate2D(source.Size(), AllocationOptions.Clean)) - using (Buffer2D firstPassBuffer = this.Configuration.MemoryAllocator.Allocate2D(source.Size())) { // Perform the 1D convolutions on all the kernel components and accumulate the results - this.OnFrameApplyCore(source, this.SourceRectangle, this.Configuration, processingBuffer, firstPassBuffer); + this.OnFrameApplyCore(source, this.SourceRectangle, this.Configuration, processingBuffer); // Apply the inverse gamma exposure pass, and write the final pixel data this.ApplyInverseGammaExposure(source.PixelBuffer, processingBuffer, this.SourceRectangle, this.Configuration); @@ -292,27 +291,28 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// The structure that specifies the portion of the image object to draw. /// The configuration. /// The buffer with the raw pixel data to use to aggregate the results of each convolution. - /// The complex buffer to use for the first 1D convolution pass for each kernel. private void OnFrameApplyCore( ImageFrame source, Rectangle sourceRectangle, Configuration configuration, - Buffer2D processingBuffer, - Buffer2D firstPassBuffer) + Buffer2D processingBuffer) { - // Perform two 1D convolutions for each component in the current instance - ref Complex64[] baseRef = ref MemoryMarshal.GetReference(this.kernels.AsSpan()); - ref Vector4 paramsRef = ref MemoryMarshal.GetReference(this.kernelParameters.AsSpan()); - for (int i = 0; i < this.kernels.Length; i++) + using (Buffer2D firstPassBuffer = this.Configuration.MemoryAllocator.Allocate2D(source.Size())) { - // Compute the resulting complex buffer for the current component - var interest = Rectangle.Intersect(sourceRectangle, source.Bounds()); - Complex64[] kernel = Unsafe.Add(ref baseRef, i); - Vector4 parameters = Unsafe.Add(ref paramsRef, i); - - // Compute the two 1D convolutions and accumulate the partial results on the target buffer - this.ApplyConvolution(firstPassBuffer, source.PixelBuffer, interest, kernel, configuration); - this.ApplyConvolution(processingBuffer, firstPassBuffer, interest, kernel, configuration, parameters.Z, parameters.W); + // Perform two 1D convolutions for each component in the current instance + ref Complex64[] baseRef = ref MemoryMarshal.GetReference(this.kernels.AsSpan()); + ref Vector4 paramsRef = ref MemoryMarshal.GetReference(this.kernelParameters.AsSpan()); + for (int i = 0; i < this.kernels.Length; i++) + { + // Compute the resulting complex buffer for the current component + var interest = Rectangle.Intersect(sourceRectangle, source.Bounds()); + Complex64[] kernel = Unsafe.Add(ref baseRef, i); + Vector4 parameters = Unsafe.Add(ref paramsRef, i); + + // Compute the two 1D convolutions and accumulate the partial results on the target buffer + this.ApplyConvolution(firstPassBuffer, source.PixelBuffer, interest, kernel, configuration); + this.ApplyConvolution(processingBuffer, firstPassBuffer, interest, kernel, configuration, parameters.Z, parameters.W); + } } } From 8a89fdc2fbf023fa830d340f49d952b683105008 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Wed, 27 Nov 2019 15:36:42 +0100 Subject: [PATCH 7/7] Removed unnecessary Buffer2D.Slice API --- src/ImageSharp/Memory/Buffer2D{T}.cs | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/src/ImageSharp/Memory/Buffer2D{T}.cs b/src/ImageSharp/Memory/Buffer2D{T}.cs index 06cfdf560..69dff78c1 100644 --- a/src/ImageSharp/Memory/Buffer2D{T}.cs +++ b/src/ImageSharp/Memory/Buffer2D{T}.cs @@ -69,23 +69,6 @@ namespace SixLabors.ImageSharp.Memory } } - /// - /// Creates a new instance that maps to a target rows interval from the current instance. - /// - /// The target vertical offset for the rows interval to retrieve. - /// The desired number of rows to extract. - /// The new instance with the requested rows interval. - public Buffer2D Slice(int y, int h) - { - DebugGuard.MustBeGreaterThanOrEqualTo(y, 0, nameof(y)); - DebugGuard.MustBeGreaterThan(h, 0, nameof(h)); - DebugGuard.MustBeLessThanOrEqualTo(y + h, this.Height, nameof(h)); - - Memory slice = this.GetMemory().Slice(y * this.Width, h * this.Width); - var memory = new MemorySource(slice); - return new Buffer2D(memory, this.Width, h); - } - /// /// Disposes the instance ///