diff --git a/src/ImageSharp/Processing/Processors/Filters/FilterProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Filters/FilterProcessor{TPixel}.cs index a8ce67af3b..cdb67e48b2 100644 --- a/src/ImageSharp/Processing/Processors/Filters/FilterProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Filters/FilterProcessor{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.Filters @@ -34,27 +36,52 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters protected override void OnFrameApply(ImageFrame source) { var interest = Rectangle.Intersect(this.SourceRectangle, source.Bounds()); - int startX = interest.X; - ColorMatrix matrix = this.definition.Matrix; - - 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(this.Configuration, rowSpan, vectorSpan); - - Vector4Utils.Transform(vectorSpan, ref matrix); - - PixelOperations.Instance.FromVector4Destructive(this.Configuration, vectorSpan, rowSpan); - } - }); + new RowIntervalAction(interest.X, source, this.definition.Matrix, this.Configuration)); + } + + /// + /// A implementing the convolution logic for . + /// + private readonly struct RowIntervalAction : IRowIntervalAction + { + private readonly int startX; + private readonly ImageFrame source; + private readonly ColorMatrix matrix; + private readonly Configuration configuration; + + [MethodImpl(InliningOptions.ShortMethod)] + public RowIntervalAction( + int startX, + ImageFrame source, + ColorMatrix matrix, + Configuration configuration) + { + this.startX = startX; + this.source = source; + this.matrix = matrix; + this.configuration = configuration; + } + + /// + [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); + + Vector4Utils.Transform(vectorSpan, ref Unsafe.AsRef(this.matrix)); + + PixelOperations.Instance.FromVector4Destructive(this.configuration, vectorSpan, rowSpan); + } + } } } }