diff --git a/src/ImageSharp/Advanced/IRowIntervalOperation.cs b/src/ImageSharp/Advanced/IRowIntervalOperation.cs
index 3e1b086218..980ed91a78 100644
--- a/src/ImageSharp/Advanced/IRowIntervalOperation.cs
+++ b/src/ImageSharp/Advanced/IRowIntervalOperation.cs
@@ -1,8 +1,6 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
-using System;
-using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Memory;
namespace SixLabors.ImageSharp.Advanced
diff --git a/src/ImageSharp/Advanced/IRowIntervalOperation{TBuffer}.cs b/src/ImageSharp/Advanced/IRowIntervalOperation{TBuffer}.cs
index c18842a92c..47fcf253eb 100644
--- a/src/ImageSharp/Advanced/IRowIntervalOperation{TBuffer}.cs
+++ b/src/ImageSharp/Advanced/IRowIntervalOperation{TBuffer}.cs
@@ -2,8 +2,6 @@
// Licensed under the Apache License, Version 2.0.
using System;
-using System.Buffers;
-using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Memory;
namespace SixLabors.ImageSharp.Advanced
diff --git a/src/ImageSharp/Advanced/IRowOperation.cs b/src/ImageSharp/Advanced/IRowOperation.cs
new file mode 100644
index 0000000000..0a6065e4b1
--- /dev/null
+++ b/src/ImageSharp/Advanced/IRowOperation.cs
@@ -0,0 +1,17 @@
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+namespace SixLabors.ImageSharp.Advanced
+{
+ ///
+ /// Defines the contract for an action that operates on a row.
+ ///
+ public interface IRowOperation
+ {
+ ///
+ /// Invokes the method passing the row y coordinate.
+ ///
+ /// The row y coordinate.
+ void Invoke(int y);
+ }
+}
diff --git a/src/ImageSharp/Advanced/IRowOperation{TBuffer}.cs b/src/ImageSharp/Advanced/IRowOperation{TBuffer}.cs
new file mode 100644
index 0000000000..7a13930fad
--- /dev/null
+++ b/src/ImageSharp/Advanced/IRowOperation{TBuffer}.cs
@@ -0,0 +1,22 @@
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+using System;
+
+namespace SixLabors.ImageSharp.Advanced
+{
+ ///
+ /// Defines the contract for an action that operates on a row with a temporary buffer.
+ ///
+ /// The type of buffer elements.
+ public interface IRowOperation
+ where TBuffer : unmanaged
+ {
+ ///
+ /// Invokes the method passing the row and a buffer.
+ ///
+ /// The row y coordinate.
+ /// The contiguous region of memory.
+ void Invoke(int y, Span span);
+ }
+}
diff --git a/src/ImageSharp/Advanced/ParallelRowIterator.Wrappers.cs b/src/ImageSharp/Advanced/ParallelRowIterator.Wrappers.cs
index adbad0d662..3f0f77ca39 100644
--- a/src/ImageSharp/Advanced/ParallelRowIterator.Wrappers.cs
+++ b/src/ImageSharp/Advanced/ParallelRowIterator.Wrappers.cs
@@ -17,51 +17,130 @@ namespace SixLabors.ImageSharp.Advanced
///
public static partial class ParallelRowIterator
{
- private readonly struct IterationParameters
+ private readonly struct RowOperationWrapper
+ where T : struct, IRowOperation
{
- public readonly int MinY;
- public readonly int MaxY;
- public readonly int StepY;
- public readonly int Width;
+ private readonly int minY;
+ private readonly int maxY;
+ private readonly int stepY;
+ private readonly T action;
- public IterationParameters(int minY, int maxY, int stepY)
- : this(minY, maxY, stepY, 0)
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public RowOperationWrapper(
+ int minY,
+ int maxY,
+ int stepY,
+ in T action)
{
+ this.minY = minY;
+ this.maxY = maxY;
+ this.stepY = stepY;
+ this.action = action;
}
- public IterationParameters(int minY, int maxY, int stepY, int width)
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void Invoke(int i)
{
- this.MinY = minY;
- this.MaxY = maxY;
- this.StepY = stepY;
- this.Width = width;
+ int yMin = this.minY + (i * this.stepY);
+
+ if (yMin >= this.maxY)
+ {
+ return;
+ }
+
+ int yMax = Math.Min(yMin + this.stepY, this.maxY);
+
+ for (int y = yMin; y < yMax; y++)
+ {
+ // Skip the safety copy when invoking a potentially impure method on a readonly field
+ Unsafe.AsRef(this.action).Invoke(y);
+ }
+ }
+ }
+
+ private readonly struct RowOperationWrapper
+ where T : struct, IRowOperation
+ where TBuffer : unmanaged
+ {
+ private readonly int minY;
+ private readonly int maxY;
+ private readonly int stepY;
+ private readonly int width;
+ private readonly MemoryAllocator allocator;
+ private readonly T action;
+
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public RowOperationWrapper(
+ int minY,
+ int maxY,
+ int stepY,
+ int width,
+ MemoryAllocator allocator,
+ in T action)
+ {
+ this.minY = minY;
+ this.maxY = maxY;
+ this.stepY = stepY;
+ this.width = width;
+ this.allocator = allocator;
+ this.action = action;
+ }
+
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public void Invoke(int i)
+ {
+ int yMin = this.minY + (i * this.stepY);
+
+ if (yMin >= this.maxY)
+ {
+ return;
+ }
+
+ int yMax = Math.Min(yMin + this.stepY, this.maxY);
+
+ using IMemoryOwner buffer = this.allocator.Allocate(this.width);
+
+ Span span = buffer.Memory.Span;
+
+ for (int y = yMin; y < yMax; y++)
+ {
+ Unsafe.AsRef(this.action).Invoke(y, span);
+ }
}
}
private readonly struct RowIntervalOperationWrapper
where T : struct, IRowIntervalOperation
{
- private readonly IterationParameters info;
+ private readonly int minY;
+ private readonly int maxY;
+ private readonly int stepY;
private readonly T operation;
[MethodImpl(InliningOptions.ShortMethod)]
- public RowIntervalOperationWrapper(in IterationParameters info, in T operation)
+ public RowIntervalOperationWrapper(
+ int minY,
+ int maxY,
+ int stepY,
+ in T operation)
{
- this.info = info;
+ this.minY = minY;
+ this.maxY = maxY;
+ this.stepY = stepY;
this.operation = operation;
}
[MethodImpl(InliningOptions.ShortMethod)]
public void Invoke(int i)
{
- int yMin = this.info.MinY + (i * this.info.StepY);
+ int yMin = this.minY + (i * this.stepY);
- if (yMin >= this.info.MaxY)
+ if (yMin >= this.maxY)
{
return;
}
- int yMax = Math.Min(yMin + this.info.StepY, this.info.MaxY);
+ int yMax = Math.Min(yMin + this.stepY, this.maxY);
var rows = new RowInterval(yMin, yMax);
// Skip the safety copy when invoking a potentially impure method on a readonly field
@@ -73,17 +152,26 @@ namespace SixLabors.ImageSharp.Advanced
where T : struct, IRowIntervalOperation
where TBuffer : unmanaged
{
- private readonly IterationParameters info;
+ private readonly int minY;
+ private readonly int maxY;
+ private readonly int stepY;
+ private readonly int width;
private readonly MemoryAllocator allocator;
private readonly T operation;
[MethodImpl(InliningOptions.ShortMethod)]
public RowIntervalOperationWrapper(
- in IterationParameters info,
+ int minY,
+ int maxY,
+ int stepY,
+ int width,
MemoryAllocator allocator,
in T operation)
{
- this.info = info;
+ this.minY = minY;
+ this.maxY = maxY;
+ this.stepY = stepY;
+ this.width = width;
this.allocator = allocator;
this.operation = operation;
}
@@ -91,17 +179,17 @@ namespace SixLabors.ImageSharp.Advanced
[MethodImpl(InliningOptions.ShortMethod)]
public void Invoke(int i)
{
- int yMin = this.info.MinY + (i * this.info.StepY);
+ int yMin = this.minY + (i * this.stepY);
- if (yMin >= this.info.MaxY)
+ if (yMin >= this.maxY)
{
return;
}
- int yMax = Math.Min(yMin + this.info.StepY, this.info.MaxY);
+ int yMax = Math.Min(yMin + this.stepY, this.maxY);
var rows = new RowInterval(yMin, yMax);
- using IMemoryOwner buffer = this.allocator.Allocate(this.info.Width);
+ using IMemoryOwner buffer = this.allocator.Allocate(this.width);
Unsafe.AsRef(in this.operation).Invoke(in rows, buffer.Memory.Span);
}
diff --git a/src/ImageSharp/Advanced/ParallelRowIterator.cs b/src/ImageSharp/Advanced/ParallelRowIterator.cs
index 123784c57f..fb85de9863 100644
--- a/src/ImageSharp/Advanced/ParallelRowIterator.cs
+++ b/src/ImageSharp/Advanced/ParallelRowIterator.cs
@@ -17,6 +17,135 @@ namespace SixLabors.ImageSharp.Advanced
///
public static partial class ParallelRowIterator
{
+ ///
+ /// Iterate through the rows of a rectangle in optimized batches.
+ ///
+ /// The type of row operation to perform.
+ /// The to get the parallel settings from.
+ /// The .
+ /// The operation defining the iteration logic on a single row.
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public static void IterateRows(Configuration configuration, Rectangle rectangle, in T operation)
+ where T : struct, IRowOperation
+ {
+ var parallelSettings = ParallelExecutionSettings.FromConfiguration(configuration);
+ IterateRows(rectangle, in parallelSettings, in operation);
+ }
+
+ ///
+ /// Iterate through the rows of a rectangle in optimized batches.
+ ///
+ /// The type of row operation to perform.
+ /// The .
+ /// The .
+ /// The operation defining the iteration logic on a single row.
+ public static void IterateRows(
+ Rectangle rectangle,
+ in ParallelExecutionSettings parallelSettings,
+ in T operation)
+ where T : struct, IRowOperation
+ {
+ ValidateRectangle(rectangle);
+
+ int top = rectangle.Top;
+ int bottom = rectangle.Bottom;
+ int width = rectangle.Width;
+ int height = rectangle.Height;
+
+ int maxSteps = DivideCeil(width * height, parallelSettings.MinimumPixelsProcessedPerTask);
+ int numOfSteps = Math.Min(parallelSettings.MaxDegreeOfParallelism, maxSteps);
+
+ // Avoid TPL overhead in this trivial case:
+ if (numOfSteps == 1)
+ {
+ for (int y = top; y < bottom; y++)
+ {
+ Unsafe.AsRef(operation).Invoke(y);
+ }
+
+ return;
+ }
+
+ int verticalStep = DivideCeil(rectangle.Height, numOfSteps);
+ var parallelOptions = new ParallelOptions { MaxDegreeOfParallelism = numOfSteps };
+ var wrappingOperation = new RowOperationWrapper(top, bottom, verticalStep, in operation);
+
+ Parallel.For(
+ 0,
+ numOfSteps,
+ parallelOptions,
+ wrappingOperation.Invoke);
+ }
+
+ ///
+ /// Iterate through the rows of a rectangle in optimized batches.
+ /// instantiating a temporary buffer for each invocation.
+ ///
+ /// The type of row operation to perform.
+ /// The type of buffer elements.
+ /// The to get the parallel settings from.
+ /// The .
+ /// The operation defining the iteration logic on a single row.
+ public static void IterateRows(Configuration configuration, Rectangle rectangle, in T operation)
+ where T : struct, IRowOperation
+ where TBuffer : unmanaged
+ {
+ var parallelSettings = ParallelExecutionSettings.FromConfiguration(configuration);
+ IterateRows(rectangle, in parallelSettings, in operation);
+ }
+
+ ///
+ /// Iterate through the rows of a rectangle in optimized batches.
+ /// instantiating a temporary buffer for each invocation.
+ ///
+ /// The type of row operation to perform.
+ /// The type of buffer elements.
+ /// The .
+ /// The .
+ /// The operation defining the iteration logic on a single row.
+ public static void IterateRows(
+ Rectangle rectangle,
+ in ParallelExecutionSettings parallelSettings,
+ in T operation)
+ where T : struct, IRowOperation
+ where TBuffer : unmanaged
+ {
+ ValidateRectangle(rectangle);
+
+ int top = rectangle.Top;
+ int bottom = rectangle.Bottom;
+ int width = rectangle.Width;
+ int height = rectangle.Height;
+
+ int maxSteps = DivideCeil(width * height, parallelSettings.MinimumPixelsProcessedPerTask);
+ int numOfSteps = Math.Min(parallelSettings.MaxDegreeOfParallelism, maxSteps);
+ MemoryAllocator allocator = parallelSettings.MemoryAllocator;
+
+ // Avoid TPL overhead in this trivial case:
+ if (numOfSteps == 1)
+ {
+ using IMemoryOwner buffer = allocator.Allocate(width);
+ Span span = buffer.Memory.Span;
+
+ for (int y = top; y < bottom; y++)
+ {
+ Unsafe.AsRef(operation).Invoke(y, span);
+ }
+
+ return;
+ }
+
+ int verticalStep = DivideCeil(height, numOfSteps);
+ var parallelOptions = new ParallelOptions { MaxDegreeOfParallelism = numOfSteps };
+ var wrappingOperation = new RowOperationWrapper(top, bottom, verticalStep, width, allocator, in operation);
+
+ Parallel.For(
+ 0,
+ numOfSteps,
+ parallelOptions,
+ wrappingOperation.Invoke);
+ }
+
///
/// Iterate through the rows of a rectangle in optimized batches defined by -s.
///
@@ -25,11 +154,11 @@ namespace SixLabors.ImageSharp.Advanced
/// The .
/// The operation defining the iteration logic on a single .
[MethodImpl(InliningOptions.ShortMethod)]
- public static void IterateRows(Configuration configuration, Rectangle rectangle, in T operation)
+ public static void IterateRowIntervals(Configuration configuration, Rectangle rectangle, in T operation)
where T : struct, IRowIntervalOperation
{
var parallelSettings = ParallelExecutionSettings.FromConfiguration(configuration);
- IterateRows(rectangle, in parallelSettings, in operation);
+ IterateRowIntervals(rectangle, in parallelSettings, in operation);
}
///
@@ -39,7 +168,7 @@ namespace SixLabors.ImageSharp.Advanced
/// The .
/// The .
/// The operation defining the iteration logic on a single .
- public static void IterateRows(
+ public static void IterateRowIntervals(
Rectangle rectangle,
in ParallelExecutionSettings parallelSettings,
in T operation)
@@ -65,8 +194,7 @@ namespace SixLabors.ImageSharp.Advanced
int verticalStep = DivideCeil(rectangle.Height, numOfSteps);
var parallelOptions = new ParallelOptions { MaxDegreeOfParallelism = numOfSteps };
- var info = new IterationParameters(top, bottom, verticalStep);
- var wrappingOperation = new RowIntervalOperationWrapper(in info, in operation);
+ var wrappingOperation = new RowIntervalOperationWrapper(top, bottom, verticalStep, in operation);
Parallel.For(
0,
@@ -84,12 +212,12 @@ namespace SixLabors.ImageSharp.Advanced
/// The to get the parallel settings from.
/// The .
/// The operation defining the iteration logic on a single .
- public static void IterateRows(Configuration configuration, Rectangle rectangle, in T operation)
+ public static void IterateRowIntervals(Configuration configuration, Rectangle rectangle, in T operation)
where T : struct, IRowIntervalOperation
where TBuffer : unmanaged
{
var parallelSettings = ParallelExecutionSettings.FromConfiguration(configuration);
- IterateRows(rectangle, in parallelSettings, in operation);
+ IterateRowIntervals(rectangle, in parallelSettings, in operation);
}
///
@@ -101,7 +229,7 @@ namespace SixLabors.ImageSharp.Advanced
/// The .
/// The .
/// The operation defining the iteration logic on a single .
- public static void IterateRows(
+ public static void IterateRowIntervals(
Rectangle rectangle,
in ParallelExecutionSettings parallelSettings,
in T operation)
@@ -123,18 +251,16 @@ namespace SixLabors.ImageSharp.Advanced
if (numOfSteps == 1)
{
var rows = new RowInterval(top, bottom);
- using (IMemoryOwner buffer = allocator.Allocate(width))
- {
- Unsafe.AsRef(operation).Invoke(in rows, buffer.Memory.Span);
- }
+ using IMemoryOwner buffer = allocator.Allocate(width);
+
+ Unsafe.AsRef(operation).Invoke(in rows, buffer.Memory.Span);
return;
}
int verticalStep = DivideCeil(height, numOfSteps);
var parallelOptions = new ParallelOptions { MaxDegreeOfParallelism = numOfSteps };
- var info = new IterationParameters(top, bottom, verticalStep, width);
- var wrappingOperation = new RowIntervalOperationWrapper(in info, allocator, in operation);
+ var wrappingOperation = new RowIntervalOperationWrapper(top, bottom, verticalStep, width, allocator, in operation);
Parallel.For(
0,
diff --git a/src/ImageSharp/ImageFrame{TPixel}.cs b/src/ImageSharp/ImageFrame{TPixel}.cs
index 321f2938c5..a35443ec9d 100644
--- a/src/ImageSharp/ImageFrame{TPixel}.cs
+++ b/src/ImageSharp/ImageFrame{TPixel}.cs
@@ -277,7 +277,7 @@ namespace SixLabors.ImageSharp
var target = new ImageFrame(configuration, this.Width, this.Height, this.Metadata.DeepClone());
var operation = new RowIntervalOperation(this, target, configuration);
- ParallelRowIterator.IterateRows(
+ ParallelRowIterator.IterateRowIntervals(
configuration,
this.Bounds(),
in operation);
diff --git a/src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor{TPixel}.cs
index 18b3471441..0d363689dd 100644
--- a/src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor{TPixel}.cs
@@ -3,8 +3,8 @@
using System;
using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
using SixLabors.ImageSharp.Advanced;
-using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Processing.Processors.Binarization
@@ -44,7 +44,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Binarization
var interest = Rectangle.Intersect(sourceRectangle, source.Bounds());
bool isAlphaOnly = typeof(TPixel) == typeof(A8);
- var operation = new RowIntervalOperation(interest, source, upper, lower, threshold, isAlphaOnly);
+ var operation = new RowOperation(interest, source, upper, lower, threshold, isAlphaOnly);
ParallelRowIterator.IterateRows(
configuration,
interest,
@@ -54,7 +54,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Binarization
///
/// A implementing the clone logic for .
///
- private readonly struct RowIntervalOperation : IRowIntervalOperation
+ private readonly struct RowOperation : IRowOperation
{
private readonly ImageFrame source;
private readonly TPixel upper;
@@ -65,7 +65,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Binarization
private readonly bool isAlphaOnly;
[MethodImpl(InliningOptions.ShortMethod)]
- public RowIntervalOperation(
+ public RowOperation(
Rectangle bounds,
ImageFrame source,
TPixel upper,
@@ -84,22 +84,20 @@ namespace SixLabors.ImageSharp.Processing.Processors.Binarization
///
[MethodImpl(InliningOptions.ShortMethod)]
- public void Invoke(in RowInterval rows)
+ public void Invoke(int y)
{
Rgba32 rgba = default;
- for (int y = rows.Min; y < rows.Max; y++)
- {
- Span row = this.source.GetPixelRowSpan(y);
+ Span row = this.source.GetPixelRowSpan(y);
+ ref TPixel rowRef = ref MemoryMarshal.GetReference(row);
- for (int x = this.minX; x < this.maxX; x++)
- {
- ref TPixel color = ref row[x];
- color.ToRgba32(ref rgba);
+ for (int x = this.minX; x < this.maxX; x++)
+ {
+ ref TPixel color = ref Unsafe.Add(ref rowRef, x);
+ color.ToRgba32(ref rgba);
- // Convert to grayscale using ITU-R Recommendation BT.709 if required
- byte luminance = this.isAlphaOnly ? rgba.A : ImageMaths.Get8BitBT709Luminance(rgba.R, rgba.G, rgba.B);
- color = luminance >= this.threshold ? this.upper : this.lower;
- }
+ // Convert to grayscale using ITU-R Recommendation BT.709 if required
+ byte luminance = this.isAlphaOnly ? rgba.A : ImageMaths.Get8BitBT709Luminance(rgba.R, rgba.G, rgba.B);
+ color = luminance >= this.threshold ? this.upper : this.lower;
}
}
}
diff --git a/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor{TPixel}.cs
index 17f60ebefc..493218cde5 100644
--- a/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor{TPixel}.cs
@@ -72,8 +72,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
protected override void OnFrameApply(ImageFrame source)
{
// Preliminary gamma highlight pass
- var gammaOperation = new ApplyGammaExposureRowIntervalOperation(this.SourceRectangle, source.PixelBuffer, this.Configuration, this.gamma);
- ParallelRowIterator.IterateRows(
+ var gammaOperation = new ApplyGammaExposureRowOperation(this.SourceRectangle, source.PixelBuffer, this.Configuration, this.gamma);
+ ParallelRowIterator.IterateRows(
this.Configuration,
this.SourceRectangle,
in gammaOperation);
@@ -87,7 +87,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
float inverseGamma = 1 / this.gamma;
// Apply the inverse gamma exposure pass, and write the final pixel data
- var operation = new ApplyInverseGammaExposureRowIntervalOperation(this.SourceRectangle, source.PixelBuffer, processingBuffer, this.Configuration, inverseGamma);
+ var operation = new ApplyInverseGammaExposureRowOperation(this.SourceRectangle, source.PixelBuffer, processingBuffer, this.Configuration, inverseGamma);
ParallelRowIterator.IterateRows(
this.Configuration,
this.SourceRectangle,
@@ -120,14 +120,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
Vector4 parameters = Unsafe.Add(ref paramsRef, i);
// Compute the vertical 1D convolution
- var verticalOperation = new ApplyVerticalConvolutionRowIntervalOperation(sourceRectangle, firstPassBuffer, source.PixelBuffer, kernel);
+ var verticalOperation = new ApplyVerticalConvolutionRowOperation(sourceRectangle, firstPassBuffer, source.PixelBuffer, kernel);
ParallelRowIterator.IterateRows(
configuration,
sourceRectangle,
in verticalOperation);
// Compute the horizontal 1D convolutions and accumulate the partial results on the target buffer
- var horizontalOperation = new ApplyHorizontalConvolutionRowIntervalOperation(sourceRectangle, processingBuffer, firstPassBuffer, kernel, parameters.Z, parameters.W);
+ var horizontalOperation = new ApplyHorizontalConvolutionRowOperation(sourceRectangle, processingBuffer, firstPassBuffer, kernel, parameters.Z, parameters.W);
ParallelRowIterator.IterateRows(
configuration,
sourceRectangle,
@@ -138,7 +138,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
///
/// A implementing the vertical convolution logic for .
///
- private readonly struct ApplyVerticalConvolutionRowIntervalOperation : IRowIntervalOperation
+ private readonly struct ApplyVerticalConvolutionRowOperation : IRowOperation
{
private readonly Rectangle bounds;
private readonly Buffer2D targetValues;
@@ -148,7 +148,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
private readonly int maxX;
[MethodImpl(InliningOptions.ShortMethod)]
- public ApplyVerticalConvolutionRowIntervalOperation(
+ public ApplyVerticalConvolutionRowOperation(
Rectangle bounds,
Buffer2D targetValues,
Buffer2D sourcePixels,
@@ -164,16 +164,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
///
[MethodImpl(InliningOptions.ShortMethod)]
- public void Invoke(in RowInterval rows)
+ public void Invoke(int y)
{
- for (int y = rows.Min; y < rows.Max; y++)
- {
- Span targetRowSpan = this.targetValues.GetRowSpan(y).Slice(this.bounds.X);
+ Span targetRowSpan = this.targetValues.GetRowSpan(y).Slice(this.bounds.X);
- for (int x = 0; x < this.bounds.Width; x++)
- {
- Buffer2DUtils.Convolve4(this.kernel, this.sourcePixels, targetRowSpan, y, x, this.bounds.Y, this.maxY, this.bounds.X, this.maxX);
- }
+ for (int x = 0; x < this.bounds.Width; x++)
+ {
+ Buffer2DUtils.Convolve4(this.kernel, this.sourcePixels, targetRowSpan, y, x, this.bounds.Y, this.maxY, this.bounds.X, this.maxX);
}
}
}
@@ -181,7 +178,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
///
/// A implementing the horizontal convolution logic for .
///
- private readonly struct ApplyHorizontalConvolutionRowIntervalOperation : IRowIntervalOperation
+ private readonly struct ApplyHorizontalConvolutionRowOperation : IRowOperation
{
private readonly Rectangle bounds;
private readonly Buffer2D targetValues;
@@ -193,7 +190,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
private readonly int maxX;
[MethodImpl(InliningOptions.ShortMethod)]
- public ApplyHorizontalConvolutionRowIntervalOperation(
+ public ApplyHorizontalConvolutionRowOperation(
Rectangle bounds,
Buffer2D targetValues,
Buffer2D sourceValues,
@@ -213,16 +210,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
///
[MethodImpl(InliningOptions.ShortMethod)]
- public void Invoke(in RowInterval rows)
+ public void Invoke(int y)
{
- for (int y = rows.Min; y < rows.Max; y++)
- {
- Span targetRowSpan = this.targetValues.GetRowSpan(y).Slice(this.bounds.X);
+ Span targetRowSpan = this.targetValues.GetRowSpan(y).Slice(this.bounds.X);
- for (int x = 0; x < this.bounds.Width; x++)
- {
- Buffer2DUtils.Convolve4AndAccumulatePartials(this.kernel, this.sourceValues, targetRowSpan, y, x, this.bounds.Y, this.maxY, this.bounds.X, this.maxX, this.z, this.w);
- }
+ for (int x = 0; x < this.bounds.Width; x++)
+ {
+ Buffer2DUtils.Convolve4AndAccumulatePartials(this.kernel, this.sourceValues, targetRowSpan, y, x, this.bounds.Y, this.maxY, this.bounds.X, this.maxX, this.z, this.w);
}
}
}
@@ -230,7 +224,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
///
/// A implementing the gamma exposure logic for .
///
- private readonly struct ApplyGammaExposureRowIntervalOperation : IRowIntervalOperation
+ private readonly struct ApplyGammaExposureRowOperation : IRowOperation
{
private readonly Rectangle bounds;
private readonly Buffer2D targetPixels;
@@ -238,7 +232,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
private readonly float gamma;
[MethodImpl(InliningOptions.ShortMethod)]
- public ApplyGammaExposureRowIntervalOperation(
+ public ApplyGammaExposureRowOperation(
Rectangle bounds,
Buffer2D targetPixels,
Configuration configuration,
@@ -252,31 +246,28 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
///
[MethodImpl(InliningOptions.ShortMethod)]
- public void Invoke(in RowInterval rows, Span span)
+ public void Invoke(int y, Span 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, span.Length), span, PixelConversionModifiers.Premultiply);
+ ref Vector4 baseRef = ref MemoryMarshal.GetReference(span);
+
+ for (int x = 0; x < this.bounds.Width; x++)
{
- Span targetRowSpan = this.targetPixels.GetRowSpan(y).Slice(this.bounds.X);
- 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++)
- {
- 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, targetRowSpan);
+ 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, targetRowSpan);
}
}
///
/// A implementing the inverse gamma exposure logic for .
///
- private readonly struct ApplyInverseGammaExposureRowIntervalOperation : IRowIntervalOperation
+ private readonly struct ApplyInverseGammaExposureRowOperation : IRowOperation
{
private readonly Rectangle bounds;
private readonly Buffer2D targetPixels;
@@ -285,7 +276,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
private readonly float inverseGamma;
[MethodImpl(InliningOptions.ShortMethod)]
- public ApplyInverseGammaExposureRowIntervalOperation(
+ public ApplyInverseGammaExposureRowOperation(
Rectangle bounds,
Buffer2D targetPixels,
Buffer2D sourceValues,
@@ -301,28 +292,25 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
///
[MethodImpl(InliningOptions.ShortMethod)]
- public void Invoke(in RowInterval rows)
+ public void Invoke(int y)
{
Vector4 low = Vector4.Zero;
var high = new Vector4(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity);
- for (int y = rows.Min; y < rows.Max; y++)
+ Span targetPixelSpan = this.targetPixels.GetRowSpan(y).Slice(this.bounds.X);
+ Span sourceRowSpan = this.sourceValues.GetRowSpan(y).Slice(this.bounds.X);
+ ref Vector4 sourceRef = ref MemoryMarshal.GetReference(sourceRowSpan);
+
+ for (int x = 0; x < this.bounds.Width; x++)
{
- Span targetPixelSpan = this.targetPixels.GetRowSpan(y).Slice(this.bounds.X);
- Span sourceRowSpan = this.sourceValues.GetRowSpan(y).Slice(this.bounds.X);
- ref Vector4 sourceRef = ref MemoryMarshal.GetReference(sourceRowSpan);
-
- for (int x = 0; x < this.bounds.Width; x++)
- {
- ref Vector4 v = ref Unsafe.Add(ref sourceRef, x);
- var clamp = Vector4.Clamp(v, low, high);
- v.X = MathF.Pow(clamp.X, this.inverseGamma);
- v.Y = MathF.Pow(clamp.Y, this.inverseGamma);
- v.Z = MathF.Pow(clamp.Z, this.inverseGamma);
- }
-
- PixelOperations.Instance.FromVector4Destructive(this.configuration, sourceRowSpan.Slice(0, this.bounds.Width), targetPixelSpan, PixelConversionModifiers.Premultiply);
+ ref Vector4 v = ref Unsafe.Add(ref sourceRef, x);
+ var clamp = Vector4.Clamp(v, low, high);
+ v.X = MathF.Pow(clamp.X, this.inverseGamma);
+ v.Y = MathF.Pow(clamp.Y, this.inverseGamma);
+ v.Z = MathF.Pow(clamp.Z, this.inverseGamma);
}
+
+ PixelOperations.Instance.FromVector4Destructive(this.configuration, sourceRowSpan.Slice(0, this.bounds.Width), targetPixelSpan, PixelConversionModifiers.Premultiply);
}
}
}
diff --git a/src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor{TPixel}.cs
index b4902fbd7e..f7439879e4 100644
--- a/src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor{TPixel}.cs
@@ -65,9 +65,9 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
source.CopyTo(targetPixels);
var interest = Rectangle.Intersect(this.SourceRectangle, source.Bounds());
- var operation = new RowIntervalOperation(interest, targetPixels, source.PixelBuffer, this.KernelY, this.KernelX, this.Configuration, this.PreserveAlpha);
+ var operation = new RowOperation(interest, targetPixels, source.PixelBuffer, this.KernelY, this.KernelX, this.Configuration, this.PreserveAlpha);
- ParallelRowIterator.IterateRows(
+ ParallelRowIterator.IterateRows(
this.Configuration,
interest,
in operation);
@@ -78,7 +78,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
///
/// A implementing the convolution logic for .
///
- private readonly struct RowIntervalOperation : IRowIntervalOperation
+ private readonly struct RowOperation : IRowOperation
{
private readonly Rectangle bounds;
private readonly int maxY;
@@ -91,7 +91,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
private readonly bool preserveAlpha;
[MethodImpl(InliningOptions.ShortMethod)]
- public RowIntervalOperation(
+ public RowOperation(
Rectangle bounds,
Buffer2D targetPixels,
Buffer2D sourcePixels,
@@ -113,52 +113,48 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
///
[MethodImpl(InliningOptions.ShortMethod)]
- public void Invoke(in RowInterval rows, Span span)
+ public void Invoke(int y, Span span)
{
ref Vector4 spanRef = ref MemoryMarshal.GetReference(span);
+ Span targetRowSpan = this.targetPixels.GetRowSpan(y).Slice(this.bounds.X);
+ PixelOperations.Instance.ToVector4(this.configuration, targetRowSpan.Slice(0, span.Length), span);
- for (int y = rows.Min; y < rows.Max; y++)
+ if (this.preserveAlpha)
{
- Span targetRowSpan = this.targetPixels.GetRowSpan(y).Slice(this.bounds.X);
- PixelOperations.Instance.ToVector4(this.configuration, targetRowSpan.Slice(0, span.Length), span);
-
- 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 spanRef,
- y,
- x,
- this.bounds.Y,
- this.maxY,
- this.bounds.X,
- this.maxX);
- }
+ DenseMatrixUtils.Convolve2D3(
+ in this.kernelY,
+ in this.kernelX,
+ this.sourcePixels,
+ ref spanRef,
+ 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 spanRef,
- y,
- x,
- this.bounds.Y,
- this.maxY,
- this.bounds.X,
- this.maxX);
- }
+ DenseMatrixUtils.Convolve2D4(
+ in this.kernelY,
+ in this.kernelX,
+ this.sourcePixels,
+ ref spanRef,
+ y,
+ x,
+ this.bounds.Y,
+ this.maxY,
+ this.bounds.X,
+ this.maxX);
}
-
- PixelOperations.Instance.FromVector4Destructive(this.configuration, span, 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 30f2c6b4e6..4bbb15cbad 100644
--- a/src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor{TPixel}.cs
@@ -64,15 +64,15 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
var interest = Rectangle.Intersect(this.SourceRectangle, source.Bounds());
// Horizontal convolution
- var horizontalOperation = new RowIntervalOperation(interest, firstPassPixels, source.PixelBuffer, this.KernelX, this.Configuration, this.PreserveAlpha);
- ParallelRowIterator.IterateRows(
+ var horizontalOperation = new RowOperation(interest, firstPassPixels, source.PixelBuffer, this.KernelX, this.Configuration, this.PreserveAlpha);
+ ParallelRowIterator.IterateRows(
this.Configuration,
interest,
in horizontalOperation);
// Vertical convolution
- var verticalOperation = new RowIntervalOperation(interest, source.PixelBuffer, firstPassPixels, this.KernelY, this.Configuration, this.PreserveAlpha);
- ParallelRowIterator.IterateRows(
+ var verticalOperation = new RowOperation(interest, source.PixelBuffer, firstPassPixels, this.KernelY, this.Configuration, this.PreserveAlpha);
+ ParallelRowIterator.IterateRows(
this.Configuration,
interest,
in verticalOperation);
@@ -81,7 +81,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
///
/// A implementing the convolution logic for .
///
- private readonly struct RowIntervalOperation : IRowIntervalOperation
+ private readonly struct RowOperation : IRowOperation
{
private readonly Rectangle bounds;
private readonly Buffer2D targetPixels;
@@ -91,7 +91,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
private readonly bool preserveAlpha;
[MethodImpl(InliningOptions.ShortMethod)]
- public RowIntervalOperation(
+ public RowOperation(
Rectangle bounds,
Buffer2D targetPixels,
Buffer2D sourcePixels,
@@ -109,53 +109,50 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
///
[MethodImpl(InliningOptions.ShortMethod)]
- public void Invoke(in RowInterval rows, Span span)
+ public void Invoke(int y, Span span)
{
ref Vector4 spanRef = 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, span.Length), span);
+ Span targetRowSpan = this.targetPixels.GetRowSpan(y).Slice(this.bounds.X);
+ PixelOperations.Instance.ToVector4(this.configuration, targetRowSpan.Slice(0, span.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 spanRef,
- y,
- x,
- this.bounds.Y,
- maxY,
- this.bounds.X,
- maxX);
- }
+ DenseMatrixUtils.Convolve3(
+ in this.kernel,
+ this.sourcePixels,
+ ref spanRef,
+ 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 spanRef,
- y,
- x,
- this.bounds.Y,
- maxY,
- this.bounds.X,
- maxX);
- }
+ DenseMatrixUtils.Convolve4(
+ in this.kernel,
+ this.sourcePixels,
+ ref spanRef,
+ y,
+ x,
+ this.bounds.Y,
+ maxY,
+ this.bounds.X,
+ maxX);
}
-
- PixelOperations.Instance.FromVector4Destructive(this.configuration, span, 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 b6f9bb319e..a2c8fc1fbe 100644
--- a/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor{TPixel}.cs
@@ -56,8 +56,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
source.CopyTo(targetPixels);
var interest = Rectangle.Intersect(this.SourceRectangle, source.Bounds());
- var operation = new RowIntervalOperation(interest, targetPixels, source.PixelBuffer, this.KernelXY, this.Configuration, this.PreserveAlpha);
- ParallelRowIterator.IterateRows(
+ var operation = new RowOperation(interest, targetPixels, source.PixelBuffer, this.KernelXY, this.Configuration, this.PreserveAlpha);
+ ParallelRowIterator.IterateRows(
this.Configuration,
interest,
in operation);
@@ -68,7 +68,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
///
/// A implementing the convolution logic for .
///
- private readonly struct RowIntervalOperation : IRowIntervalOperation
+ private readonly struct RowOperation : IRowOperation
{
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 RowIntervalOperation(
+ public RowOperation(
Rectangle bounds,
Buffer2D targetPixels,
Buffer2D sourcePixels,
@@ -100,50 +100,47 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
///
[MethodImpl(InliningOptions.ShortMethod)]
- public void Invoke(in RowInterval rows, Span span)
+ public void Invoke(int y, Span span)
{
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, span.Length), span);
+ Span targetRowSpan = this.targetPixels.GetRowSpan(y).Slice(this.bounds.X);
+ PixelOperations.Instance.ToVector4(this.configuration, targetRowSpan.Slice(0, span.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 spanRef,
- y,
- x,
- this.bounds.Y,
- this.maxY,
- this.bounds.X,
- this.maxX);
- }
+ DenseMatrixUtils.Convolve3(
+ in this.kernel,
+ this.sourcePixels,
+ ref spanRef,
+ 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 spanRef,
- y,
- x,
- this.bounds.Y,
- this.maxY,
- this.bounds.X,
- this.maxX);
- }
+ DenseMatrixUtils.Convolve4(
+ in this.kernel,
+ this.sourcePixels,
+ ref spanRef,
+ y,
+ x,
+ this.bounds.Y,
+ this.maxY,
+ this.bounds.X,
+ this.maxX);
}
-
- PixelOperations.Instance.FromVector4Destructive(this.configuration, span, targetRowSpan);
}
+
+ PixelOperations.Instance.FromVector4Destructive(this.configuration, span, targetRowSpan);
}
}
}
diff --git a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorCompassProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorCompassProcessor{TPixel}.cs
index f93fe20b14..159c67b5cf 100644
--- a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorCompassProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorCompassProcessor{TPixel}.cs
@@ -78,7 +78,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
processor.Apply(pass);
}
- var operation = new RowIntervalOperation(source.PixelBuffer, pass.PixelBuffer, interest);
+ var operation = new RowOperation(source.PixelBuffer, pass.PixelBuffer, interest);
ParallelRowIterator.IterateRows(
this.Configuration,
interest,
@@ -89,7 +89,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
///
/// A implementing the convolution logic for .
///
- private readonly struct RowIntervalOperation : IRowIntervalOperation
+ private readonly struct RowOperation : IRowOperation
{
private readonly Buffer2D targetPixels;
private readonly Buffer2D passPixels;
@@ -97,7 +97,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
private readonly int maxX;
[MethodImpl(InliningOptions.ShortMethod)]
- public RowIntervalOperation(
+ public RowOperation(
Buffer2D targetPixels,
Buffer2D passPixels,
Rectangle bounds)
@@ -110,23 +110,20 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
///
[MethodImpl(InliningOptions.ShortMethod)]
- public void Invoke(in RowInterval rows)
+ public void Invoke(int y)
{
- for (int y = rows.Min; y < rows.Max; y++)
- {
- ref TPixel passPixelsBase = ref MemoryMarshal.GetReference(this.passPixels.GetRowSpan(y));
- ref TPixel targetPixelsBase = ref MemoryMarshal.GetReference(this.targetPixels.GetRowSpan(y));
+ ref TPixel passPixelsBase = ref MemoryMarshal.GetReference(this.passPixels.GetRowSpan(y));
+ ref TPixel targetPixelsBase = ref MemoryMarshal.GetReference(this.targetPixels.GetRowSpan(y));
- for (int x = this.minX; x < this.maxX; x++)
- {
- // Grab the max components of the two pixels
- ref TPixel currentPassPixel = ref Unsafe.Add(ref passPixelsBase, x);
- ref TPixel currentTargetPixel = ref Unsafe.Add(ref targetPixelsBase, x);
+ for (int x = this.minX; x < this.maxX; x++)
+ {
+ // Grab the max components of the two pixels
+ ref TPixel currentPassPixel = ref Unsafe.Add(ref passPixelsBase, x);
+ ref TPixel currentTargetPixel = ref Unsafe.Add(ref targetPixelsBase, x);
- var pixelValue = Vector4.Max(currentPassPixel.ToVector4(), currentTargetPixel.ToVector4());
+ var pixelValue = Vector4.Max(currentPassPixel.ToVector4(), currentTargetPixel.ToVector4());
- currentTargetPixel.FromVector4(pixelValue);
- }
+ currentTargetPixel.FromVector4(pixelValue);
}
}
}
diff --git a/src/ImageSharp/Processing/Processors/Dithering/OrderedDither.cs b/src/ImageSharp/Processing/Processors/Dithering/OrderedDither.cs
index 64fe230f36..3e25e2a02a 100644
--- a/src/ImageSharp/Processing/Processors/Dithering/OrderedDither.cs
+++ b/src/ImageSharp/Processing/Processors/Dithering/OrderedDither.cs
@@ -119,7 +119,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering
destination,
bounds);
- ParallelRowIterator.IterateRows(
+ ParallelRowIterator.IterateRowIntervals(
quantizer.Configuration,
bounds,
in ditherOperation);
@@ -140,7 +140,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering
source,
bounds);
- ParallelRowIterator.IterateRows(
+ ParallelRowIterator.IterateRowIntervals(
processor.Configuration,
bounds,
in ditherOperation);
diff --git a/src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor{TPixelBg,TPixelFg}.cs b/src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor{TPixelBg,TPixelFg}.cs
index ae938aec1b..fca896929f 100644
--- a/src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor{TPixelBg,TPixelFg}.cs
+++ b/src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor{TPixelBg,TPixelFg}.cs
@@ -99,7 +99,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing
"Cannot draw image because the source image does not overlap the target image.");
}
- var operation = new RowIntervalOperation(source, targetImage, blender, configuration, minX, width, locationY, targetX, this.Opacity);
+ var operation = new RowOperation(source, targetImage, blender, configuration, minX, width, locationY, targetX, this.Opacity);
ParallelRowIterator.IterateRows(
configuration,
workingRect,
@@ -109,7 +109,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing
///
/// A implementing the draw logic for .
///
- private readonly struct RowIntervalOperation : IRowIntervalOperation
+ private readonly struct RowOperation : IRowOperation
{
private readonly ImageFrame sourceFrame;
private readonly Image targetImage;
@@ -122,7 +122,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing
private readonly float opacity;
[MethodImpl(InliningOptions.ShortMethod)]
- public RowIntervalOperation(
+ public RowOperation(
ImageFrame sourceFrame,
Image targetImage,
PixelBlender blender,
@@ -146,14 +146,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing
///
[MethodImpl(InliningOptions.ShortMethod)]
- public void Invoke(in RowInterval rows)
+ public void Invoke(int y)
{
- for (int y = rows.Min; y < rows.Max; y++)
- {
- Span background = this.sourceFrame.GetPixelRowSpan(y).Slice(this.minX, this.width);
- Span foreground = this.targetImage.GetPixelRowSpan(y - this.locationY).Slice(this.targetX, this.width);
- this.blender.Blend(this.configuration, background, background, foreground, this.opacity);
- }
+ Span background = this.sourceFrame.GetPixelRowSpan(y).Slice(this.minX, this.width);
+ Span foreground = this.targetImage.GetPixelRowSpan(y - this.locationY).Slice(this.targetX, this.width);
+ this.blender.Blend(this.configuration, background, background, foreground, this.opacity);
}
}
}
diff --git a/src/ImageSharp/Processing/Processors/Effects/OilPaintingProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Effects/OilPaintingProcessor{TPixel}.cs
index 270eb1343c..5ee1e40de0 100644
--- a/src/ImageSharp/Processing/Processors/Effects/OilPaintingProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Effects/OilPaintingProcessor{TPixel}.cs
@@ -48,7 +48,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Effects
source.CopyTo(targetPixels);
var operation = new RowIntervalOperation(this.SourceRectangle, targetPixels, source, this.Configuration, brushSize >> 1, this.definition.Levels);
- ParallelRowIterator.IterateRows(
+ ParallelRowIterator.IterateRowIntervals(
this.Configuration,
this.SourceRectangle,
in operation);
diff --git a/src/ImageSharp/Processing/Processors/Effects/PixelRowDelegateProcessor{TPixel,TDelegate}.cs b/src/ImageSharp/Processing/Processors/Effects/PixelRowDelegateProcessor{TPixel,TDelegate}.cs
index 1907228c96..71259a6188 100644
--- a/src/ImageSharp/Processing/Processors/Effects/PixelRowDelegateProcessor{TPixel,TDelegate}.cs
+++ b/src/ImageSharp/Processing/Processors/Effects/PixelRowDelegateProcessor{TPixel,TDelegate}.cs
@@ -50,9 +50,9 @@ namespace SixLabors.ImageSharp.Processing.Processors.Effects
protected override void OnFrameApply(ImageFrame source)
{
var interest = Rectangle.Intersect(this.SourceRectangle, source.Bounds());
- var operation = new RowIntervalOperation(interest.X, source, this.Configuration, this.modifiers, this.rowDelegate);
+ var operation = new RowOperation(interest.X, source, this.Configuration, this.modifiers, this.rowDelegate);
- ParallelRowIterator.IterateRows(
+ ParallelRowIterator.IterateRows(
this.Configuration,
interest,
in operation);
@@ -61,7 +61,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Effects
///
/// A implementing the convolution logic for .
///
- private readonly struct RowIntervalOperation : IRowIntervalOperation
+ private readonly struct RowOperation : IRowOperation
{
private readonly int startX;
private readonly ImageFrame source;
@@ -70,7 +70,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Effects
private readonly TDelegate rowProcessor;
[MethodImpl(InliningOptions.ShortMethod)]
- public RowIntervalOperation(
+ public RowOperation(
int startX,
ImageFrame source,
Configuration configuration,
@@ -86,18 +86,15 @@ namespace SixLabors.ImageSharp.Processing.Processors.Effects
///
[MethodImpl(InliningOptions.ShortMethod)]
- public void Invoke(in RowInterval rows, Span span)
+ public void Invoke(int y, Span span)
{
- for (int y = rows.Min; y < rows.Max; y++)
- {
- Span rowSpan = this.source.GetPixelRowSpan(y).Slice(this.startX, span.Length);
- PixelOperations.Instance.ToVector4(this.configuration, rowSpan, span, 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(span, 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, span, 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 545c53915a..7da4eb1b10 100644
--- a/src/ImageSharp/Processing/Processors/Filters/FilterProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Filters/FilterProcessor{TPixel}.cs
@@ -36,9 +36,9 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters
protected override void OnFrameApply(ImageFrame source)
{
var interest = Rectangle.Intersect(this.SourceRectangle, source.Bounds());
- var operation = new RowIntervalOperation(interest.X, source, this.definition.Matrix, this.Configuration);
+ var operation = new RowOperation(interest.X, source, this.definition.Matrix, this.Configuration);
- ParallelRowIterator.IterateRows(
+ ParallelRowIterator.IterateRows(
this.Configuration,
interest,
in operation);
@@ -47,7 +47,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters
///
/// A implementing the convolution logic for .
///
- private readonly struct RowIntervalOperation : IRowIntervalOperation
+ private readonly struct RowOperation : IRowOperation
{
private readonly int startX;
private readonly ImageFrame source;
@@ -55,7 +55,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters
private readonly Configuration configuration;
[MethodImpl(InliningOptions.ShortMethod)]
- public RowIntervalOperation(
+ public RowOperation(
int startX,
ImageFrame source,
ColorMatrix matrix,
@@ -69,17 +69,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters
///
[MethodImpl(InliningOptions.ShortMethod)]
- public void Invoke(in RowInterval rows, Span span)
+ public void Invoke(int y, Span span)
{
- for (int y = rows.Min; y < rows.Max; y++)
- {
- Span rowSpan = this.source.GetPixelRowSpan(y).Slice(this.startX, span.Length);
- PixelOperations.Instance.ToVector4(this.configuration, rowSpan, span);
+ Span rowSpan = this.source.GetPixelRowSpan(y).Slice(this.startX, span.Length);
+ PixelOperations.Instance.ToVector4(this.configuration, rowSpan, span);
- Vector4Utils.Transform(span, ref Unsafe.AsRef(this.matrix));
+ Vector4Utils.Transform(span, ref Unsafe.AsRef(this.matrix));
- PixelOperations.Instance.FromVector4Destructive(this.configuration, span, rowSpan);
- }
+ PixelOperations.Instance.FromVector4Destructive(this.configuration, span, rowSpan);
}
}
}
diff --git a/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistogramEqualizationProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistogramEqualizationProcessor{TPixel}.cs
index 5fdedad6ed..1547de8acf 100644
--- a/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistogramEqualizationProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistogramEqualizationProcessor{TPixel}.cs
@@ -81,7 +81,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization
}
var operation = new RowIntervalOperation(cdfData, tileYStartPositions, tileWidth, tileHeight, tileCount, halfTileWidth, luminanceLevels, source);
- ParallelRowIterator.IterateRows(
+ ParallelRowIterator.IterateRowIntervals(
this.Configuration,
new Rectangle(0, 0, sourceWidth, tileYStartPositions.Count),
in operation);
@@ -522,7 +522,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization
this.luminanceLevels,
source);
- ParallelRowIterator.IterateRows(
+ ParallelRowIterator.IterateRowIntervals(
this.configuration,
new Rectangle(0, 0, this.sourceWidth, this.tileYStartPositions.Count),
in operation);
diff --git a/src/ImageSharp/Processing/Processors/Normalization/GlobalHistogramEqualizationProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Normalization/GlobalHistogramEqualizationProcessor{TPixel}.cs
index a99fb405e8..209135debb 100644
--- a/src/ImageSharp/Processing/Processors/Normalization/GlobalHistogramEqualizationProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Normalization/GlobalHistogramEqualizationProcessor{TPixel}.cs
@@ -52,7 +52,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization
using IMemoryOwner histogramBuffer = memoryAllocator.Allocate(this.LuminanceLevels, AllocationOptions.Clean);
// Build the histogram of the grayscale levels
- var grayscaleOperation = new GrayscaleLevelsRowIntervalOperation(interest, histogramBuffer, source, this.LuminanceLevels);
+ var grayscaleOperation = new GrayscaleLevelsRowOperation(interest, histogramBuffer, source, this.LuminanceLevels);
ParallelRowIterator.IterateRows(
this.Configuration,
interest,
@@ -75,7 +75,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization
float numberOfPixelsMinusCdfMin = numberOfPixels - cdfMin;
// Apply the cdf to each pixel of the image
- var cdfOperation = new CdfApplicationRowIntervalOperation(interest, cdfBuffer, source, this.LuminanceLevels, numberOfPixelsMinusCdfMin);
+ var cdfOperation = new CdfApplicationRowOperation(interest, cdfBuffer, source, this.LuminanceLevels, numberOfPixelsMinusCdfMin);
ParallelRowIterator.IterateRows(
this.Configuration,
interest,
@@ -85,7 +85,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization
///
/// A implementing the grayscale levels logic for .
///
- private readonly struct GrayscaleLevelsRowIntervalOperation : IRowIntervalOperation
+ private readonly struct GrayscaleLevelsRowOperation : IRowOperation
{
private readonly Rectangle bounds;
private readonly IMemoryOwner histogramBuffer;
@@ -93,7 +93,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization
private readonly int luminanceLevels;
[MethodImpl(InliningOptions.ShortMethod)]
- public GrayscaleLevelsRowIntervalOperation(
+ public GrayscaleLevelsRowOperation(
Rectangle bounds,
IMemoryOwner histogramBuffer,
ImageFrame source,
@@ -107,18 +107,15 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization
///
[MethodImpl(InliningOptions.ShortMethod)]
- public void Invoke(in RowInterval rows)
+ public void Invoke(int y)
{
ref int histogramBase = ref MemoryMarshal.GetReference(this.histogramBuffer.GetSpan());
- for (int y = rows.Min; y < rows.Max; y++)
- {
- ref TPixel pixelBase = ref MemoryMarshal.GetReference(this.source.GetPixelRowSpan(y));
+ ref TPixel pixelBase = ref MemoryMarshal.GetReference(this.source.GetPixelRowSpan(y));
- for (int x = 0; x < this.bounds.Width; x++)
- {
- int luminance = GetLuminance(Unsafe.Add(ref pixelBase, x), this.luminanceLevels);
- Unsafe.Add(ref histogramBase, luminance)++;
- }
+ for (int x = 0; x < this.bounds.Width; x++)
+ {
+ int luminance = GetLuminance(Unsafe.Add(ref pixelBase, x), this.luminanceLevels);
+ Unsafe.Add(ref histogramBase, luminance)++;
}
}
}
@@ -126,7 +123,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization
///
/// A implementing the cdf application levels logic for .
///
- private readonly struct CdfApplicationRowIntervalOperation : IRowIntervalOperation
+ private readonly struct CdfApplicationRowOperation : IRowOperation
{
private readonly Rectangle bounds;
private readonly IMemoryOwner cdfBuffer;
@@ -135,7 +132,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization
private readonly float numberOfPixelsMinusCdfMin;
[MethodImpl(InliningOptions.ShortMethod)]
- public CdfApplicationRowIntervalOperation(
+ public CdfApplicationRowOperation(
Rectangle bounds,
IMemoryOwner cdfBuffer,
ImageFrame source,
@@ -151,20 +148,17 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization
///
[MethodImpl(InliningOptions.ShortMethod)]
- public void Invoke(in RowInterval rows)
+ public void Invoke(int y)
{
ref int cdfBase = ref MemoryMarshal.GetReference(this.cdfBuffer.GetSpan());
- for (int y = rows.Min; y < rows.Max; y++)
+ ref TPixel pixelBase = ref MemoryMarshal.GetReference(this.source.GetPixelRowSpan(y));
+
+ for (int x = 0; x < this.bounds.Width; x++)
{
- ref TPixel pixelBase = ref MemoryMarshal.GetReference(this.source.GetPixelRowSpan(y));
-
- for (int x = 0; x < this.bounds.Width; x++)
- {
- ref TPixel pixel = ref Unsafe.Add(ref pixelBase, x);
- int luminance = GetLuminance(pixel, this.luminanceLevels);
- float luminanceEqualized = Unsafe.Add(ref cdfBase, luminance) / this.numberOfPixelsMinusCdfMin;
- pixel.FromVector4(new Vector4(luminanceEqualized, luminanceEqualized, luminanceEqualized, pixel.ToVector4().W));
- }
+ ref TPixel pixel = ref Unsafe.Add(ref pixelBase, x);
+ int luminance = GetLuminance(pixel, this.luminanceLevels);
+ float luminanceEqualized = Unsafe.Add(ref cdfBase, luminance) / this.numberOfPixelsMinusCdfMin;
+ pixel.FromVector4(new Vector4(luminanceEqualized, luminanceEqualized, luminanceEqualized, pixel.ToVector4().W));
}
}
}
diff --git a/src/ImageSharp/Processing/Processors/Overlays/BackgroundColorProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Overlays/BackgroundColorProcessor{TPixel}.cs
index a1e9d1c4ef..727e724698 100644
--- a/src/ImageSharp/Processing/Processors/Overlays/BackgroundColorProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Overlays/BackgroundColorProcessor{TPixel}.cs
@@ -49,14 +49,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays
PixelBlender blender = PixelOperations.Instance.GetPixelBlender(graphicsOptions);
- var operation = new RowIntervalOperation(configuration, interest, blender, amount, colors, source);
+ var operation = new RowOperation(configuration, interest, blender, amount, colors, source);
ParallelRowIterator.IterateRows(
configuration,
interest,
in operation);
}
- private readonly struct RowIntervalOperation : IRowIntervalOperation
+ private readonly struct RowOperation : IRowOperation
{
private readonly Configuration configuration;
private readonly Rectangle bounds;
@@ -66,7 +66,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays
private readonly ImageFrame source;
[MethodImpl(InliningOptions.ShortMethod)]
- public RowIntervalOperation(
+ public RowOperation(
Configuration configuration,
Rectangle bounds,
PixelBlender blender,
@@ -83,23 +83,20 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays
}
[MethodImpl(InliningOptions.ShortMethod)]
- public void Invoke(in RowInterval rows)
+ public void Invoke(int y)
{
- for (int y = rows.Min; y < rows.Max; y++)
- {
- 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);
- // Switch color & destination in the 2nd and 3rd places because we are
- // applying the target color under the current one.
- this.blender.Blend(
- this.configuration,
- destination,
- this.colors.GetSpan(),
- destination,
- this.amount.GetSpan());
- }
+ // Switch color & destination in the 2nd and 3rd places because we are
+ // applying the target color under the current one.
+ this.blender.Blend(
+ this.configuration,
+ destination,
+ this.colors.GetSpan(),
+ destination,
+ this.amount.GetSpan());
}
}
}
diff --git a/src/ImageSharp/Processing/Processors/Overlays/GlowProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Overlays/GlowProcessor{TPixel}.cs
index 33c4123e99..fbecbc37ce 100644
--- a/src/ImageSharp/Processing/Processors/Overlays/GlowProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Overlays/GlowProcessor{TPixel}.cs
@@ -55,14 +55,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays
using IMemoryOwner rowColors = allocator.Allocate(interest.Width);
rowColors.GetSpan().Fill(glowColor);
- var operation = new RowIntervalOperation(configuration, interest, rowColors, this.blender, center, maxDistance, blendPercent, source);
- ParallelRowIterator.IterateRows(
+ var operation = new RowOperation(configuration, interest, rowColors, this.blender, center, maxDistance, blendPercent, source);
+ ParallelRowIterator.IterateRows(
configuration,
interest,
in operation);
}
- private readonly struct RowIntervalOperation : IRowIntervalOperation
+ private readonly struct RowOperation : IRowOperation
{
private readonly Configuration configuration;
private readonly Rectangle bounds;
@@ -74,7 +74,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays
private readonly ImageFrame source;
[MethodImpl(InliningOptions.ShortMethod)]
- public RowIntervalOperation(
+ public RowOperation(
Configuration configuration,
Rectangle bounds,
IMemoryOwner colors,
@@ -95,27 +95,24 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays
}
[MethodImpl(InliningOptions.ShortMethod)]
- public void Invoke(in RowInterval rows, Span span)
+ public void Invoke(int y, Span 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));
- span[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,
- span);
- }
+ 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 0618873f25..378009c400 100644
--- a/src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor{TPixel}.cs
@@ -63,14 +63,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays
using IMemoryOwner rowColors = allocator.Allocate(interest.Width);
rowColors.GetSpan().Fill(vignetteColor);
- var operation = new RowIntervalOperation(configuration, interest, rowColors, this.blender, center, maxDistance, blendPercent, source);
- ParallelRowIterator.IterateRows(
+ var operation = new RowOperation(configuration, interest, rowColors, this.blender, center, maxDistance, blendPercent, source);
+ ParallelRowIterator.IterateRows(
configuration,
interest,
in operation);
}
- private readonly struct RowIntervalOperation : IRowIntervalOperation
+ private readonly struct RowOperation : IRowOperation
{
private readonly Configuration configuration;
private readonly Rectangle bounds;
@@ -82,7 +82,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays
private readonly ImageFrame source;
[MethodImpl(InliningOptions.ShortMethod)]
- public RowIntervalOperation(
+ public RowOperation(
Configuration configuration,
Rectangle bounds,
IMemoryOwner colors,
@@ -103,27 +103,24 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays
}
[MethodImpl(InliningOptions.ShortMethod)]
- public void Invoke(in RowInterval rows, Span span)
+ public void Invoke(int y, Span 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));
- 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);
+ 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/Quantization/FrameQuantizerExtensions.cs b/src/ImageSharp/Processing/Processors/Quantization/FrameQuantizerExtensions.cs
index 139ed6e9ea..88973c44b4 100644
--- a/src/ImageSharp/Processing/Processors/Quantization/FrameQuantizerExtensions.cs
+++ b/src/ImageSharp/Processing/Processors/Quantization/FrameQuantizerExtensions.cs
@@ -70,7 +70,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
if (dither is null)
{
var operation = new RowIntervalOperation(ref quantizer, source, destination, bounds);
- ParallelRowIterator.IterateRows(
+ ParallelRowIterator.IterateRowIntervals(
quantizer.Configuration,
bounds,
in operation);
diff --git a/src/ImageSharp/Processing/Processors/Quantization/QuantizeProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/QuantizeProcessor{TPixel}.cs
index 5a0116a03f..cbef193005 100644
--- a/src/ImageSharp/Processing/Processors/Quantization/QuantizeProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Quantization/QuantizeProcessor{TPixel}.cs
@@ -42,7 +42,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
using QuantizedFrame quantized = frameQuantizer.QuantizeFrame(source, interest);
var operation = new RowIntervalOperation(this.SourceRectangle, source, quantized);
- ParallelRowIterator.IterateRows(
+ ParallelRowIterator.IterateRowIntervals(
configuration,
interest,
in operation);
diff --git a/src/ImageSharp/Processing/Processors/Transforms/CropProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/CropProcessor{TPixel}.cs
index a4bcb3d719..a366fd51de 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/CropProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/CropProcessor{TPixel}.cs
@@ -51,7 +51,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
ParallelExecutionSettings parallelSettings =
ParallelExecutionSettings.FromConfiguration(this.Configuration).MultiplyMinimumPixelsPerTask(4);
- var operation = new RowIntervalOperation(bounds, source, destination);
+ var operation = new RowOperation(bounds, source, destination);
ParallelRowIterator.IterateRows(
bounds,
@@ -62,20 +62,20 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
///
/// A implementing the processor logic for .
///
- private readonly struct RowIntervalOperation : IRowIntervalOperation
+ private readonly struct RowOperation : IRowOperation
{
private readonly Rectangle bounds;
private readonly ImageFrame source;
private readonly ImageFrame destination;
///
- /// Initializes a new instance of the struct.
+ /// Initializes a new instance of the struct.
///
/// The target processing bounds for the current instance.
/// The source for the current instance.
/// The destination for the current instance.
[MethodImpl(InliningOptions.ShortMethod)]
- public RowIntervalOperation(Rectangle bounds, ImageFrame source, ImageFrame destination)
+ public RowOperation(Rectangle bounds, ImageFrame source, ImageFrame destination)
{
this.bounds = bounds;
this.source = source;
@@ -84,14 +84,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
///
[MethodImpl(InliningOptions.ShortMethod)]
- public void Invoke(in RowInterval rows)
+ public void Invoke(int y)
{
- for (int y = rows.Min; y < rows.Max; y++)
- {
- Span sourceRow = this.source.GetPixelRowSpan(y).Slice(this.bounds.Left);
- Span targetRow = this.destination.GetPixelRowSpan(y - this.bounds.Top);
- sourceRow.Slice(0, this.bounds.Width).CopyTo(targetRow);
- }
+ Span sourceRow = this.source.GetPixelRowSpan(y).Slice(this.bounds.Left);
+ Span targetRow = this.destination.GetPixelRowSpan(y - this.bounds.Top);
+ sourceRow.Slice(0, this.bounds.Width).CopyTo(targetRow);
}
}
}
diff --git a/src/ImageSharp/Processing/Processors/Transforms/Linear/AffineTransformProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/Linear/AffineTransformProcessor{TPixel}.cs
index ac18c67cd6..a3c8f71082 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/Linear/AffineTransformProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/Linear/AffineTransformProcessor{TPixel}.cs
@@ -111,7 +111,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
in operation);
}
- private readonly struct NNAffineOperation : IRowIntervalOperation
+ private readonly struct NNAffineOperation : IRowOperation
{
private readonly ImageFrame source;
private readonly ImageFrame destination;
@@ -133,28 +133,25 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
}
[MethodImpl(InliningOptions.ShortMethod)]
- public void Invoke(in RowInterval rows)
+ public void Invoke(int y)
{
- for (int y = rows.Min; y < rows.Max; y++)
+ Span destRow = this.destination.GetPixelRowSpan(y);
+
+ for (int x = 0; x < this.maxX; x++)
{
- Span destRow = this.destination.GetPixelRowSpan(y);
+ var point = Vector2.Transform(new Vector2(x, y), this.matrix);
+ int px = (int)MathF.Round(point.X);
+ int py = (int)MathF.Round(point.Y);
- for (int x = 0; x < this.maxX; x++)
+ if (this.bounds.Contains(px, py))
{
- var point = Vector2.Transform(new Vector2(x, y), this.matrix);
- int px = (int)MathF.Round(point.X);
- int py = (int)MathF.Round(point.Y);
-
- if (this.bounds.Contains(px, py))
- {
- destRow[x] = this.source[px, py];
- }
+ destRow[x] = this.source[px, py];
}
}
}
}
- private readonly struct AffineOperation : IRowIntervalOperation
+ private readonly struct AffineOperation : IRowOperation
where TResampler : struct, IResampler
{
private readonly Configuration configuration;
@@ -193,41 +190,39 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
}
[MethodImpl(InliningOptions.ShortMethod)]
- public void Invoke(in RowInterval rows, Span span)
+ public void Invoke(int y, Span span)
{
Buffer2D sourceBuffer = this.source.PixelBuffer;
- for (int y = rows.Min; y < rows.Max; y++)
- {
- PixelOperations.Instance.ToVector4(
- this.configuration,
- this.destination.GetPixelRowSpan(y),
- span);
- ref float yKernelSpanRef = ref MemoryMarshal.GetReference(this.yKernelBuffer.GetRowSpan(y));
- ref float xKernelSpanRef = ref MemoryMarshal.GetReference(this.xKernelBuffer.GetRowSpan(y));
+ PixelOperations.Instance.ToVector4(
+ this.configuration,
+ this.destination.GetPixelRowSpan(y),
+ span);
- 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);
- LinearTransformUtilities.Convolve(
- in this.sampler,
- point,
- sourceBuffer,
- span,
- x,
- ref yKernelSpanRef,
- ref xKernelSpanRef,
- this.radialExtents,
- this.maxSourceExtents);
- }
+ ref float yKernelSpanRef = ref MemoryMarshal.GetReference(this.yKernelBuffer.GetRowSpan(y));
+ ref float xKernelSpanRef = ref MemoryMarshal.GetReference(this.xKernelBuffer.GetRowSpan(y));
- PixelOperations.Instance.FromVector4Destructive(
- this.configuration,
+ 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);
+ LinearTransformUtilities.Convolve(
+ in this.sampler,
+ point,
+ sourceBuffer,
span,
- this.destination.GetPixelRowSpan(y));
+ x,
+ ref yKernelSpanRef,
+ ref xKernelSpanRef,
+ this.radialExtents,
+ this.maxSourceExtents);
}
+
+ PixelOperations.Instance.FromVector4Destructive(
+ this.configuration,
+ span,
+ this.destination.GetPixelRowSpan(y));
}
}
}
diff --git a/src/ImageSharp/Processing/Processors/Transforms/Linear/FlipProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/Linear/FlipProcessor{TPixel}.cs
index 8db2d42c61..470eafcd8d 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/Linear/FlipProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/Linear/FlipProcessor{TPixel}.cs
@@ -5,7 +5,6 @@ using System;
using System.Buffers;
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Advanced;
-using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Processing.Processors.Transforms
@@ -76,28 +75,22 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
/// The configuration.
private void FlipY(ImageFrame source, Configuration configuration)
{
- var operation = new RowIntervalOperation(source);
+ var operation = new RowOperation(source);
ParallelRowIterator.IterateRows(
configuration,
source.Bounds(),
in operation);
}
- private readonly struct RowIntervalOperation : IRowIntervalOperation
+ private readonly struct RowOperation : IRowOperation
{
private readonly ImageFrame source;
[MethodImpl(InliningOptions.ShortMethod)]
- public RowIntervalOperation(ImageFrame source) => this.source = source;
+ public RowOperation(ImageFrame source) => this.source = source;
[MethodImpl(InliningOptions.ShortMethod)]
- public void Invoke(in RowInterval rows)
- {
- for (int y = rows.Min; y < rows.Max; y++)
- {
- this.source.GetPixelRowSpan(y).Reverse();
- }
- }
+ public void Invoke(int y) => this.source.GetPixelRowSpan(y).Reverse();
}
}
}
diff --git a/src/ImageSharp/Processing/Processors/Transforms/Linear/ProjectiveTransformProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/Linear/ProjectiveTransformProcessor{TPixel}.cs
index 89ebb50f24..f348721d7a 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/Linear/ProjectiveTransformProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/Linear/ProjectiveTransformProcessor{TPixel}.cs
@@ -111,7 +111,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
in operation);
}
- private readonly struct NNProjectiveOperation : IRowIntervalOperation
+ private readonly struct NNProjectiveOperation : IRowOperation
{
private readonly ImageFrame source;
private readonly ImageFrame destination;
@@ -133,28 +133,25 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
}
[MethodImpl(InliningOptions.ShortMethod)]
- public void Invoke(in RowInterval rows)
+ public void Invoke(int y)
{
- for (int y = rows.Min; y < rows.Max; y++)
+ Span destRow = this.destination.GetPixelRowSpan(y);
+
+ for (int x = 0; x < this.maxX; x++)
{
- Span destRow = this.destination.GetPixelRowSpan(y);
+ Vector2 point = TransformUtilities.ProjectiveTransform2D(x, y, this.matrix);
+ int px = (int)MathF.Round(point.X);
+ int py = (int)MathF.Round(point.Y);
- for (int x = 0; x < this.maxX; x++)
+ if (this.bounds.Contains(px, py))
{
- Vector2 point = TransformUtilities.ProjectiveTransform2D(x, y, this.matrix);
- int px = (int)MathF.Round(point.X);
- int py = (int)MathF.Round(point.Y);
-
- if (this.bounds.Contains(px, py))
- {
- destRow[x] = this.source[px, py];
- }
+ destRow[x] = this.source[px, py];
}
}
}
}
- private readonly struct ProjectiveOperation : IRowIntervalOperation
+ private readonly struct ProjectiveOperation