diff --git a/src/ImageSharp/Advanced/IRowIntervalOperation.cs b/src/ImageSharp/Advanced/IRowIntervalOperation.cs
index 9aa79e730..3e1b08621 100644
--- a/src/ImageSharp/Advanced/IRowIntervalOperation.cs
+++ b/src/ImageSharp/Advanced/IRowIntervalOperation.cs
@@ -18,85 +18,4 @@ namespace SixLabors.ImageSharp.Advanced
/// The row interval.
void Invoke(in RowInterval rows);
}
-
- internal readonly struct WrappingRowIntervalInfo
- {
- public readonly int MinY;
- public readonly int MaxY;
- public readonly int StepY;
- public readonly int MaxX;
-
- public WrappingRowIntervalInfo(int minY, int maxY, int stepY)
- : this(minY, maxY, stepY, 0)
- {
- }
-
- public WrappingRowIntervalInfo(int minY, int maxY, int stepY, int maxX)
- {
- this.MinY = minY;
- this.MaxY = maxY;
- this.StepY = stepY;
- this.MaxX = maxX;
- }
- }
-
- internal readonly struct WrappingRowIntervalOperation
- {
- private readonly WrappingRowIntervalInfo info;
- private readonly Action action;
-
- [MethodImpl(InliningOptions.ShortMethod)]
- public WrappingRowIntervalOperation(in WrappingRowIntervalInfo info, Action action)
- {
- this.info = info;
- this.action = action;
- }
-
- [MethodImpl(InliningOptions.ShortMethod)]
- public void Invoke(int i)
- {
- int yMin = this.info.MinY + (i * this.info.StepY);
-
- if (yMin >= this.info.MaxY)
- {
- return;
- }
-
- int yMax = Math.Min(yMin + this.info.StepY, this.info.MaxY);
- var rows = new RowInterval(yMin, yMax);
-
- this.action(rows);
- }
- }
-
- internal readonly struct WrappingRowIntervalOperation
- where T : struct, IRowIntervalOperation
- {
- private readonly WrappingRowIntervalInfo info;
- private readonly T operation;
-
- [MethodImpl(InliningOptions.ShortMethod)]
- public WrappingRowIntervalOperation(in WrappingRowIntervalInfo info, in T operation)
- {
- this.info = info;
- this.operation = operation;
- }
-
- [MethodImpl(InliningOptions.ShortMethod)]
- public void Invoke(int i)
- {
- int yMin = this.info.MinY + (i * this.info.StepY);
-
- if (yMin >= this.info.MaxY)
- {
- return;
- }
-
- int yMax = Math.Min(yMin + this.info.StepY, this.info.MaxY);
- var rows = new RowInterval(yMin, yMax);
-
- // Skip the safety copy when invoking a potentially impure method on a readonly field
- Unsafe.AsRef(this.operation).Invoke(in rows);
- }
- }
}
diff --git a/src/ImageSharp/Advanced/IRowIntervalOperation{TBuffer}.cs b/src/ImageSharp/Advanced/IRowIntervalOperation{TBuffer}.cs
index 18ebc9fb9..c18842a92 100644
--- a/src/ImageSharp/Advanced/IRowIntervalOperation{TBuffer}.cs
+++ b/src/ImageSharp/Advanced/IRowIntervalOperation{TBuffer}.cs
@@ -19,81 +19,7 @@ namespace SixLabors.ImageSharp.Advanced
/// Invokes the method passing the row interval and a buffer.
///
/// The row interval.
- /// The contiguous region of memory.
- void Invoke(in RowInterval rows, Memory memory);
- }
-
- internal readonly struct WrappingRowIntervalBufferOperation
- where TBuffer : unmanaged
- {
- private readonly WrappingRowIntervalInfo info;
- private readonly MemoryAllocator allocator;
- private readonly Action> action;
-
- [MethodImpl(InliningOptions.ShortMethod)]
- public WrappingRowIntervalBufferOperation(
- in WrappingRowIntervalInfo info,
- MemoryAllocator allocator,
- Action> action)
- {
- this.info = info;
- this.allocator = allocator;
- this.action = action;
- }
-
- [MethodImpl(InliningOptions.ShortMethod)]
- public void Invoke(int i)
- {
- int yMin = this.info.MinY + (i * this.info.StepY);
-
- if (yMin >= this.info.MaxY)
- {
- return;
- }
-
- int yMax = Math.Min(yMin + this.info.StepY, this.info.MaxY);
- var rows = new RowInterval(yMin, yMax);
-
- using IMemoryOwner buffer = this.allocator.Allocate(this.info.MaxX);
- this.action(rows, buffer.Memory);
- }
- }
-
- internal readonly struct WrappingRowIntervalBufferOperation
- where T : struct, IRowIntervalOperation
- where TBuffer : unmanaged
- {
- private readonly WrappingRowIntervalInfo info;
- private readonly MemoryAllocator allocator;
- private readonly T operation;
-
- [MethodImpl(InliningOptions.ShortMethod)]
- public WrappingRowIntervalBufferOperation(
- in WrappingRowIntervalInfo info,
- MemoryAllocator allocator,
- in T operation)
- {
- this.info = info;
- this.allocator = allocator;
- this.operation = operation;
- }
-
- [MethodImpl(InliningOptions.ShortMethod)]
- public void Invoke(int i)
- {
- int yMin = this.info.MinY + (i * this.info.StepY);
-
- if (yMin >= this.info.MaxY)
- {
- return;
- }
-
- int yMax = Math.Min(yMin + this.info.StepY, this.info.MaxY);
- var rows = new RowInterval(yMin, yMax);
-
- using IMemoryOwner buffer = this.allocator.Allocate(this.info.MaxX);
-
- Unsafe.AsRef(this.operation).Invoke(in rows, buffer.Memory);
- }
+ /// The contiguous region of memory.
+ void Invoke(in RowInterval rows, Span span);
}
}
diff --git a/src/ImageSharp/Advanced/ParallelRowIterator.Wrappers.cs b/src/ImageSharp/Advanced/ParallelRowIterator.Wrappers.cs
new file mode 100644
index 000000000..4abcd1a3e
--- /dev/null
+++ b/src/ImageSharp/Advanced/ParallelRowIterator.Wrappers.cs
@@ -0,0 +1,110 @@
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+using System;
+using System.Buffers;
+using System.Runtime.CompilerServices;
+using System.Threading.Tasks;
+using SixLabors.ImageSharp.Memory;
+
+namespace SixLabors.ImageSharp.Advanced
+{
+ ///
+ /// Utility methods for batched processing of pixel row intervals.
+ /// Parallel execution is optimized for image processing based on values defined
+ /// or .
+ /// Using this class is preferred over direct usage of utility methods.
+ ///
+ public static partial class ParallelRowIterator
+ {
+ private readonly struct WrappingRowIntervalInfo
+ {
+ public readonly int MinY;
+ public readonly int MaxY;
+ public readonly int StepY;
+ public readonly int MaxX;
+
+ public WrappingRowIntervalInfo(int minY, int maxY, int stepY)
+ : this(minY, maxY, stepY, 0)
+ {
+ }
+
+ public WrappingRowIntervalInfo(int minY, int maxY, int stepY, int maxX)
+ {
+ this.MinY = minY;
+ this.MaxY = maxY;
+ this.StepY = stepY;
+ this.MaxX = maxX;
+ }
+ }
+
+ private readonly struct WrappingRowIntervalOperation
+ where T : struct, IRowIntervalOperation
+ {
+ private readonly WrappingRowIntervalInfo info;
+ private readonly T operation;
+
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public WrappingRowIntervalOperation(in WrappingRowIntervalInfo info, in T operation)
+ {
+ this.info = info;
+ this.operation = operation;
+ }
+
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void Invoke(int i)
+ {
+ int yMin = this.info.MinY + (i * this.info.StepY);
+
+ if (yMin >= this.info.MaxY)
+ {
+ return;
+ }
+
+ int yMax = Math.Min(yMin + this.info.StepY, this.info.MaxY);
+ var rows = new RowInterval(yMin, yMax);
+
+ // Skip the safety copy when invoking a potentially impure method on a readonly field
+ Unsafe.AsRef(this.operation).Invoke(in rows);
+ }
+ }
+
+ private readonly struct WrappingRowIntervalBufferOperation
+ where T : struct, IRowIntervalOperation
+ where TBuffer : unmanaged
+ {
+ private readonly WrappingRowIntervalInfo info;
+ private readonly MemoryAllocator allocator;
+ private readonly T operation;
+
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public WrappingRowIntervalBufferOperation(
+ in WrappingRowIntervalInfo info,
+ MemoryAllocator allocator,
+ in T operation)
+ {
+ this.info = info;
+ this.allocator = allocator;
+ this.operation = operation;
+ }
+
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void Invoke(int i)
+ {
+ int yMin = this.info.MinY + (i * this.info.StepY);
+
+ if (yMin >= this.info.MaxY)
+ {
+ return;
+ }
+
+ int yMax = Math.Min(yMin + this.info.StepY, this.info.MaxY);
+ var rows = new RowInterval(yMin, yMax);
+
+ using IMemoryOwner buffer = this.allocator.Allocate(this.info.MaxX);
+
+ Unsafe.AsRef(this.operation).Invoke(in rows, buffer.Memory.Span);
+ }
+ }
+ }
+}
diff --git a/src/ImageSharp/Advanced/ParallelRowIterator.cs b/src/ImageSharp/Advanced/ParallelRowIterator.cs
index d7939478b..e9d522966 100644
--- a/src/ImageSharp/Advanced/ParallelRowIterator.cs
+++ b/src/ImageSharp/Advanced/ParallelRowIterator.cs
@@ -15,7 +15,7 @@ namespace SixLabors.ImageSharp.Advanced
/// or .
/// Using this class is preferred over direct usage of utility methods.
///
- public static class ParallelRowIterator
+ public static partial class ParallelRowIterator
{
///
/// Iterate through the rows of a rectangle in optimized batches defined by -s.
@@ -125,7 +125,7 @@ namespace SixLabors.ImageSharp.Advanced
var rows = new RowInterval(top, bottom);
using (IMemoryOwner buffer = allocator.Allocate(width))
{
- Unsafe.AsRef(operation).Invoke(rows, buffer.Memory);
+ Unsafe.AsRef(operation).Invoke(rows, buffer.Memory.Span);
}
return;
diff --git a/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor{TPixel}.cs
index 16acc2407..e388fdaad 100644
--- a/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor{TPixel}.cs
@@ -448,16 +448,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
///
[MethodImpl(InliningOptions.ShortMethod)]
- public void Invoke(in RowInterval rows, Memory memory)
+ public void Invoke(in RowInterval rows, Span span)
{
- Span vectorSpan = memory.Span;
- int length = vectorSpan.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);
+ PixelOperations.Instance.ToVector4(this.configuration, targetRowSpan.Slice(0, span.Length), span, PixelConversionModifiers.Premultiply);
+ ref Vector4 baseRef = ref MemoryMarshal.GetReference(span);
for (int x = 0; x < this.bounds.Width; x++)
{
@@ -467,7 +464,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
v.Z = MathF.Pow(v.Z, this.gamma);
}
- PixelOperations.Instance.FromVector4Destructive(this.configuration, vectorSpan.Slice(0, length), targetRowSpan);
+ PixelOperations.Instance.FromVector4Destructive(this.configuration, span, targetRowSpan);
}
}
}
diff --git a/src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor{TPixel}.cs
index d8179c6d5..1c4987c79 100644
--- a/src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor{TPixel}.cs
@@ -113,16 +113,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
///
[MethodImpl(InliningOptions.ShortMethod)]
- public void Invoke(in RowInterval rows, Memory memory)
+ public void Invoke(in RowInterval rows, Span span)
{
- Span vectorSpan = memory.Span;
- int length = vectorSpan.Length;
- ref Vector4 vectorSpanRef = ref MemoryMarshal.GetReference(vectorSpan);
+ ref Vector4 spanRef = 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);
+ PixelOperations.Instance.ToVector4(this.configuration, targetRowSpan.Slice(0, span.Length), span);
if (this.preserveAlpha)
{
@@ -132,7 +130,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
in this.kernelY,
in this.kernelX,
this.sourcePixels,
- ref vectorSpanRef,
+ ref spanRef,
y,
x,
this.bounds.Y,
@@ -149,7 +147,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
in this.kernelY,
in this.kernelX,
this.sourcePixels,
- ref vectorSpanRef,
+ ref spanRef,
y,
x,
this.bounds.Y,
@@ -159,7 +157,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
}
}
- 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 fb477e2d6..33a8ab7d1 100644
--- a/src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor{TPixel}.cs
@@ -109,11 +109,9 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
///
[MethodImpl(InliningOptions.ShortMethod)]
- public void Invoke(in RowInterval rows, Memory memory)
+ public void Invoke(in RowInterval rows, Span span)
{
- Span vectorSpan = memory.Span;
- int length = vectorSpan.Length;
- ref Vector4 vectorSpanRef = ref MemoryMarshal.GetReference(vectorSpan);
+ ref Vector4 spanRef = ref MemoryMarshal.GetReference(span);
int maxY = this.bounds.Bottom - 1;
int maxX = this.bounds.Right - 1;
@@ -121,7 +119,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
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);
+ PixelOperations.Instance.ToVector4(this.configuration, targetRowSpan.Slice(0, span.Length), span);
if (this.preserveAlpha)
{
@@ -130,7 +128,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
DenseMatrixUtils.Convolve3(
in this.kernel,
this.sourcePixels,
- ref vectorSpanRef,
+ ref spanRef,
y,
x,
this.bounds.Y,
@@ -146,7 +144,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
DenseMatrixUtils.Convolve4(
in this.kernel,
this.sourcePixels,
- ref vectorSpanRef,
+ ref spanRef,
y,
x,
this.bounds.Y,
@@ -156,7 +154,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
}
}
- 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 feb27ac62..542ee389b 100644
--- a/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor{TPixel}.cs
@@ -100,16 +100,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
///
[MethodImpl(InliningOptions.ShortMethod)]
- public void Invoke(in RowInterval rows, Memory memory)
+ public void Invoke(in RowInterval rows, Span span)
{
- Span vectorSpan = memory.Span;
- int length = vectorSpan.Length;
- ref Vector4 vectorSpanRef = ref MemoryMarshal.GetReference(vectorSpan);
+ ref Vector4 spanRef = 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);
+ PixelOperations.Instance.ToVector4(this.configuration, targetRowSpan.Slice(0, span.Length), span);
if (this.preserveAlpha)
{
@@ -118,7 +116,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
DenseMatrixUtils.Convolve3(
in this.kernel,
this.sourcePixels,
- ref vectorSpanRef,
+ ref spanRef,
y,
x,
this.bounds.Y,
@@ -134,7 +132,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
DenseMatrixUtils.Convolve4(
in this.kernel,
this.sourcePixels,
- ref vectorSpanRef,
+ ref spanRef,
y,
x,
this.bounds.Y,
@@ -144,7 +142,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
}
}
- 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 a22af8ce2..44ade727a 100644
--- a/src/ImageSharp/Processing/Processors/Effects/PixelRowDelegateProcessor{TPixel,TDelegate}.cs
+++ b/src/ImageSharp/Processing/Processors/Effects/PixelRowDelegateProcessor{TPixel,TDelegate}.cs
@@ -86,19 +86,17 @@ namespace SixLabors.ImageSharp.Processing.Processors.Effects
///
[MethodImpl(InliningOptions.ShortMethod)]
- public void Invoke(in RowInterval rows, Memory memory)
+ public void Invoke(in RowInterval rows, 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);
+ Span rowSpan = this.source.GetPixelRowSpan(y).Slice(this.startX, span.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));
+ 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 cae8b14b8..19142ceb0 100644
--- a/src/ImageSharp/Processing/Processors/Filters/FilterProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Filters/FilterProcessor{TPixel}.cs
@@ -69,18 +69,16 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters
///
[MethodImpl(InliningOptions.ShortMethod)]
- public void Invoke(in RowInterval rows, Memory memory)
+ public void Invoke(in RowInterval rows, 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);
+ Span rowSpan = this.source.GetPixelRowSpan(y).Slice(this.startX, span.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 83d9bd1ef..21a4e1345 100644
--- a/src/ImageSharp/Processing/Processors/Overlays/GlowProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Overlays/GlowProcessor{TPixel}.cs
@@ -95,9 +95,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays
}
[MethodImpl(InliningOptions.ShortMethod)]
- public void Invoke(in RowInterval rows, Memory memory)
+ public void Invoke(in RowInterval rows, Span span)
{
- Span amountsSpan = memory.Span;
Span colorSpan = this.colors.GetSpan();
for (int y = rows.Min; y < rows.Max; y++)
@@ -105,7 +104,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays
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);
+ 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);
@@ -115,7 +114,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays
destination,
destination,
colorSpan,
- amountsSpan);
+ span);
}
}
}
diff --git a/src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor{TPixel}.cs
index b36e6b534..3515a2891 100644
--- a/src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor{TPixel}.cs
@@ -103,9 +103,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays
}
[MethodImpl(InliningOptions.ShortMethod)]
- public void Invoke(in RowInterval rows, Memory memory)
+ public void Invoke(in RowInterval rows, Span span)
{
- Span amountsSpan = memory.Span;
Span colorSpan = this.colors.GetSpan();
for (int y = rows.Min; y < rows.Max; y++)
@@ -113,7 +112,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays
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[i] = (this.blendPercent * (.9F * (distance / this.maxDistance))).Clamp(0, 1);
}
Span destination = this.source.GetPixelRowSpan(y).Slice(this.bounds.X, this.bounds.Width);
@@ -123,7 +122,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays
destination,
destination,
colorSpan,
- amountsSpan);
+ span);
}
}
}
diff --git a/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor{TPixel}.cs
index 2b579541c..0d9055f34 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor{TPixel}.cs
@@ -154,13 +154,12 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
///
[MethodImpl(InliningOptions.ShortMethod)]
- public void Invoke(in RowInterval rows, Memory memory)
+ public void Invoke(in RowInterval rows, 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);
+ PixelOperations.Instance.ToVector4(this.configuration, targetRowSpan, span);
ref float ySpanRef = ref this.kernelMap.GetYStartReference(y);
ref float xSpanRef = ref this.kernelMap.GetXStartReference(y);
@@ -175,12 +174,12 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
ref ySpanRef,
ref xSpanRef,
this.source.PixelBuffer,
- vectorSpan);
+ span);
}
PixelOperations.Instance.FromVector4Destructive(
this.configuration,
- vectorSpan,
+ span,
targetRowSpan);
}
}
diff --git a/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor{TPixel}.cs
index 3969a8c3e..83bc540eb 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor{TPixel}.cs
@@ -150,13 +150,12 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
}
[MethodImpl(InliningOptions.ShortMethod)]
- public void Invoke(in RowInterval rows, Memory memory)
+ public void Invoke(in RowInterval rows, 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);
+ PixelOperations.Instance.ToVector4(this.configuration, targetRowSpan, span);
ref float ySpanRef = ref this.kernelMap.GetYStartReference(y);
ref float xSpanRef = ref this.kernelMap.GetXStartReference(y);
@@ -171,12 +170,12 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
ref ySpanRef,
ref xSpanRef,
this.source.PixelBuffer,
- vectorSpan);
+ span);
}
PixelOperations.Instance.FromVector4Destructive(
this.configuration,
- vectorSpan,
+ span,
targetRowSpan);
}
}
diff --git a/tests/ImageSharp.Tests/Helpers/ParallelRowIteratorTests.cs b/tests/ImageSharp.Tests/Helpers/ParallelRowIteratorTests.cs
index 80ac384fd..3f5e9040d 100644
--- a/tests/ImageSharp.Tests/Helpers/ParallelRowIteratorTests.cs
+++ b/tests/ImageSharp.Tests/Helpers/ParallelRowIteratorTests.cs
@@ -2,7 +2,6 @@
// Licensed under the Apache License, Version 2.0.
using System;
-using System.Collections.Concurrent;
using System.Linq;
using System.Numerics;
using System.Threading;
@@ -17,6 +16,8 @@ namespace SixLabors.ImageSharp.Tests.Helpers
{
public class ParallelRowIteratorTests
{
+ public delegate void RowIntervalAction(RowInterval rows, Span span);
+
private readonly ITestOutputHelper output;
public ParallelRowIteratorTests(ITestOutputHelper output)
@@ -140,17 +141,13 @@ namespace SixLabors.ImageSharp.Tests.Helpers
var rectangle = new Rectangle(0, minY, 10, maxY - minY);
- var bufferHashes = new ConcurrentBag();
-
int actualNumberOfSteps = 0;
- void RowAction(RowInterval rows, Memory buffer)
+ void RowAction(RowInterval rows, Span buffer)
{
Assert.True(rows.Min >= minY);
Assert.True(rows.Max <= maxY);
- bufferHashes.Add(buffer.GetHashCode());
-
int step = rows.Max - rows.Min;
int expected = rows.Max < maxY ? expectedStepLength : expectedLastStepLength;
@@ -166,9 +163,6 @@ namespace SixLabors.ImageSharp.Tests.Helpers
in operation);
Assert.Equal(expectedNumberOfSteps, actualNumberOfSteps);
-
- int numberOfDifferentBuffers = bufferHashes.Distinct().Count();
- Assert.Equal(actualNumberOfSteps, numberOfDifferentBuffers);
}
[Theory]
@@ -191,7 +185,7 @@ namespace SixLabors.ImageSharp.Tests.Helpers
int[] expectedData = Enumerable.Repeat(0, minY).Concat(Enumerable.Range(minY, maxY - minY)).ToArray();
var actualData = new int[maxY];
- void RowAction(RowInterval rows, Memory buffer)
+ void RowAction(RowInterval rows, Span buffer)
{
for (int y = rows.Min; y < rows.Max; y++)
{
@@ -283,7 +277,7 @@ namespace SixLabors.ImageSharp.Tests.Helpers
int actualNumberOfSteps = 0;
- void RowAction(RowInterval rows, Memory buffer)
+ void RowAction(RowInterval rows, Span buffer)
{
Assert.True(rows.Min >= 0);
Assert.True(rows.Max <= height);
@@ -405,7 +399,7 @@ namespace SixLabors.ImageSharp.Tests.Helpers
var rect = new Rectangle(0, 0, width, height);
- void RowAction(RowInterval rows, Memory memory)
+ void RowAction(RowInterval rows, Span memory)
{
}
@@ -430,13 +424,13 @@ namespace SixLabors.ImageSharp.Tests.Helpers
private readonly struct TestRowIntervalOperation : IRowIntervalOperation
where TBuffer : unmanaged
{
- private readonly Action> action;
+ private readonly RowIntervalAction action;
- public TestRowIntervalOperation(Action> action)
+ public TestRowIntervalOperation(RowIntervalAction action)
=> this.action = action;
- public void Invoke(in RowInterval rows, Memory memory)
- => this.action(rows, memory);
+ public void Invoke(in RowInterval rows, Span span)
+ => this.action(rows, span);
}
}
}
diff --git a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs
index d570b4d05..2ef62ed1c 100644
--- a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs
+++ b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs
@@ -724,20 +724,19 @@ namespace SixLabors.ImageSharp.Tests
this.source = source;
}
- public void Invoke(in RowInterval rows, Memory memory)
+ public void Invoke(in RowInterval rows, Span span)
{
- Span tempSpan = memory.Span;
for (int y = rows.Min; y < rows.Max; y++)
{
Span rowSpan = this.source.GetPixelRowSpan(y).Slice(this.bounds.Left, this.bounds.Width);
- PixelOperations.Instance.ToVector4(this.configuration, rowSpan, tempSpan, PixelConversionModifiers.Scale);
- for (int i = 0; i < tempSpan.Length; i++)
+ PixelOperations.Instance.ToVector4(this.configuration, rowSpan, span, PixelConversionModifiers.Scale);
+ for (int i = 0; i < span.Length; i++)
{
- ref Vector4 v = ref tempSpan[i];
+ ref Vector4 v = ref span[i];
v.W = 1F;
}
- PixelOperations.Instance.FromVector4Destructive(this.configuration, tempSpan, rowSpan, PixelConversionModifiers.Scale);
+ PixelOperations.Instance.FromVector4Destructive(this.configuration, span, rowSpan, PixelConversionModifiers.Scale);
}
}
}