diff --git a/src/ImageSharp/Processing/Processors/Effects/PixelRowDelegateProcessorBase{TPixel}.cs b/src/ImageSharp/Processing/Processors/Effects/PixelRowDelegateProcessorBase{TPixel}.cs index 8926ddc66..16d8c0ed4 100644 --- a/src/ImageSharp/Processing/Processors/Effects/PixelRowDelegateProcessorBase{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Effects/PixelRowDelegateProcessorBase{TPixel}.cs @@ -3,7 +3,9 @@ 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 @@ -35,28 +37,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Effects protected override void OnFrameApply(ImageFrame source) { var interest = Rectangle.Intersect(this.SourceRectangle, source.Bounds()); - int startX = interest.X; - Configuration configuration = this.Configuration; - PixelConversionModifiers modifiers = this.modifiers; - ParallelRowIterator.IterateRows( + ParallelRowIterator.IterateRows( interest, this.Configuration, - (rows, vectorBuffer) => - { - for (int y = rows.Min; y < rows.Max; y++) - { - Span vectorSpan = vectorBuffer.Span; - int length = vectorSpan.Length; - Span rowSpan = source.GetPixelRowSpan(y).Slice(startX, length); - PixelOperations.Instance.ToVector4(configuration, rowSpan, vectorSpan, modifiers); - - // Run the user defined pixel shader to the current row of pixels - this.ApplyPixelRowDelegate(vectorSpan, new Point(startX, y)); - - PixelOperations.Instance.FromVector4Destructive(configuration, vectorSpan, rowSpan, modifiers); - } - }); + new RowIntervalAction(interest.X, source, this.Configuration, this.modifiers, this)); } /// @@ -65,5 +50,50 @@ namespace SixLabors.ImageSharp.Processing.Processors.Effects /// The target row of pixels to process. /// The initial horizontal and vertical offset for the input pixels to process. protected abstract void ApplyPixelRowDelegate(Span span, Point offset); + + /// + /// A implementing the convolution logic for . + /// + private readonly struct RowIntervalAction : IRowIntervalAction + { + private readonly int startX; + private readonly ImageFrame source; + private readonly Configuration configuration; + private readonly PixelConversionModifiers modifiers; + private readonly PixelRowDelegateProcessorBase processor; + + [MethodImpl(InliningOptions.ShortMethod)] + public RowIntervalAction( + int startX, + ImageFrame source, + Configuration configuration, + PixelConversionModifiers modifiers, + PixelRowDelegateProcessorBase processor) + { + this.startX = startX; + this.source = source; + this.configuration = configuration; + this.modifiers = modifiers; + this.processor = processor; + } + + /// + [MethodImpl(InliningOptions.ShortMethod)] + public void Invoke(in RowInterval rows, Memory memory) + { + 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); + + // Run the user defined pixel shader to the current row of pixels + this.processor.ApplyPixelRowDelegate(vectorSpan, new Point(this.startX, y)); + + PixelOperations.Instance.FromVector4Destructive(this.configuration, vectorSpan, rowSpan, this.modifiers); + } + } + } } }