From 5708137dbdda6d855650f32960bf157ac0eca682 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Fri, 7 Feb 2020 17:47:34 +0100 Subject: [PATCH] Refactor processors to single row with buffer APIs --- .../Convolution/BokehBlurProcessor{TPixel}.cs | 38 ++++----- .../Convolution2DProcessor{TPixel}.cs | 84 +++++++++---------- .../Convolution2PassProcessor{TPixel}.cs | 84 +++++++++---------- .../ConvolutionProcessor{TPixel}.cs | 80 +++++++++--------- ...lRowDelegateProcessor{TPixel,TDelegate}.cs | 27 +++--- .../Filters/FilterProcessor{TPixel}.cs | 25 +++--- .../Overlays/GlowProcessor{TPixel}.cs | 36 ++++---- .../Overlays/VignetteProcessor{TPixel}.cs | 38 ++++----- .../AffineTransformProcessor{TPixel}.cs | 58 ++++++------- .../ProjectiveTransformProcessor{TPixel}.cs | 69 +++++++-------- 10 files changed, 251 insertions(+), 288 deletions(-) diff --git a/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor{TPixel}.cs index 326522996..7eb91b68d 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor{TPixel}.cs @@ -268,10 +268,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution protected override void OnFrameApply(ImageFrame source) { // Preliminary gamma highlight pass - ParallelRowIterator.IterateRows( + ParallelRowIterator.IterateRows2( this.SourceRectangle, this.Configuration, - new ApplyGammaExposureRowIntervalAction(this.SourceRectangle, source.PixelBuffer, this.Configuration, this.gamma)); + new ApplyGammaExposureRowAction(this.SourceRectangle, source.PixelBuffer, this.Configuration, this.gamma)); // 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); @@ -416,7 +416,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// /// A implementing the gamma exposure logic for . /// - private readonly struct ApplyGammaExposureRowIntervalAction : IRowIntervalAction + private readonly struct ApplyGammaExposureRowAction : IRowAction { private readonly Rectangle bounds; private readonly Buffer2D targetPixels; @@ -424,7 +424,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution private readonly float gamma; [MethodImpl(InliningOptions.ShortMethod)] - public ApplyGammaExposureRowIntervalAction( + public ApplyGammaExposureRowAction( Rectangle bounds, Buffer2D targetPixels, Configuration configuration, @@ -438,27 +438,23 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// [MethodImpl(InliningOptions.ShortMethod)] - public void Invoke(in RowInterval rows, Memory memory) + public void Invoke(int y, Span span) { - Span vectorSpan = memory.Span; - int length = vectorSpan.Length; + int length = span.Length; - for (int y = rows.Min; y < rows.Max; y++) - { - Span targetRowSpan = this.targetPixels.GetRowSpan(y).Slice(this.bounds.X); - PixelOperations.Instance.ToVector4(this.configuration, targetRowSpan.Slice(0, length), vectorSpan, PixelConversionModifiers.Premultiply); - ref Vector4 baseRef = ref MemoryMarshal.GetReference(vectorSpan); - - for (int x = 0; x < this.bounds.Width; x++) - { - ref Vector4 v = ref Unsafe.Add(ref baseRef, x); - v.X = MathF.Pow(v.X, this.gamma); - v.Y = MathF.Pow(v.Y, this.gamma); - v.Z = MathF.Pow(v.Z, this.gamma); - } + Span targetRowSpan = this.targetPixels.GetRowSpan(y).Slice(this.bounds.X); + PixelOperations.Instance.ToVector4(this.configuration, targetRowSpan.Slice(0, length), span, PixelConversionModifiers.Premultiply); + ref Vector4 baseRef = ref MemoryMarshal.GetReference(span); - PixelOperations.Instance.FromVector4Destructive(this.configuration, vectorSpan.Slice(0, length), targetRowSpan); + for (int x = 0; x < this.bounds.Width; x++) + { + ref Vector4 v = ref Unsafe.Add(ref baseRef, x); + v.X = MathF.Pow(v.X, this.gamma); + v.Y = MathF.Pow(v.Y, this.gamma); + v.Z = MathF.Pow(v.Z, this.gamma); } + + PixelOperations.Instance.FromVector4Destructive(this.configuration, span.Slice(0, length), targetRowSpan); } } diff --git a/src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor{TPixel}.cs index cd550a335..c169ef38d 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor{TPixel}.cs @@ -66,10 +66,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution var interest = Rectangle.Intersect(this.SourceRectangle, source.Bounds()); - ParallelRowIterator.IterateRows( + ParallelRowIterator.IterateRows2( interest, this.Configuration, - new RowIntervalAction(interest, targetPixels, source.PixelBuffer, this.KernelY, this.KernelX, this.Configuration, this.PreserveAlpha)); + new RowAction(interest, targetPixels, source.PixelBuffer, this.KernelY, this.KernelX, this.Configuration, this.PreserveAlpha)); Buffer2D.SwapOrCopyContent(source.PixelBuffer, targetPixels); } @@ -77,7 +77,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// /// A implementing the convolution logic for . /// - private readonly struct RowIntervalAction : IRowIntervalAction + private readonly struct RowAction : IRowAction { private readonly Rectangle bounds; private readonly int maxY; @@ -90,7 +90,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution private readonly bool preserveAlpha; [MethodImpl(InliningOptions.ShortMethod)] - public RowIntervalAction( + public RowAction( Rectangle bounds, Buffer2D targetPixels, Buffer2D sourcePixels, @@ -112,54 +112,50 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// [MethodImpl(InliningOptions.ShortMethod)] - public void Invoke(in RowInterval rows, Memory memory) + public void Invoke(int y, Span span) { - Span vectorSpan = memory.Span; - int length = vectorSpan.Length; - ref Vector4 vectorSpanRef = ref MemoryMarshal.GetReference(vectorSpan); + int length = span.Length; + ref Vector4 vectorSpanRef = ref MemoryMarshal.GetReference(span); - for (int y = rows.Min; y < rows.Max; y++) - { - Span targetRowSpan = this.targetPixels.GetRowSpan(y).Slice(this.bounds.X); - PixelOperations.Instance.ToVector4(this.configuration, targetRowSpan.Slice(0, length), vectorSpan); + Span targetRowSpan = this.targetPixels.GetRowSpan(y).Slice(this.bounds.X); + PixelOperations.Instance.ToVector4(this.configuration, targetRowSpan.Slice(0, length), span); - if (this.preserveAlpha) + if (this.preserveAlpha) + { + for (int x = 0; x < this.bounds.Width; x++) { - for (int x = 0; x < this.bounds.Width; x++) - { - DenseMatrixUtils.Convolve2D3( - in this.kernelY, - in this.kernelX, - this.sourcePixels, - ref vectorSpanRef, - y, - x, - this.bounds.Y, - this.maxY, - this.bounds.X, - this.maxX); - } + DenseMatrixUtils.Convolve2D3( + in this.kernelY, + in this.kernelX, + this.sourcePixels, + ref vectorSpanRef, + y, + x, + this.bounds.Y, + this.maxY, + this.bounds.X, + this.maxX); } - else + } + else + { + for (int x = 0; x < this.bounds.Width; x++) { - for (int x = 0; x < this.bounds.Width; x++) - { - DenseMatrixUtils.Convolve2D4( - in this.kernelY, - in this.kernelX, - this.sourcePixels, - ref vectorSpanRef, - y, - x, - this.bounds.Y, - this.maxY, - this.bounds.X, - this.maxX); - } + DenseMatrixUtils.Convolve2D4( + in this.kernelY, + in this.kernelX, + this.sourcePixels, + ref vectorSpanRef, + y, + x, + this.bounds.Y, + this.maxY, + this.bounds.X, + this.maxX); } - - PixelOperations.Instance.FromVector4Destructive(this.configuration, vectorSpan, targetRowSpan); } + + PixelOperations.Instance.FromVector4Destructive(this.configuration, span, targetRowSpan); } } } diff --git a/src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor{TPixel}.cs index 1be97a4f8..156c20d38 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor{TPixel}.cs @@ -64,22 +64,22 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution var interest = Rectangle.Intersect(this.SourceRectangle, source.Bounds()); // Horizontal convolution - ParallelRowIterator.IterateRows( + ParallelRowIterator.IterateRows2( interest, this.Configuration, - new RowIntervalAction(interest, firstPassPixels, source.PixelBuffer, this.KernelX, this.Configuration, this.PreserveAlpha)); + new RowAction(interest, firstPassPixels, source.PixelBuffer, this.KernelX, this.Configuration, this.PreserveAlpha)); // Vertical convolution - ParallelRowIterator.IterateRows( + ParallelRowIterator.IterateRows2( interest, this.Configuration, - new RowIntervalAction(interest, source.PixelBuffer, firstPassPixels, this.KernelY, this.Configuration, this.PreserveAlpha)); + new RowAction(interest, source.PixelBuffer, firstPassPixels, this.KernelY, this.Configuration, this.PreserveAlpha)); } /// /// A implementing the convolution logic for . /// - private readonly struct RowIntervalAction : IRowIntervalAction + private readonly struct RowAction : IRowAction { private readonly Rectangle bounds; private readonly Buffer2D targetPixels; @@ -89,7 +89,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution private readonly bool preserveAlpha; [MethodImpl(InliningOptions.ShortMethod)] - public RowIntervalAction( + public RowAction( Rectangle bounds, Buffer2D targetPixels, Buffer2D sourcePixels, @@ -107,55 +107,51 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// [MethodImpl(InliningOptions.ShortMethod)] - public void Invoke(in RowInterval rows, Memory memory) + public void Invoke(int y, Span span) { - Span vectorSpan = memory.Span; - int length = vectorSpan.Length; - ref Vector4 vectorSpanRef = ref MemoryMarshal.GetReference(vectorSpan); + int length = span.Length; + ref Vector4 vectorSpanRef = ref MemoryMarshal.GetReference(span); int maxY = this.bounds.Bottom - 1; int maxX = this.bounds.Right - 1; - for (int y = rows.Min; y < rows.Max; y++) - { - Span targetRowSpan = this.targetPixels.GetRowSpan(y).Slice(this.bounds.X); - PixelOperations.Instance.ToVector4(this.configuration, targetRowSpan.Slice(0, length), vectorSpan); + Span targetRowSpan = this.targetPixels.GetRowSpan(y).Slice(this.bounds.X); + PixelOperations.Instance.ToVector4(this.configuration, targetRowSpan.Slice(0, length), span); - if (this.preserveAlpha) + if (this.preserveAlpha) + { + for (int x = 0; x < this.bounds.Width; x++) { - for (int x = 0; x < this.bounds.Width; x++) - { - DenseMatrixUtils.Convolve3( - in this.kernel, - this.sourcePixels, - ref vectorSpanRef, - y, - x, - this.bounds.Y, - maxY, - this.bounds.X, - maxX); - } + DenseMatrixUtils.Convolve3( + in this.kernel, + this.sourcePixels, + ref vectorSpanRef, + y, + x, + this.bounds.Y, + maxY, + this.bounds.X, + maxX); } - else + } + else + { + for (int x = 0; x < this.bounds.Width; x++) { - for (int x = 0; x < this.bounds.Width; x++) - { - DenseMatrixUtils.Convolve4( - in this.kernel, - this.sourcePixels, - ref vectorSpanRef, - y, - x, - this.bounds.Y, - maxY, - this.bounds.X, - maxX); - } + DenseMatrixUtils.Convolve4( + in this.kernel, + this.sourcePixels, + ref vectorSpanRef, + y, + x, + this.bounds.Y, + maxY, + this.bounds.X, + maxX); } - - PixelOperations.Instance.FromVector4Destructive(this.configuration, vectorSpan, targetRowSpan); } + + PixelOperations.Instance.FromVector4Destructive(this.configuration, span, targetRowSpan); } } } diff --git a/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor{TPixel}.cs index b68dc56e0..6c56af6bb 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor{TPixel}.cs @@ -57,10 +57,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution var interest = Rectangle.Intersect(this.SourceRectangle, source.Bounds()); - ParallelRowIterator.IterateRows( + ParallelRowIterator.IterateRows2( interest, this.Configuration, - new RowIntervalAction(interest, targetPixels, source.PixelBuffer, this.KernelXY, this.Configuration, this.PreserveAlpha)); + new RowAction(interest, targetPixels, source.PixelBuffer, this.KernelXY, this.Configuration, this.PreserveAlpha)); Buffer2D.SwapOrCopyContent(source.PixelBuffer, targetPixels); } @@ -68,7 +68,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// /// A implementing the convolution logic for . /// - private readonly struct RowIntervalAction : IRowIntervalAction + private readonly struct RowAction : IRowAction { private readonly Rectangle bounds; private readonly int maxY; @@ -80,7 +80,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution private readonly bool preserveAlpha; [MethodImpl(InliningOptions.ShortMethod)] - public RowIntervalAction( + public RowAction( Rectangle bounds, Buffer2D targetPixels, Buffer2D sourcePixels, @@ -100,52 +100,48 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution /// [MethodImpl(InliningOptions.ShortMethod)] - public void Invoke(in RowInterval rows, Memory memory) + public void Invoke(int y, Span span) { - Span vectorSpan = memory.Span; - int length = vectorSpan.Length; - ref Vector4 vectorSpanRef = ref MemoryMarshal.GetReference(vectorSpan); + int length = span.Length; + ref Vector4 vectorSpanRef = ref MemoryMarshal.GetReference(span); - for (int y = rows.Min; y < rows.Max; y++) - { - Span targetRowSpan = this.targetPixels.GetRowSpan(y).Slice(this.bounds.X); - PixelOperations.Instance.ToVector4(this.configuration, targetRowSpan.Slice(0, length), vectorSpan); + Span targetRowSpan = this.targetPixels.GetRowSpan(y).Slice(this.bounds.X); + PixelOperations.Instance.ToVector4(this.configuration, targetRowSpan.Slice(0, length), span); - if (this.preserveAlpha) + if (this.preserveAlpha) + { + for (int x = 0; x < this.bounds.Width; x++) { - for (int x = 0; x < this.bounds.Width; x++) - { - DenseMatrixUtils.Convolve3( - in this.kernel, - this.sourcePixels, - ref vectorSpanRef, - y, - x, - this.bounds.Y, - this.maxY, - this.bounds.X, - this.maxX); - } + DenseMatrixUtils.Convolve3( + in this.kernel, + this.sourcePixels, + ref vectorSpanRef, + y, + x, + this.bounds.Y, + this.maxY, + this.bounds.X, + this.maxX); } - else + } + else + { + for (int x = 0; x < this.bounds.Width; x++) { - for (int x = 0; x < this.bounds.Width; x++) - { - DenseMatrixUtils.Convolve4( - in this.kernel, - this.sourcePixels, - ref vectorSpanRef, - y, - x, - this.bounds.Y, - this.maxY, - this.bounds.X, - this.maxX); - } + DenseMatrixUtils.Convolve4( + in this.kernel, + this.sourcePixels, + ref vectorSpanRef, + y, + x, + this.bounds.Y, + this.maxY, + this.bounds.X, + this.maxX); } - - PixelOperations.Instance.FromVector4Destructive(this.configuration, vectorSpan, targetRowSpan); } + + PixelOperations.Instance.FromVector4Destructive(this.configuration, span, targetRowSpan); } } } diff --git a/src/ImageSharp/Processing/Processors/Effects/PixelRowDelegateProcessor{TPixel,TDelegate}.cs b/src/ImageSharp/Processing/Processors/Effects/PixelRowDelegateProcessor{TPixel,TDelegate}.cs index fd725d3ba..99e0341b4 100644 --- a/src/ImageSharp/Processing/Processors/Effects/PixelRowDelegateProcessor{TPixel,TDelegate}.cs +++ b/src/ImageSharp/Processing/Processors/Effects/PixelRowDelegateProcessor{TPixel,TDelegate}.cs @@ -5,7 +5,6 @@ using System; using System.Numerics; using System.Runtime.CompilerServices; using SixLabors.ImageSharp.Advanced; -using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp.Processing.Processors.Effects @@ -51,16 +50,16 @@ namespace SixLabors.ImageSharp.Processing.Processors.Effects { var interest = Rectangle.Intersect(this.SourceRectangle, source.Bounds()); - ParallelRowIterator.IterateRows( + ParallelRowIterator.IterateRows2( interest, this.Configuration, - new RowIntervalAction(interest.X, source, this.Configuration, this.modifiers, this.rowDelegate)); + new RowAction(interest.X, source, this.Configuration, this.modifiers, this.rowDelegate)); } /// /// A implementing the convolution logic for . /// - private readonly struct RowIntervalAction : IRowIntervalAction + private readonly struct RowAction : IRowAction { private readonly int startX; private readonly ImageFrame source; @@ -69,7 +68,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Effects private readonly TDelegate rowProcessor; [MethodImpl(InliningOptions.ShortMethod)] - public RowIntervalAction( + public RowAction( int startX, ImageFrame source, Configuration configuration, @@ -85,20 +84,16 @@ namespace SixLabors.ImageSharp.Processing.Processors.Effects /// [MethodImpl(InliningOptions.ShortMethod)] - public void Invoke(in RowInterval rows, Memory memory) + public void Invoke(int y, Span span) { - for (int y = rows.Min; y < rows.Max; y++) - { - Span vectorSpan = memory.Span; - int length = vectorSpan.Length; - Span rowSpan = this.source.GetPixelRowSpan(y).Slice(this.startX, length); - PixelOperations.Instance.ToVector4(this.configuration, rowSpan, vectorSpan, this.modifiers); + int length = span.Length; + Span rowSpan = this.source.GetPixelRowSpan(y).Slice(this.startX, length); + PixelOperations.Instance.ToVector4(this.configuration, rowSpan, span, this.modifiers); - // Run the user defined pixel shader to the current row of pixels - Unsafe.AsRef(this.rowProcessor).Invoke(vectorSpan, new Point(this.startX, y)); + // Run the user defined pixel shader to the current row of pixels + Unsafe.AsRef(this.rowProcessor).Invoke(span, new Point(this.startX, y)); - PixelOperations.Instance.FromVector4Destructive(this.configuration, vectorSpan, rowSpan, this.modifiers); - } + PixelOperations.Instance.FromVector4Destructive(this.configuration, span, rowSpan, this.modifiers); } } } diff --git a/src/ImageSharp/Processing/Processors/Filters/FilterProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Filters/FilterProcessor{TPixel}.cs index cdb67e48b..2426765f8 100644 --- a/src/ImageSharp/Processing/Processors/Filters/FilterProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Filters/FilterProcessor{TPixel}.cs @@ -5,7 +5,6 @@ using System; using System.Numerics; using System.Runtime.CompilerServices; using SixLabors.ImageSharp.Advanced; -using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp.Processing.Processors.Filters @@ -37,16 +36,16 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters { var interest = Rectangle.Intersect(this.SourceRectangle, source.Bounds()); - ParallelRowIterator.IterateRows( + ParallelRowIterator.IterateRows2( interest, this.Configuration, - new RowIntervalAction(interest.X, source, this.definition.Matrix, this.Configuration)); + new RowAction(interest.X, source, this.definition.Matrix, this.Configuration)); } /// /// A implementing the convolution logic for . /// - private readonly struct RowIntervalAction : IRowIntervalAction + private readonly struct RowAction : IRowAction { private readonly int startX; private readonly ImageFrame source; @@ -54,7 +53,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters private readonly Configuration configuration; [MethodImpl(InliningOptions.ShortMethod)] - public RowIntervalAction( + public RowAction( int startX, ImageFrame source, ColorMatrix matrix, @@ -68,19 +67,15 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters /// [MethodImpl(InliningOptions.ShortMethod)] - public void Invoke(in RowInterval rows, Memory memory) + public void Invoke(int y, Span span) { - for (int y = rows.Min; y < rows.Max; y++) - { - Span vectorSpan = memory.Span; - int length = vectorSpan.Length; - Span rowSpan = this.source.GetPixelRowSpan(y).Slice(this.startX, length); - PixelOperations.Instance.ToVector4(this.configuration, rowSpan, vectorSpan); + int length = span.Length; + Span rowSpan = this.source.GetPixelRowSpan(y).Slice(this.startX, length); + PixelOperations.Instance.ToVector4(this.configuration, rowSpan, span); - Vector4Utils.Transform(vectorSpan, ref Unsafe.AsRef(this.matrix)); + Vector4Utils.Transform(span, ref Unsafe.AsRef(this.matrix)); - PixelOperations.Instance.FromVector4Destructive(this.configuration, vectorSpan, rowSpan); - } + PixelOperations.Instance.FromVector4Destructive(this.configuration, span, rowSpan); } } } diff --git a/src/ImageSharp/Processing/Processors/Overlays/GlowProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Overlays/GlowProcessor{TPixel}.cs index 65a87fbf0..1b321310d 100644 --- a/src/ImageSharp/Processing/Processors/Overlays/GlowProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Overlays/GlowProcessor{TPixel}.cs @@ -55,13 +55,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays using IMemoryOwner rowColors = allocator.Allocate(interest.Width); rowColors.GetSpan().Fill(glowColor); - ParallelRowIterator.IterateRows( + ParallelRowIterator.IterateRows2( interest, configuration, - new RowIntervalAction(configuration, interest, rowColors, this.blender, center, maxDistance, blendPercent, source)); + new RowAction(configuration, interest, rowColors, this.blender, center, maxDistance, blendPercent, source)); } - private readonly struct RowIntervalAction : IRowIntervalAction + private readonly struct RowAction : IRowAction { private readonly Configuration configuration; private readonly Rectangle bounds; @@ -73,7 +73,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays private readonly ImageFrame source; [MethodImpl(InliningOptions.ShortMethod)] - public RowIntervalAction( + public RowAction( Configuration configuration, Rectangle bounds, IMemoryOwner colors, @@ -94,28 +94,24 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays } [MethodImpl(InliningOptions.ShortMethod)] - public void Invoke(in RowInterval rows, Memory memory) + public void Invoke(int y, Span span) { - Span amountsSpan = memory.Span; Span colorSpan = this.colors.GetSpan(); - for (int y = rows.Min; y < rows.Max; y++) + for (int i = 0; i < this.bounds.Width; i++) { - for (int i = 0; i < this.bounds.Width; i++) - { - float distance = Vector2.Distance(this.center, new Vector2(i + this.bounds.X, y)); - amountsSpan[i] = (this.blendPercent * (1 - (.95F * (distance / this.maxDistance)))).Clamp(0, 1); - } + float distance = Vector2.Distance(this.center, new Vector2(i + this.bounds.X, y)); + span[i] = (this.blendPercent * (1 - (.95F * (distance / this.maxDistance)))).Clamp(0, 1); + } - Span destination = this.source.GetPixelRowSpan(y).Slice(this.bounds.X, this.bounds.Width); + Span destination = this.source.GetPixelRowSpan(y).Slice(this.bounds.X, this.bounds.Width); - this.blender.Blend( - this.configuration, - destination, - destination, - colorSpan, - amountsSpan); - } + this.blender.Blend( + this.configuration, + destination, + destination, + colorSpan, + span); } } } diff --git a/src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor{TPixel}.cs index 11887433c..1ca83190c 100644 --- a/src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor{TPixel}.cs @@ -63,13 +63,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays using IMemoryOwner rowColors = allocator.Allocate(interest.Width); rowColors.GetSpan().Fill(vignetteColor); - ParallelRowIterator.IterateRows( + ParallelRowIterator.IterateRows2( interest, configuration, - new RowIntervalAction(configuration, interest, rowColors, this.blender, center, maxDistance, blendPercent, source)); + new RowAction(configuration, interest, rowColors, this.blender, center, maxDistance, blendPercent, source)); } - private readonly struct RowIntervalAction : IRowIntervalAction + private readonly struct RowAction : IRowAction { private readonly Configuration configuration; private readonly Rectangle bounds; @@ -81,7 +81,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays private readonly ImageFrame source; [MethodImpl(InliningOptions.ShortMethod)] - public RowIntervalAction( + public RowAction( Configuration configuration, Rectangle bounds, IMemoryOwner colors, @@ -102,28 +102,24 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays } [MethodImpl(InliningOptions.ShortMethod)] - public void Invoke(in RowInterval rows, Memory memory) + public void Invoke(int y, Span span) { - Span amountsSpan = memory.Span; Span colorSpan = this.colors.GetSpan(); - for (int y = rows.Min; y < rows.Max; y++) + for (int i = 0; i < this.bounds.Width; i++) { - for (int i = 0; i < this.bounds.Width; i++) - { - float distance = Vector2.Distance(this.center, new Vector2(i + this.bounds.X, y)); - amountsSpan[i] = (this.blendPercent * (.9F * (distance / this.maxDistance))).Clamp(0, 1); - } - - Span destination = this.source.GetPixelRowSpan(y).Slice(this.bounds.X, this.bounds.Width); - - this.blender.Blend( - this.configuration, - destination, - destination, - colorSpan, - amountsSpan); + float distance = Vector2.Distance(this.center, new Vector2(i + this.bounds.X, y)); + span[i] = (this.blendPercent * (.9F * (distance / this.maxDistance))).Clamp(0, 1); } + + Span destination = this.source.GetPixelRowSpan(y).Slice(this.bounds.X, this.bounds.Width); + + this.blender.Blend( + this.configuration, + destination, + destination, + colorSpan, + span); } } } diff --git a/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor{TPixel}.cs index 8a44dcd9b..e7f6f429c 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor{TPixel}.cs @@ -5,7 +5,6 @@ using System; using System.Numerics; using System.Runtime.CompilerServices; using SixLabors.ImageSharp.Advanced; -using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp.Processing.Processors.Transforms @@ -68,10 +67,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms using var kernelMap = new TransformKernelMap(configuration, source.Size(), destination.Size(), this.resampler); - ParallelRowIterator.IterateRows( + ParallelRowIterator.IterateRows2( targetBounds, configuration, - new RowIntervalAction(configuration, kernelMap, ref matrix, width, source, destination)); + new RowAction(configuration, kernelMap, ref matrix, width, source, destination)); } /// @@ -101,7 +100,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms } /// - /// [MethodImpl(InliningOptions.ShortMethod)] public void Invoke(int y) { @@ -121,7 +119,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms /// /// A implementing the transformation logic for . /// - private readonly struct RowIntervalAction : IRowIntervalAction + private readonly struct RowAction : IRowAction { private readonly Configuration configuration; private readonly TransformKernelMap kernelMap; @@ -131,7 +129,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms private readonly ImageFrame destination; [MethodImpl(InliningOptions.ShortMethod)] - public RowIntervalAction( + public RowAction( Configuration configuration, TransformKernelMap kernelMap, ref Matrix3x2 matrix, @@ -149,35 +147,31 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms /// [MethodImpl(InliningOptions.ShortMethod)] - public void Invoke(in RowInterval rows, Memory memory) + public void Invoke(int y, Span span) { - Span vectorSpan = memory.Span; - for (int y = rows.Min; y < rows.Max; y++) - { - Span targetRowSpan = this.destination.GetPixelRowSpan(y); - PixelOperations.Instance.ToVector4(this.configuration, targetRowSpan, vectorSpan); - ref float ySpanRef = ref this.kernelMap.GetYStartReference(y); - ref float xSpanRef = ref this.kernelMap.GetXStartReference(y); - - for (int x = 0; x < this.maxX; x++) - { - // 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); - this.kernelMap.Convolve( - point, - x, - ref ySpanRef, - ref xSpanRef, - this.source.PixelBuffer, - vectorSpan); - } + Span targetRowSpan = this.destination.GetPixelRowSpan(y); + PixelOperations.Instance.ToVector4(this.configuration, targetRowSpan, span); + ref float ySpanRef = ref this.kernelMap.GetYStartReference(y); + ref float xSpanRef = ref this.kernelMap.GetXStartReference(y); - PixelOperations.Instance.FromVector4Destructive( - this.configuration, - vectorSpan, - targetRowSpan); + for (int x = 0; x < this.maxX; x++) + { + // 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); + this.kernelMap.Convolve( + point, + x, + ref ySpanRef, + ref xSpanRef, + this.source.PixelBuffer, + span); } + + PixelOperations.Instance.FromVector4Destructive( + this.configuration, + span, + targetRowSpan); } } } diff --git a/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor{TPixel}.cs index 6619ea892..8e219f7cc 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor{TPixel}.cs @@ -5,7 +5,6 @@ using System; using System.Numerics; using System.Runtime.CompilerServices; using SixLabors.ImageSharp.Advanced; -using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp.Processing.Processors.Transforms @@ -17,9 +16,9 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms internal class ProjectiveTransformProcessor : TransformProcessor where TPixel : struct, IPixel { - private Size targetSize; + private readonly Size targetSize; private readonly IResampler resampler; - private Matrix4x4 transformMatrix; + private readonly Matrix4x4 transformMatrix; /// /// Initializes a new instance of the class. @@ -70,12 +69,15 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms using var kernelMap = new TransformKernelMap(configuration, source.Size(), destination.Size(), this.resampler); - ParallelRowIterator.IterateRows( + ParallelRowIterator.IterateRows2( targetBounds, configuration, - new RowIntervalAction(configuration, kernelMap, ref matrix, width, source, destination)); + new RowAction(configuration, kernelMap, ref matrix, width, source, destination)); } + /// + /// A implementing the nearest neighbor interpolation logic for . + /// private readonly struct NearestNeighborRowAction : IRowAction { private readonly Rectangle bounds; @@ -99,6 +101,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms this.destination = destination; } + /// [MethodImpl(InliningOptions.ShortMethod)] public void Invoke(int y) { @@ -118,7 +121,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms } } - private readonly struct RowIntervalAction : IRowIntervalAction + /// + /// A implementing the convolution logic for . + /// + private readonly struct RowAction : IRowAction { private readonly Configuration configuration; private readonly TransformKernelMap kernelMap; @@ -128,7 +134,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms private readonly ImageFrame destination; [MethodImpl(InliningOptions.ShortMethod)] - public RowIntervalAction( + public RowAction( Configuration configuration, TransformKernelMap kernelMap, ref Matrix4x4 matrix, @@ -144,36 +150,33 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms this.destination = destination; } + /// [MethodImpl(InliningOptions.ShortMethod)] - public void Invoke(in RowInterval rows, Memory memory) + public void Invoke(int y, Span span) { - Span vectorSpan = memory.Span; - for (int y = rows.Min; y < rows.Max; y++) - { - Span targetRowSpan = this.destination.GetPixelRowSpan(y); - PixelOperations.Instance.ToVector4(this.configuration, targetRowSpan, vectorSpan); - ref float ySpanRef = ref this.kernelMap.GetYStartReference(y); - ref float xSpanRef = ref this.kernelMap.GetXStartReference(y); - - for (int x = 0; x < this.maxX; x++) - { - // 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); - this.kernelMap.Convolve( - point, - x, - ref ySpanRef, - ref xSpanRef, - this.source.PixelBuffer, - vectorSpan); - } + Span targetRowSpan = this.destination.GetPixelRowSpan(y); + PixelOperations.Instance.ToVector4(this.configuration, targetRowSpan, span); + ref float ySpanRef = ref this.kernelMap.GetYStartReference(y); + ref float xSpanRef = ref this.kernelMap.GetXStartReference(y); - PixelOperations.Instance.FromVector4Destructive( - this.configuration, - vectorSpan, - targetRowSpan); + for (int x = 0; x < this.maxX; x++) + { + // 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); + this.kernelMap.Convolve( + point, + x, + ref ySpanRef, + ref xSpanRef, + this.source.PixelBuffer, + span); } + + PixelOperations.Instance.FromVector4Destructive( + this.configuration, + span, + targetRowSpan); } } }