diff --git a/src/ImageSharp/Processing/Processors/PixelShading/Abstract/PixelShaderProcessorBase.cs b/src/ImageSharp/Processing/Processors/PixelShading/Abstract/PixelShaderProcessorBase.cs
new file mode 100644
index 0000000000..4d2cb233b0
--- /dev/null
+++ b/src/ImageSharp/Processing/Processors/PixelShading/Abstract/PixelShaderProcessorBase.cs
@@ -0,0 +1,64 @@
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+using System;
+using System.Numerics;
+
+using SixLabors.ImageSharp.Advanced;
+using SixLabors.ImageSharp.Advanced.ParallelUtils;
+using SixLabors.ImageSharp.PixelFormats;
+using SixLabors.Primitives;
+
+namespace SixLabors.ImageSharp.Processing.Processors.PixelShading.Abstract
+{
+ ///
+ /// Applies a user defined pixel shader effect through a given delegate.
+ ///
+ /// The pixel format.
+ internal abstract class PixelShaderProcessorBase : ImageProcessor
+ where TPixel : struct, IPixel
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The source for the current processor instance.
+ /// The source area to process for the current processor instance.
+ protected PixelShaderProcessorBase(Image source, Rectangle sourceRectangle)
+ : base(source, sourceRectangle)
+ { }
+
+ ///
+ protected override void OnFrameApply(ImageFrame source)
+ {
+ var interest = Rectangle.Intersect(this.SourceRectangle, source.Bounds());
+ int startX = interest.X;
+
+ ParallelHelper.IterateRowsWithTempBuffer(
+ 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);
+
+ // Run the user defined pixel shader on the current row of pixels
+ this.ApplyPixelShader(vectorSpan, y, startX);
+
+ PixelOperations.Instance.FromVector4Destructive(this.Configuration, vectorSpan, rowSpan);
+ }
+ });
+ }
+
+ ///
+ /// Applies the current pixel shader effect on a target row of preprocessed pixels.
+ ///
+ /// The target row of pixels to process.
+ /// The initial vertical offset for the input pixels to process.
+ /// The initial horizontal offset for the input pixels to process.
+ protected abstract void ApplyPixelShader(Span span, int offsetY, int offsetX);
+ }
+}
diff --git a/src/ImageSharp/Processing/Processors/PixelShading/PixelShaderProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/PixelShading/PixelShaderProcessor{TPixel}.cs
index b856355aed..70728a4ecb 100644
--- a/src/ImageSharp/Processing/Processors/PixelShading/PixelShaderProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/PixelShading/PixelShaderProcessor{TPixel}.cs
@@ -4,10 +4,9 @@
using System;
using System.Numerics;
-using SixLabors.ImageSharp.Advanced;
-using SixLabors.ImageSharp.Advanced.ParallelUtils;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing.Delegates;
+using SixLabors.ImageSharp.Processing.Processors.PixelShading.Abstract;
using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Processing.Processors.PixelShading
@@ -16,7 +15,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.PixelShading
/// Applies a user defined pixel shader effect through a given delegate.
///
/// The pixel format.
- internal class PixelShaderProcessor : ImageProcessor
+ internal class PixelShaderProcessor : PixelShaderProcessorBase
where TPixel : struct, IPixel
{
///
@@ -37,30 +36,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.PixelShading
}
///
- protected override void OnFrameApply(ImageFrame source)
- {
- var interest = Rectangle.Intersect(this.SourceRectangle, source.Bounds());
- int startX = interest.X;
- PixelShader pixelShader = this.pixelShader;
-
- ParallelHelper.IterateRowsWithTempBuffer(
- 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);
-
- // Run the user defined pixel shader on the current row of pixels
- pixelShader(vectorSpan);
-
- PixelOperations.Instance.FromVector4Destructive(this.Configuration, vectorSpan, rowSpan);
- }
- });
- }
+ protected override void ApplyPixelShader(Span span, int offsetY, int offsetX) => this.pixelShader(span);
}
}
diff --git a/src/ImageSharp/Processing/Processors/PixelShading/PositionAwarePixelShaderProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/PixelShading/PositionAwarePixelShaderProcessor{TPixel}.cs
index 55ad325ad7..7c5eff5979 100644
--- a/src/ImageSharp/Processing/Processors/PixelShading/PositionAwarePixelShaderProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/PixelShading/PositionAwarePixelShaderProcessor{TPixel}.cs
@@ -4,10 +4,9 @@
using System;
using System.Numerics;
-using SixLabors.ImageSharp.Advanced;
-using SixLabors.ImageSharp.Advanced.ParallelUtils;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing.Delegates;
+using SixLabors.ImageSharp.Processing.Processors.PixelShading.Abstract;
using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Processing.Processors.PixelShading
@@ -16,7 +15,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.PixelShading
/// Applies a user defined pixel shader effect through a given delegate.
///
/// The pixel format.
- internal class PositionAwarePixelShaderProcessor : ImageProcessor
+ internal class PositionAwarePixelShaderProcessor : PixelShaderProcessorBase
where TPixel : struct, IPixel
{
///
@@ -37,29 +36,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.PixelShading
}
///
- protected override void OnFrameApply(ImageFrame source)
- {
- var interest = Rectangle.Intersect(this.SourceRectangle, source.Bounds());
- int startX = interest.X;
- PositionAwarePixelShader pixelShader = this.pixelShader;
-
- ParallelHelper.IterateRowsWithTempBuffer(
- 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);
-
- pixelShader(vectorSpan, y, startX);
-
- PixelOperations.Instance.FromVector4Destructive(this.Configuration, vectorSpan, rowSpan);
- }
- });
- }
+ protected override void ApplyPixelShader(Span span, int offsetY, int offsetX) => this.pixelShader(span, offsetY, offsetX);
}
}