diff --git a/src/ImageSharp/Advanced/IRowAction.cs b/src/ImageSharp/Advanced/IRowAction.cs
new file mode 100644
index 000000000..74498eb0b
--- /dev/null
+++ b/src/ImageSharp/Advanced/IRowAction.cs
@@ -0,0 +1,70 @@
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+using System;
+using System.Runtime.CompilerServices;
+
+namespace SixLabors.ImageSharp.Advanced
+{
+ ///
+ /// Defines the contract for an action that operates on a row.
+ ///
+ public interface IRowAction
+ {
+ ///
+ /// Invokes the method passing the row y coordinate.
+ ///
+ /// The row y coordinate.
+ void Invoke(int y);
+ }
+
+ ///
+ /// A that wraps a value delegate of a specified type, and info on the memory areas to process
+ ///
+ /// The type of value delegate to invoke
+ internal readonly struct WrappingRowAction
+ where T : struct, IRowAction
+ {
+ public readonly int MinY;
+ public readonly int MaxY;
+ public readonly int StepY;
+ public readonly int MaxX;
+
+ private readonly T action;
+
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public WrappingRowAction(int minY, int maxY, int stepY, in T action)
+ : this(minY, maxY, stepY, 0, action)
+ {
+ }
+
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public WrappingRowAction(int minY, int maxY, int stepY, int maxX, in T action)
+ {
+ this.MinY = minY;
+ this.MaxY = maxY;
+ this.StepY = stepY;
+ this.MaxX = maxX;
+ 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);
+
+ 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);
+ }
+ }
+ }
+}
diff --git a/src/ImageSharp/Advanced/IRowAction{TBuffer}.cs b/src/ImageSharp/Advanced/IRowAction{TBuffer}.cs
new file mode 100644
index 000000000..4bf0d1fe4
--- /dev/null
+++ b/src/ImageSharp/Advanced/IRowAction{TBuffer}.cs
@@ -0,0 +1,88 @@
+// Copyright (c) Six Labors and contributors.
+// 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
+{
+ ///
+ /// Defines the contract for an action that operates on a row with a temporary buffer.
+ ///
+ /// The type of buffer elements.
+ public interface IRowAction
+ 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);
+ }
+
+ internal readonly struct WrappingRowAction
+ where T : struct, IRowAction
+ where TBuffer : unmanaged
+ {
+ public readonly int MinY;
+ public readonly int MaxY;
+ public readonly int StepY;
+ public readonly int MaxX;
+
+ private readonly MemoryAllocator allocator;
+ private readonly T action;
+
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public WrappingRowAction(
+ int minY,
+ int maxY,
+ int stepY,
+ MemoryAllocator allocator,
+ in T action)
+ : this(minY, maxY, stepY, 0, allocator, action)
+ {
+ }
+
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public WrappingRowAction(
+ int minY,
+ int maxY,
+ int stepY,
+ int maxX,
+ MemoryAllocator allocator,
+ in T action)
+ {
+ this.MinY = minY;
+ this.MaxY = maxY;
+ this.StepY = stepY;
+ this.MaxX = maxX;
+ 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.MaxX);
+
+ Span span = buffer.Memory.Span;
+
+ for (int y = yMin; y < yMax; y++)
+ {
+ Unsafe.AsRef(this.action).Invoke(y, span);
+ }
+ }
+ }
+}
diff --git a/src/ImageSharp/Advanced/ParallelRowIterator.cs b/src/ImageSharp/Advanced/ParallelRowIterator.cs
index 5c8a30f68..d57e673c0 100644
--- a/src/ImageSharp/Advanced/ParallelRowIterator.cs
+++ b/src/ImageSharp/Advanced/ParallelRowIterator.cs
@@ -19,32 +19,32 @@ namespace SixLabors.ImageSharp.Advanced
public static class ParallelRowIterator
{
///
- /// Iterate through the rows of a rectangle in optimized batches defined by -s.
+ /// Iterate through the rows of a rectangle in optimized batches.
///
/// The type of row action to perform.
/// The .
/// The to get the parallel settings from.
- /// The method body defining the iteration logic on a single .
+ /// The method body defining the iteration logic on a single row.
[MethodImpl(InliningOptions.ShortMethod)]
public static void IterateRows(Rectangle rectangle, Configuration configuration, in T body)
- where T : struct, IRowIntervalAction
+ where T : struct, IRowAction
{
var parallelSettings = ParallelExecutionSettings.FromConfiguration(configuration);
IterateRows(rectangle, in parallelSettings, in body);
}
///
- /// Iterate through the rows of a rectangle in optimized batches defined by -s.
+ /// Iterate through the rows of a rectangle in optimized batches.
///
/// The type of row action to perform.
/// The .
/// The .
- /// The method body defining the iteration logic on a single .
+ /// The method body defining the iteration logic on a single row.
public static void IterateRows(
Rectangle rectangle,
in ParallelExecutionSettings parallelSettings,
in T body)
- where T : struct, IRowIntervalAction
+ where T : struct, IRowAction
{
ValidateRectangle(rectangle);
@@ -59,15 +59,17 @@ namespace SixLabors.ImageSharp.Advanced
// Avoid TPL overhead in this trivial case:
if (numOfSteps == 1)
{
- var rows = new RowInterval(top, bottom);
- Unsafe.AsRef(body).Invoke(in rows);
+ for (int y = top; y < bottom; y++)
+ {
+ Unsafe.AsRef(body).Invoke(y);
+ }
+
return;
}
int verticalStep = DivideCeil(rectangle.Height, numOfSteps);
var parallelOptions = new ParallelOptions { MaxDegreeOfParallelism = numOfSteps };
- var rowInfo = new WrappingRowIntervalInfo(top, bottom, verticalStep);
- var rowAction = new WrappingRowIntervalAction(in rowInfo, in body);
+ var rowAction = new WrappingRowAction(top, bottom, verticalStep, in body);
Parallel.For(
0,
@@ -86,7 +88,7 @@ namespace SixLabors.ImageSharp.Advanced
/// The to get the parallel settings from.
/// The method body defining the iteration logic on a single .
public static void IterateRows(Rectangle rectangle, Configuration configuration, in T body)
- where T : struct, IRowIntervalAction
+ where T : struct, IRowAction
where TBuffer : unmanaged
{
var parallelSettings = ParallelExecutionSettings.FromConfiguration(configuration);
@@ -101,7 +103,7 @@ namespace SixLabors.ImageSharp.Advanced
Rectangle rectangle,
in ParallelExecutionSettings parallelSettings,
in T body)
- where T : struct, IRowIntervalAction
+ where T : struct, IRowAction
where TBuffer : unmanaged
{
ValidateRectangle(rectangle);
@@ -118,10 +120,14 @@ namespace SixLabors.ImageSharp.Advanced
// Avoid TPL overhead in this trivial case:
if (numOfSteps == 1)
{
- var rows = new RowInterval(top, bottom);
using (IMemoryOwner buffer = allocator.Allocate(width))
{
- Unsafe.AsRef(body).Invoke(rows, buffer.Memory);
+ Span span = buffer.Memory.Span;
+
+ for (int y = top; y < bottom; y++)
+ {
+ Unsafe.AsRef(body).Invoke(y, span);
+ }
}
return;
@@ -129,8 +135,7 @@ namespace SixLabors.ImageSharp.Advanced
int verticalStep = DivideCeil(height, numOfSteps);
var parallelOptions = new ParallelOptions { MaxDegreeOfParallelism = numOfSteps };
- var rowInfo = new WrappingRowIntervalInfo(top, bottom, verticalStep, width);
- var rowAction = new WrappingRowIntervalBufferAction(in rowInfo, allocator, in body);
+ var rowAction = new WrappingRowAction(top, bottom, verticalStep, width, allocator, in body);
Parallel.For(
0,
diff --git a/src/ImageSharp/ImageFrame{TPixel}.cs b/src/ImageSharp/ImageFrame{TPixel}.cs
index c3bab8e65..57b8a953a 100644
--- a/src/ImageSharp/ImageFrame{TPixel}.cs
+++ b/src/ImageSharp/ImageFrame{TPixel}.cs
@@ -263,7 +263,7 @@ namespace SixLabors.ImageSharp
ParallelRowIterator.IterateRows(
this.Bounds(),
configuration,
- new RowIntervalAction(this, target, configuration));
+ new RowAction(this, target, configuration));
return target;
}
@@ -289,7 +289,7 @@ namespace SixLabors.ImageSharp
///
/// A implementing the clone logic for .
///
- private readonly struct RowIntervalAction : IRowIntervalAction
+ private readonly struct RowAction : IRowAction
where TPixel2 : struct, IPixel
{
private readonly ImageFrame source;
@@ -297,7 +297,7 @@ namespace SixLabors.ImageSharp
private readonly Configuration configuration;
[MethodImpl(InliningOptions.ShortMethod)]
- public RowIntervalAction(
+ public RowAction(
ImageFrame source,
ImageFrame target,
Configuration configuration)
@@ -309,14 +309,11 @@ namespace SixLabors.ImageSharp
///
[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);
- Span targetRow = this.target.GetPixelRowSpan(y);
- PixelOperations.Instance.To(this.configuration, sourceRow, targetRow);
- }
+ Span sourceRow = this.source.GetPixelRowSpan(y);
+ Span targetRow = this.target.GetPixelRowSpan(y);
+ PixelOperations.Instance.To(this.configuration, sourceRow, targetRow);
}
}
}
diff --git a/src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor{TPixel}.cs
index 9e9dccc46..4db2b938f 100644
--- a/src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor{TPixel}.cs
@@ -4,7 +4,6 @@
using System;
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Advanced;
-using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Processing.Processors.Binarization
@@ -54,13 +53,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Binarization
ParallelRowIterator.IterateRows(
workingRect,
configuration,
- new RowIntervalAction(source, upper, lower, threshold, startX, endX, isAlphaOnly));
+ new RowAction(source, upper, lower, threshold, startX, endX, isAlphaOnly));
}
///
/// A implementing the clone logic for .
///
- private readonly struct RowIntervalAction : IRowIntervalAction
+ private readonly struct RowAction : IRowAction
{
private readonly ImageFrame source;
private readonly TPixel upper;
@@ -71,7 +70,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Binarization
private readonly bool isAlphaOnly;
[MethodImpl(InliningOptions.ShortMethod)]
- public RowIntervalAction(
+ public RowAction(
ImageFrame source,
TPixel upper,
TPixel lower,
@@ -91,22 +90,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);
- for (int x = this.startX; x < this.endX; x++)
- {
- ref TPixel color = ref row[x];
- color.ToRgba32(ref rgba);
+ Span row = this.source.GetPixelRowSpan(y);
+
+ for (int x = this.startX; x < this.endX; x++)
+ {
+ ref TPixel color = ref row[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 834120f84..05508c90f 100644
--- a/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor{TPixel}.cs
@@ -268,10 +268,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
protected override void OnFrameApply(ImageFrame source)
{
// Preliminary gamma highlight pass
- ParallelRowIterator.IterateRows(
+ ParallelRowIterator.IterateRows(
this.SourceRectangle,
this.Configuration,
- new ApplyGammaExposureRowIntervalAction(this.SourceRectangle, source.PixelBuffer, this.Configuration, this.gamma));
+ new ApplyGammaExposureRowAction(this.SourceRectangle, source.PixelBuffer, this.Configuration, this.gamma));
// Create a 0-filled buffer to use to store the result of the component convolutions
using Buffer2D processingBuffer = this.Configuration.MemoryAllocator.Allocate2D(source.Size(), AllocationOptions.Clean);
@@ -285,7 +285,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
ParallelRowIterator.IterateRows(
this.SourceRectangle,
this.Configuration,
- new ApplyInverseGammaExposureRowIntervalAction(this.SourceRectangle, source.PixelBuffer, processingBuffer, this.Configuration, inverseGamma));
+ new ApplyInverseGammaExposureRowAction(this.SourceRectangle, source.PixelBuffer, processingBuffer, this.Configuration, inverseGamma));
}
///
@@ -317,20 +317,20 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
ParallelRowIterator.IterateRows(
sourceRectangle,
configuration,
- new ApplyVerticalConvolutionRowIntervalAction(ref sourceRectangle, firstPassBuffer, source.PixelBuffer, kernel));
+ new ApplyVerticalConvolutionRowAction(ref sourceRectangle, firstPassBuffer, source.PixelBuffer, kernel));
// Compute the horizontal 1D convolutions and accumulate the partial results on the target buffer
ParallelRowIterator.IterateRows(
sourceRectangle,
configuration,
- new ApplyHorizontalConvolutionRowIntervalAction(ref sourceRectangle, processingBuffer, firstPassBuffer, kernel, parameters.Z, parameters.W));
+ new ApplyHorizontalConvolutionRowAction(ref sourceRectangle, processingBuffer, firstPassBuffer, kernel, parameters.Z, parameters.W));
}
}
///
/// A implementing the vertical convolution logic for .
///
- private readonly struct ApplyVerticalConvolutionRowIntervalAction : IRowIntervalAction
+ private readonly struct ApplyVerticalConvolutionRowAction : IRowAction
{
private readonly Rectangle bounds;
private readonly Buffer2D targetValues;
@@ -340,7 +340,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
private readonly int maxX;
[MethodImpl(InliningOptions.ShortMethod)]
- public ApplyVerticalConvolutionRowIntervalAction(
+ public ApplyVerticalConvolutionRowAction(
ref Rectangle bounds,
Buffer2D targetValues,
Buffer2D sourcePixels,
@@ -356,16 +356,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);
}
}
}
@@ -373,7 +370,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
///
/// A implementing the horizontal convolution logic for .
///
- private readonly struct ApplyHorizontalConvolutionRowIntervalAction : IRowIntervalAction
+ private readonly struct ApplyHorizontalConvolutionRowAction : IRowAction
{
private readonly Rectangle bounds;
private readonly Buffer2D targetValues;
@@ -385,7 +382,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
private readonly int maxX;
[MethodImpl(InliningOptions.ShortMethod)]
- public ApplyHorizontalConvolutionRowIntervalAction(
+ public ApplyHorizontalConvolutionRowAction(
ref Rectangle bounds,
Buffer2D targetValues,
Buffer2D sourceValues,
@@ -405,16 +402,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);
}
}
}
@@ -422,7 +416,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
///
/// A implementing the gamma exposure logic for .
///
- private readonly struct ApplyGammaExposureRowIntervalAction : IRowIntervalAction
+ private readonly struct ApplyGammaExposureRowAction : IRowAction
{
private readonly Rectangle bounds;
private readonly Buffer2D targetPixels;
@@ -430,7 +424,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
private readonly float gamma;
[MethodImpl(InliningOptions.ShortMethod)]
- public ApplyGammaExposureRowIntervalAction(
+ public ApplyGammaExposureRowAction(
Rectangle bounds,
Buffer2D targetPixels,
Configuration configuration,
@@ -444,34 +438,30 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
///
[MethodImpl(InliningOptions.ShortMethod)]
- public void Invoke(in RowInterval rows, Memory memory)
+ public void Invoke(int y, 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);
+ int length = span.Length;
- 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);
- }
+ Span targetRowSpan = this.targetPixels.GetRowSpan(y).Slice(this.bounds.X);
+ PixelOperations.Instance.ToVector4(this.configuration, targetRowSpan.Slice(0, length), span, PixelConversionModifiers.Premultiply);
+ ref Vector4 baseRef = ref MemoryMarshal.GetReference(span);
- PixelOperations.Instance.FromVector4Destructive(this.configuration, vectorSpan.Slice(0, length), targetRowSpan);
+ 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.Slice(0, length), targetRowSpan);
}
}
///
/// A implementing the inverse gamma exposure logic for .
///
- private readonly struct ApplyInverseGammaExposureRowIntervalAction : IRowIntervalAction
+ private readonly struct ApplyInverseGammaExposureRowAction : IRowAction
{
private readonly Rectangle bounds;
private readonly Buffer2D targetPixels;
@@ -480,7 +470,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
private readonly float inverseGamma;
[MethodImpl(InliningOptions.ShortMethod)]
- public ApplyInverseGammaExposureRowIntervalAction(
+ public ApplyInverseGammaExposureRowAction(
Rectangle bounds,
Buffer2D targetPixels,
Buffer2D sourceValues,
@@ -496,28 +486,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++)
- {
- 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);
- }
+ 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);
- PixelOperations.Instance.FromVector4Destructive(this.configuration, sourceRowSpan.Slice(0, this.bounds.Width), targetPixelSpan, PixelConversionModifiers.Premultiply);
+ 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);
}
}
}
diff --git a/src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor{TPixel}.cs
index cd550a335..a6d47fa58 100644
--- a/src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor{TPixel}.cs
@@ -66,10 +66,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
var interest = Rectangle.Intersect(this.SourceRectangle, source.Bounds());
- ParallelRowIterator.IterateRows(
+ ParallelRowIterator.IterateRows(
interest,
this.Configuration,
- new RowIntervalAction(interest, targetPixels, source.PixelBuffer, this.KernelY, this.KernelX, this.Configuration, this.PreserveAlpha));
+ new RowAction(interest, targetPixels, source.PixelBuffer, this.KernelY, this.KernelX, this.Configuration, this.PreserveAlpha));
Buffer2D.SwapOrCopyContent(source.PixelBuffer, targetPixels);
}
@@ -77,7 +77,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
///
/// A implementing the convolution logic for .
///
- private readonly struct RowIntervalAction : IRowIntervalAction
+ private readonly struct RowAction : IRowAction
{
private readonly Rectangle bounds;
private readonly int maxY;
@@ -90,7 +90,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
private readonly bool preserveAlpha;
[MethodImpl(InliningOptions.ShortMethod)]
- public RowIntervalAction(
+ public RowAction(
Rectangle bounds,
Buffer2D targetPixels,
Buffer2D sourcePixels,
@@ -112,54 +112,50 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
///
[MethodImpl(InliningOptions.ShortMethod)]
- public void Invoke(in RowInterval rows, Memory memory)
+ public void Invoke(int y, Span span)
{
- Span vectorSpan = memory.Span;
- int length = vectorSpan.Length;
- ref Vector4 vectorSpanRef = ref MemoryMarshal.GetReference(vectorSpan);
+ int length = span.Length;
+ ref Vector4 vectorSpanRef = 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);
+ Span targetRowSpan = this.targetPixels.GetRowSpan(y).Slice(this.bounds.X);
+ PixelOperations.Instance.ToVector4(this.configuration, targetRowSpan.Slice(0, 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.Convolve2D3(
- in this.kernelY,
- in this.kernelX,
- this.sourcePixels,
- ref vectorSpanRef,
- y,
- x,
- this.bounds.Y,
- this.maxY,
- this.bounds.X,
- this.maxX);
- }
+ DenseMatrixUtils.Convolve2D3(
+ in this.kernelY,
+ in this.kernelX,
+ this.sourcePixels,
+ ref vectorSpanRef,
+ 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 vectorSpanRef,
- y,
- x,
- this.bounds.Y,
- this.maxY,
- this.bounds.X,
- this.maxX);
- }
+ DenseMatrixUtils.Convolve2D4(
+ in this.kernelY,
+ in this.kernelX,
+ this.sourcePixels,
+ ref vectorSpanRef,
+ y,
+ x,
+ this.bounds.Y,
+ this.maxY,
+ this.bounds.X,
+ this.maxX);
}
-
- 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 1be97a4f8..1c6ca8b92 100644
--- a/src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor{TPixel}.cs
@@ -64,22 +64,22 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
var interest = Rectangle.Intersect(this.SourceRectangle, source.Bounds());
// Horizontal convolution
- ParallelRowIterator.IterateRows(
+ ParallelRowIterator.IterateRows(
interest,
this.Configuration,
- new RowIntervalAction(interest, firstPassPixels, source.PixelBuffer, this.KernelX, this.Configuration, this.PreserveAlpha));
+ new RowAction(interest, firstPassPixels, source.PixelBuffer, this.KernelX, this.Configuration, this.PreserveAlpha));
// Vertical convolution
- ParallelRowIterator.IterateRows(
+ ParallelRowIterator.IterateRows(
interest,
this.Configuration,
- new RowIntervalAction(interest, source.PixelBuffer, firstPassPixels, this.KernelY, this.Configuration, this.PreserveAlpha));
+ new RowAction(interest, source.PixelBuffer, firstPassPixels, this.KernelY, this.Configuration, this.PreserveAlpha));
}
///
/// A implementing the convolution logic for .
///
- private readonly struct RowIntervalAction : IRowIntervalAction
+ private readonly struct RowAction : IRowAction
{
private readonly Rectangle bounds;
private readonly Buffer2D targetPixels;
@@ -89,7 +89,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
private readonly bool preserveAlpha;
[MethodImpl(InliningOptions.ShortMethod)]
- public RowIntervalAction(
+ public RowAction(
Rectangle bounds,
Buffer2D targetPixels,
Buffer2D sourcePixels,
@@ -107,55 +107,51 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
///
[MethodImpl(InliningOptions.ShortMethod)]
- public void Invoke(in RowInterval rows, Memory memory)
+ public void Invoke(int y, Span span)
{
- Span vectorSpan = memory.Span;
- int length = vectorSpan.Length;
- ref Vector4 vectorSpanRef = ref MemoryMarshal.GetReference(vectorSpan);
+ int length = span.Length;
+ ref Vector4 vectorSpanRef = 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, length), vectorSpan);
+ Span targetRowSpan = this.targetPixels.GetRowSpan(y).Slice(this.bounds.X);
+ PixelOperations.Instance.ToVector4(this.configuration, targetRowSpan.Slice(0, 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 vectorSpanRef,
- y,
- x,
- this.bounds.Y,
- maxY,
- this.bounds.X,
- maxX);
- }
+ DenseMatrixUtils.Convolve3(
+ in this.kernel,
+ this.sourcePixels,
+ ref vectorSpanRef,
+ 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 vectorSpanRef,
- y,
- x,
- this.bounds.Y,
- maxY,
- this.bounds.X,
- maxX);
- }
+ DenseMatrixUtils.Convolve4(
+ in this.kernel,
+ this.sourcePixels,
+ ref vectorSpanRef,
+ y,
+ x,
+ this.bounds.Y,
+ maxY,
+ this.bounds.X,
+ maxX);
}
-
- 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 b68dc56e0..6a2acf770 100644
--- a/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor{TPixel}.cs
@@ -57,10 +57,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
var interest = Rectangle.Intersect(this.SourceRectangle, source.Bounds());
- ParallelRowIterator.IterateRows(
+ ParallelRowIterator.IterateRows(
interest,
this.Configuration,
- new RowIntervalAction(interest, targetPixels, source.PixelBuffer, this.KernelXY, this.Configuration, this.PreserveAlpha));
+ new RowAction(interest, targetPixels, source.PixelBuffer, this.KernelXY, this.Configuration, this.PreserveAlpha));
Buffer2D.SwapOrCopyContent(source.PixelBuffer, targetPixels);
}
@@ -68,7 +68,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
///
/// A implementing the convolution logic for .
///
- private readonly struct RowIntervalAction : IRowIntervalAction
+ private readonly struct RowAction : IRowAction
{
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 RowIntervalAction(
+ public RowAction(
Rectangle bounds,
Buffer2D targetPixels,
Buffer2D sourcePixels,
@@ -100,52 +100,48 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
///
[MethodImpl(InliningOptions.ShortMethod)]
- public void Invoke(in RowInterval rows, Memory memory)
+ public void Invoke(int y, Span span)
{
- Span vectorSpan = memory.Span;
- int length = vectorSpan.Length;
- ref Vector4 vectorSpanRef = ref MemoryMarshal.GetReference(vectorSpan);
+ int length = span.Length;
+ ref Vector4 vectorSpanRef = 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);
+ Span targetRowSpan = this.targetPixels.GetRowSpan(y).Slice(this.bounds.X);
+ PixelOperations.Instance.ToVector4(this.configuration, targetRowSpan.Slice(0, 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 vectorSpanRef,
- y,
- x,
- this.bounds.Y,
- this.maxY,
- this.bounds.X,
- this.maxX);
- }
+ DenseMatrixUtils.Convolve3(
+ in this.kernel,
+ this.sourcePixels,
+ ref vectorSpanRef,
+ 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 vectorSpanRef,
- y,
- x,
- this.bounds.Y,
- this.maxY,
- this.bounds.X,
- this.maxX);
- }
+ DenseMatrixUtils.Convolve4(
+ in this.kernel,
+ this.sourcePixels,
+ ref vectorSpanRef,
+ y,
+ x,
+ this.bounds.Y,
+ this.maxY,
+ this.bounds.X,
+ this.maxX);
}
-
- PixelOperations.Instance.FromVector4Destructive(this.configuration, vectorSpan, 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 e2480957e..85736cbd9 100644
--- a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorCompassProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorCompassProcessor{TPixel}.cs
@@ -105,14 +105,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
ParallelRowIterator.IterateRows(
Rectangle.FromLTRB(minX, minY, maxX, maxY),
this.Configuration,
- new RowIntervalAction(source.PixelBuffer, pass.PixelBuffer, minX, maxX, shiftY, shiftX));
+ new RowAction(source.PixelBuffer, pass.PixelBuffer, minX, maxX, shiftY, shiftX));
}
}
///
/// A implementing the convolution logic for .
///
- private readonly struct RowIntervalAction : IRowIntervalAction
+ private readonly struct RowAction : IRowAction
{
private readonly Buffer2D targetPixels;
private readonly Buffer2D passPixels;
@@ -122,7 +122,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
private readonly int shiftX;
[MethodImpl(InliningOptions.ShortMethod)]
- public RowIntervalAction(
+ public RowAction(
Buffer2D targetPixels,
Buffer2D passPixels,
int minX,
@@ -140,29 +140,26 @@ 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++)
- {
- int offsetY = y - this.shiftY;
+ int offsetY = y - this.shiftY;
- ref TPixel passPixelsBase = ref MemoryMarshal.GetReference(this.passPixels.GetRowSpan(offsetY));
- ref TPixel targetPixelsBase = ref MemoryMarshal.GetReference(this.targetPixels.GetRowSpan(offsetY));
+ ref TPixel passPixelsBase = ref MemoryMarshal.GetReference(this.passPixels.GetRowSpan(offsetY));
+ ref TPixel targetPixelsBase = ref MemoryMarshal.GetReference(this.targetPixels.GetRowSpan(offsetY));
- for (int x = this.minX; x < this.maxX; x++)
- {
- int offsetX = x - this.shiftX;
+ for (int x = this.minX; x < this.maxX; x++)
+ {
+ int offsetX = x - this.shiftX;
- // Grab the max components of the two pixels
- ref TPixel currentPassPixel = ref Unsafe.Add(ref passPixelsBase, offsetX);
- ref TPixel currentTargetPixel = ref Unsafe.Add(ref targetPixelsBase, offsetX);
+ // Grab the max components of the two pixels
+ ref TPixel currentPassPixel = ref Unsafe.Add(ref passPixelsBase, offsetX);
+ ref TPixel currentTargetPixel = ref Unsafe.Add(ref targetPixelsBase, offsetX);
- 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/Drawing/DrawImageProcessor{TPixelBg,TPixelFg}.cs b/src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor{TPixelBg,TPixelFg}.cs
index 2a181174c..a12bcb1fd 100644
--- a/src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor{TPixelBg,TPixelFg}.cs
+++ b/src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor{TPixelBg,TPixelFg}.cs
@@ -4,7 +4,6 @@
using System;
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Advanced;
-using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Processing.Processors.Drawing
@@ -102,13 +101,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing
ParallelRowIterator.IterateRows(
workingRect,
configuration,
- new RowIntervalAction(source, targetImage, blender, configuration, minX, width, locationY, targetX, this.Opacity));
+ new RowAction(source, targetImage, blender, configuration, minX, width, locationY, targetX, this.Opacity));
}
///
/// A implementing the draw logic for .
///
- private readonly struct RowIntervalAction : IRowIntervalAction
+ private readonly struct RowAction : IRowAction
{
private readonly ImageFrame sourceFrame;
private readonly Image targetImage;
@@ -121,7 +120,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing
private readonly float opacity;
[MethodImpl(InliningOptions.ShortMethod)]
- public RowIntervalAction(
+ public RowAction(
ImageFrame sourceFrame,
Image targetImage,
PixelBlender blender,
@@ -145,14 +144,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 4abaf7ac4..45f221c93 100644
--- a/src/ImageSharp/Processing/Processors/Effects/OilPaintingProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Effects/OilPaintingProcessor{TPixel}.cs
@@ -50,7 +50,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Effects
ParallelRowIterator.IterateRows(
this.SourceRectangle,
this.Configuration,
- new RowIntervalAction(this.SourceRectangle, targetPixels, source, this.Configuration, brushSize >> 1, this.definition.Levels));
+ new RowAction(this.SourceRectangle, targetPixels, source, this.Configuration, brushSize >> 1, this.definition.Levels));
Buffer2D.SwapOrCopyContent(source.PixelBuffer, targetPixels);
}
@@ -58,7 +58,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Effects
///
/// A implementing the convolution logic for .
///
- private readonly struct RowIntervalAction : IRowIntervalAction
+ private readonly struct RowAction : IRowAction
{
private readonly Rectangle bounds;
private readonly Buffer2D targetPixels;
@@ -68,7 +68,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Effects
private readonly int levels;
[MethodImpl(InliningOptions.ShortMethod)]
- public RowIntervalAction(
+ public RowAction(
Rectangle bounds,
Buffer2D targetPixels,
ImageFrame source,
@@ -86,7 +86,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Effects
///
[MethodImpl(InliningOptions.ShortMethod)]
- public void Invoke(in RowInterval rows)
+ public void Invoke(int y)
{
int maxY = this.bounds.Bottom - 1;
int maxX = this.bounds.Right - 1;
@@ -117,69 +117,66 @@ namespace SixLabors.ImageSharp.Processing.Processors.Effects
ref float blueBinRef = ref Unsafe.Add(ref redBinRef, this.levels);
ref float greenBinRef = ref Unsafe.Add(ref blueBinRef, this.levels);
- for (int y = rows.Min; y < rows.Max; y++)
- {
- Span sourceRowPixelSpan = this.source.GetPixelRowSpan(y);
- Span sourceRowAreaPixelSpan = sourceRowPixelSpan.Slice(this.bounds.X, this.bounds.Width);
+ Span sourceRowPixelSpan = this.source.GetPixelRowSpan(y);
+ Span sourceRowAreaPixelSpan = sourceRowPixelSpan.Slice(this.bounds.X, this.bounds.Width);
- PixelOperations.Instance.ToVector4(this.configuration, sourceRowAreaPixelSpan, sourceRowAreaVector4Span);
+ PixelOperations.Instance.ToVector4(this.configuration, sourceRowAreaPixelSpan, sourceRowAreaVector4Span);
- for (int x = this.bounds.X; x < this.bounds.Right; x++)
- {
- int maxIntensity = 0;
- int maxIndex = 0;
+ for (int x = this.bounds.X; x < this.bounds.Right; x++)
+ {
+ int maxIntensity = 0;
+ int maxIndex = 0;
- // Clear the current shared buffer before processing each target pixel
- bins.Memory.Span.Clear();
+ // Clear the current shared buffer before processing each target pixel
+ bins.Memory.Span.Clear();
- for (int fy = 0; fy <= this.radius; fy++)
- {
- int fyr = fy - this.radius;
- int offsetY = y + fyr;
+ for (int fy = 0; fy <= this.radius; fy++)
+ {
+ int fyr = fy - this.radius;
+ int offsetY = y + fyr;
- offsetY = offsetY.Clamp(0, maxY);
+ offsetY = offsetY.Clamp(0, maxY);
- Span sourceOffsetRow = this.source.GetPixelRowSpan(offsetY);
+ Span sourceOffsetRow = this.source.GetPixelRowSpan(offsetY);
- for (int fx = 0; fx <= this.radius; fx++)
- {
- int fxr = fx - this.radius;
- int offsetX = x + fxr;
- offsetX = offsetX.Clamp(0, maxX);
+ for (int fx = 0; fx <= this.radius; fx++)
+ {
+ int fxr = fx - this.radius;
+ int offsetX = x + fxr;
+ offsetX = offsetX.Clamp(0, maxX);
- var vector = sourceOffsetRow[offsetX].ToVector4();
+ var vector = sourceOffsetRow[offsetX].ToVector4();
- float sourceRed = vector.X;
- float sourceBlue = vector.Z;
- float sourceGreen = vector.Y;
+ float sourceRed = vector.X;
+ float sourceBlue = vector.Z;
+ float sourceGreen = vector.Y;
- int currentIntensity = (int)MathF.Round((sourceBlue + sourceGreen + sourceRed) / 3F * (this.levels - 1));
+ int currentIntensity = (int)MathF.Round((sourceBlue + sourceGreen + sourceRed) / 3F * (this.levels - 1));
- Unsafe.Add(ref intensityBinRef, currentIntensity)++;
- Unsafe.Add(ref redBinRef, currentIntensity) += sourceRed;
- Unsafe.Add(ref blueBinRef, currentIntensity) += sourceBlue;
- Unsafe.Add(ref greenBinRef, currentIntensity) += sourceGreen;
+ Unsafe.Add(ref intensityBinRef, currentIntensity)++;
+ Unsafe.Add(ref redBinRef, currentIntensity) += sourceRed;
+ Unsafe.Add(ref blueBinRef, currentIntensity) += sourceBlue;
+ Unsafe.Add(ref greenBinRef, currentIntensity) += sourceGreen;
- if (Unsafe.Add(ref intensityBinRef, currentIntensity) > maxIntensity)
- {
- maxIntensity = Unsafe.Add(ref intensityBinRef, currentIntensity);
- maxIndex = currentIntensity;
- }
+ if (Unsafe.Add(ref intensityBinRef, currentIntensity) > maxIntensity)
+ {
+ maxIntensity = Unsafe.Add(ref intensityBinRef, currentIntensity);
+ maxIndex = currentIntensity;
}
+ }
- float red = MathF.Abs(Unsafe.Add(ref redBinRef, maxIndex) / maxIntensity);
- float blue = MathF.Abs(Unsafe.Add(ref blueBinRef, maxIndex) / maxIntensity);
- float green = MathF.Abs(Unsafe.Add(ref greenBinRef, maxIndex) / maxIntensity);
- float alpha = sourceRowVector4Span[x].W;
+ float red = MathF.Abs(Unsafe.Add(ref redBinRef, maxIndex) / maxIntensity);
+ float blue = MathF.Abs(Unsafe.Add(ref blueBinRef, maxIndex) / maxIntensity);
+ float green = MathF.Abs(Unsafe.Add(ref greenBinRef, maxIndex) / maxIntensity);
+ float alpha = sourceRowVector4Span[x].W;
- targetRowVector4Span[x] = new Vector4(red, green, blue, alpha);
- }
+ targetRowVector4Span[x] = new Vector4(red, green, blue, alpha);
}
+ }
- Span targetRowAreaPixelSpan = this.targetPixels.GetRowSpan(y).Slice(this.bounds.X, this.bounds.Width);
+ Span targetRowAreaPixelSpan = this.targetPixels.GetRowSpan(y).Slice(this.bounds.X, this.bounds.Width);
- PixelOperations.Instance.FromVector4Destructive(this.configuration, targetRowAreaVector4Span, targetRowAreaPixelSpan);
- }
+ PixelOperations.Instance.FromVector4Destructive(this.configuration, targetRowAreaVector4Span, targetRowAreaPixelSpan);
}
}
}
diff --git a/src/ImageSharp/Processing/Processors/Effects/PixelRowDelegateProcessor{TPixel,TDelegate}.cs b/src/ImageSharp/Processing/Processors/Effects/PixelRowDelegateProcessor{TPixel,TDelegate}.cs
index fd725d3ba..c0f479756 100644
--- a/src/ImageSharp/Processing/Processors/Effects/PixelRowDelegateProcessor{TPixel,TDelegate}.cs
+++ b/src/ImageSharp/Processing/Processors/Effects/PixelRowDelegateProcessor{TPixel,TDelegate}.cs
@@ -5,7 +5,6 @@ using System;
using System.Numerics;
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Advanced;
-using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Processing.Processors.Effects
@@ -51,16 +50,16 @@ namespace SixLabors.ImageSharp.Processing.Processors.Effects
{
var interest = Rectangle.Intersect(this.SourceRectangle, source.Bounds());
- ParallelRowIterator.IterateRows(
+ ParallelRowIterator.IterateRows(
interest,
this.Configuration,
- new RowIntervalAction(interest.X, source, this.Configuration, this.modifiers, this.rowDelegate));
+ new RowAction(interest.X, source, this.Configuration, this.modifiers, this.rowDelegate));
}
///
/// A implementing the convolution logic for .
///
- private readonly struct RowIntervalAction : IRowIntervalAction
+ private readonly struct RowAction : IRowAction
{
private readonly int startX;
private readonly ImageFrame source;
@@ -69,7 +68,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Effects
private readonly TDelegate rowProcessor;
[MethodImpl(InliningOptions.ShortMethod)]
- public RowIntervalAction(
+ public RowAction(
int startX,
ImageFrame source,
Configuration configuration,
@@ -85,20 +84,16 @@ namespace SixLabors.ImageSharp.Processing.Processors.Effects
///
[MethodImpl(InliningOptions.ShortMethod)]
- public void Invoke(in RowInterval rows, Memory memory)
+ public void Invoke(int y, 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);
+ int length = span.Length;
+ Span rowSpan = this.source.GetPixelRowSpan(y).Slice(this.startX, 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));
+ // 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, 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 cdb67e48b..c797c1358 100644
--- a/src/ImageSharp/Processing/Processors/Filters/FilterProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Filters/FilterProcessor{TPixel}.cs
@@ -5,7 +5,6 @@ using System;
using System.Numerics;
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Advanced;
-using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Processing.Processors.Filters
@@ -37,16 +36,16 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters
{
var interest = Rectangle.Intersect(this.SourceRectangle, source.Bounds());
- ParallelRowIterator.IterateRows(
+ ParallelRowIterator.IterateRows(
interest,
this.Configuration,
- new RowIntervalAction(interest.X, source, this.definition.Matrix, this.Configuration));
+ new RowAction(interest.X, source, this.definition.Matrix, this.Configuration));
}
///
/// A implementing the convolution logic for .
///
- private readonly struct RowIntervalAction : IRowIntervalAction
+ private readonly struct RowAction : IRowAction
{
private readonly int startX;
private readonly ImageFrame source;
@@ -54,7 +53,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters
private readonly Configuration configuration;
[MethodImpl(InliningOptions.ShortMethod)]
- public RowIntervalAction(
+ public RowAction(
int startX,
ImageFrame source,
ColorMatrix matrix,
@@ -68,19 +67,15 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters
///
[MethodImpl(InliningOptions.ShortMethod)]
- public void Invoke(in RowInterval rows, Memory memory)
+ public void Invoke(int y, 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);
+ int length = span.Length;
+ Span rowSpan = this.source.GetPixelRowSpan(y).Slice(this.startX, 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/Normalization/GlobalHistogramEqualizationProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Normalization/GlobalHistogramEqualizationProcessor{TPixel}.cs
index 5d25bae82..a4a643425 100644
--- a/src/ImageSharp/Processing/Processors/Normalization/GlobalHistogramEqualizationProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Normalization/GlobalHistogramEqualizationProcessor{TPixel}.cs
@@ -55,7 +55,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization
ParallelRowIterator.IterateRows(
workingRect,
this.Configuration,
- new GrayscaleLevelsRowIntervalAction(workingRect, histogramBuffer, source, this.LuminanceLevels));
+ new GrayscaleLevelsRowAction(workingRect, histogramBuffer, source, this.LuminanceLevels));
Span histogram = histogramBuffer.GetSpan();
if (this.ClipHistogramEnabled)
@@ -77,13 +77,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization
ParallelRowIterator.IterateRows(
workingRect,
this.Configuration,
- new CdfApplicationRowIntervalAction(workingRect, cdfBuffer, source, this.LuminanceLevels, numberOfPixelsMinusCdfMin));
+ new CdfApplicationRowAction(workingRect, cdfBuffer, source, this.LuminanceLevels, numberOfPixelsMinusCdfMin));
}
///
/// A implementing the grayscale levels logic for .
///
- private readonly struct GrayscaleLevelsRowIntervalAction : IRowIntervalAction
+ private readonly struct GrayscaleLevelsRowAction : IRowAction
{
private readonly Rectangle bounds;
private readonly IMemoryOwner histogramBuffer;
@@ -91,7 +91,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization
private readonly int luminanceLevels;
[MethodImpl(InliningOptions.ShortMethod)]
- public GrayscaleLevelsRowIntervalAction(
+ public GrayscaleLevelsRowAction(
in Rectangle bounds,
IMemoryOwner histogramBuffer,
ImageFrame source,
@@ -105,18 +105,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)++;
}
}
}
@@ -124,7 +121,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization
///
/// A implementing the cdf application levels logic for .
///
- private readonly struct CdfApplicationRowIntervalAction : IRowIntervalAction
+ private readonly struct CdfApplicationRowAction : IRowAction
{
private readonly Rectangle bounds;
private readonly IMemoryOwner cdfBuffer;
@@ -133,7 +130,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization
private readonly float numberOfPixelsMinusCdfMin;
[MethodImpl(InliningOptions.ShortMethod)]
- public CdfApplicationRowIntervalAction(
+ public CdfApplicationRowAction(
in Rectangle bounds,
IMemoryOwner cdfBuffer,
ImageFrame source,
@@ -149,20 +146,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 a9b91e837..2c17d71c6 100644
--- a/src/ImageSharp/Processing/Processors/Overlays/BackgroundColorProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Overlays/BackgroundColorProcessor{TPixel}.cs
@@ -52,10 +52,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays
ParallelRowIterator.IterateRows(
interest,
configuration,
- new RowIntervalAction(configuration, interest, blender, amount, colors, source));
+ new RowAction(configuration, interest, blender, amount, colors, source));
}
- private readonly struct RowIntervalAction : IRowIntervalAction
+ private readonly struct RowAction : IRowAction
{
private readonly Configuration configuration;
private readonly Rectangle bounds;
@@ -65,7 +65,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays
private readonly ImageFrame source;
[MethodImpl(InliningOptions.ShortMethod)]
- public RowIntervalAction(
+ public RowAction(
Configuration configuration,
Rectangle bounds,
PixelBlender blender,
@@ -82,23 +82,18 @@ 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 65a87fbf0..6777e3234 100644
--- a/src/ImageSharp/Processing/Processors/Overlays/GlowProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Overlays/GlowProcessor{TPixel}.cs
@@ -55,13 +55,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays
using IMemoryOwner rowColors = allocator.Allocate(interest.Width);
rowColors.GetSpan().Fill(glowColor);
- ParallelRowIterator.IterateRows(
+ ParallelRowIterator.IterateRows(
interest,
configuration,
- new RowIntervalAction(configuration, interest, rowColors, this.blender, center, maxDistance, blendPercent, source));
+ new RowAction(configuration, interest, rowColors, this.blender, center, maxDistance, blendPercent, source));
}
- private readonly struct RowIntervalAction : IRowIntervalAction
+ private readonly struct RowAction : IRowAction
{
private readonly Configuration configuration;
private readonly Rectangle bounds;
@@ -73,7 +73,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays
private readonly ImageFrame source;
[MethodImpl(InliningOptions.ShortMethod)]
- public RowIntervalAction(
+ public RowAction(
Configuration configuration,
Rectangle bounds,
IMemoryOwner colors,
@@ -94,28 +94,24 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays
}
[MethodImpl(InliningOptions.ShortMethod)]
- public void Invoke(in RowInterval rows, Memory memory)
+ public void Invoke(int y, Span span)
{
- Span amountsSpan = memory.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));
- amountsSpan[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,
- amountsSpan);
- }
+ 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 11887433c..6e2c3c442 100644
--- a/src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor{TPixel}.cs
@@ -63,13 +63,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays
using IMemoryOwner rowColors = allocator.Allocate(interest.Width);
rowColors.GetSpan().Fill(vignetteColor);
- ParallelRowIterator.IterateRows(
+ ParallelRowIterator.IterateRows(
interest,
configuration,
- new RowIntervalAction(configuration, interest, rowColors, this.blender, center, maxDistance, blendPercent, source));
+ new RowAction(configuration, interest, rowColors, this.blender, center, maxDistance, blendPercent, source));
}
- private readonly struct RowIntervalAction : IRowIntervalAction
+ private readonly struct RowAction : IRowAction
{
private readonly Configuration configuration;
private readonly Rectangle bounds;
@@ -81,7 +81,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays
private readonly ImageFrame source;
[MethodImpl(InliningOptions.ShortMethod)]
- public RowIntervalAction(
+ public RowAction(
Configuration configuration,
Rectangle bounds,
IMemoryOwner colors,
@@ -102,28 +102,24 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays
}
[MethodImpl(InliningOptions.ShortMethod)]
- public void Invoke(in RowInterval rows, Memory memory)
+ public void Invoke(int y, Span span)
{
- Span amountsSpan = memory.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));
- amountsSpan[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,
- amountsSpan);
+ 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/Transforms/AffineTransformProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor{TPixel}.cs
index 402a05249..447a99eec 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor{TPixel}.cs
@@ -5,7 +5,6 @@ using System;
using System.Numerics;
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Advanced;
-using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Processing.Processors.Transforms
@@ -61,23 +60,23 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
ParallelRowIterator.IterateRows(
targetBounds,
configuration,
- new NearestNeighborRowIntervalAction(this.SourceRectangle, ref matrix, width, source, destination));
+ new NearestNeighborRowAction(this.SourceRectangle, ref matrix, width, source, destination));
return;
}
using var kernelMap = new TransformKernelMap(configuration, source.Size(), destination.Size(), this.resampler);
- ParallelRowIterator.IterateRows(
+ ParallelRowIterator.IterateRows(
targetBounds,
configuration,
- new RowIntervalAction(configuration, kernelMap, ref matrix, width, source, destination));
+ new RowAction(configuration, kernelMap, ref matrix, width, source, destination));
}
///
/// A implementing the nearest neighbor resampler logic for .
///
- private readonly struct NearestNeighborRowIntervalAction : IRowIntervalAction
+ private readonly struct NearestNeighborRowAction : IRowAction
{
private readonly Rectangle bounds;
private readonly Matrix3x2 matrix;
@@ -86,7 +85,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
private readonly ImageFrame destination;
[MethodImpl(InliningOptions.ShortMethod)]
- public NearestNeighborRowIntervalAction(
+ public NearestNeighborRowAction(
Rectangle bounds,
ref Matrix3x2 matrix,
int maxX,
@@ -101,21 +100,17 @@ 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);
+ Span destRow = this.destination.GetPixelRowSpan(y);
- for (int x = 0; x < this.maxX; x++)
+ for (int x = 0; x < this.maxX; x++)
+ {
+ var point = Point.Transform(new Point(x, y), this.matrix);
+ if (this.bounds.Contains(point.X, point.Y))
{
- var point = Point.Transform(new Point(x, y), this.matrix);
- if (this.bounds.Contains(point.X, point.Y))
- {
- destRow[x] = this.source[point.X, point.Y];
- }
+ destRow[x] = this.source[point.X, point.Y];
}
}
}
@@ -124,7 +119,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
///
/// A implementing the transformation logic for .
///
- private readonly struct RowIntervalAction : IRowIntervalAction
+ private readonly struct RowAction : IRowAction
{
private readonly Configuration configuration;
private readonly TransformKernelMap kernelMap;
@@ -134,7 +129,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
private readonly ImageFrame destination;
[MethodImpl(InliningOptions.ShortMethod)]
- public RowIntervalAction(
+ public RowAction(
Configuration configuration,
TransformKernelMap kernelMap,
ref Matrix3x2 matrix,
@@ -152,35 +147,31 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
///
[MethodImpl(InliningOptions.ShortMethod)]
- public void Invoke(in RowInterval rows, Memory memory)
+ public void Invoke(int y, 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);
- ref float ySpanRef = ref this.kernelMap.GetYStartReference(y);
- ref float xSpanRef = ref this.kernelMap.GetXStartReference(y);
-
- 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);
- this.kernelMap.Convolve(
- point,
- x,
- ref ySpanRef,
- ref xSpanRef,
- this.source.PixelBuffer,
- vectorSpan);
- }
+ Span targetRowSpan = this.destination.GetPixelRowSpan(y);
+ PixelOperations.Instance.ToVector4(this.configuration, targetRowSpan, span);
+ ref float ySpanRef = ref this.kernelMap.GetYStartReference(y);
+ ref float xSpanRef = ref this.kernelMap.GetXStartReference(y);
- PixelOperations.Instance.FromVector4Destructive(
- this.configuration,
- vectorSpan,
- targetRowSpan);
+ 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);
+ this.kernelMap.Convolve(
+ point,
+ x,
+ ref ySpanRef,
+ ref xSpanRef,
+ this.source.PixelBuffer,
+ span);
}
+
+ PixelOperations.Instance.FromVector4Destructive(
+ this.configuration,
+ span,
+ targetRowSpan);
}
}
}
diff --git a/src/ImageSharp/Processing/Processors/Transforms/CropProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/CropProcessor{TPixel}.cs
index 103c5d3ff..b294ef465 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/CropProcessor{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/CropProcessor{TPixel}.cs
@@ -4,7 +4,6 @@
using System;
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Advanced;
-using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Processing.Processors.Transforms
@@ -48,34 +47,25 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
Rectangle bounds = this.cropRectangle;
// Copying is cheap, we should process more pixels per task:
- ParallelExecutionSettings parallelSettings =
- ParallelExecutionSettings.FromConfiguration(this.Configuration).MultiplyMinimumPixelsPerTask(4);
-
- var rowAction = new RowIntervalAction(ref bounds, source, destination);
+ ParallelExecutionSettings parallelSettings = ParallelExecutionSettings.FromConfiguration(this.Configuration).MultiplyMinimumPixelsPerTask(4);
ParallelRowIterator.IterateRows(
bounds,
in parallelSettings,
- in rowAction);
+ new RowAction(ref bounds, source, destination));
}
///
/// A implementing the processor logic for .
///
- private readonly struct RowIntervalAction : IRowIntervalAction
+ private readonly struct RowAction : IRowAction
{
private readonly Rectangle bounds;
private readonly ImageFrame source;
private readonly ImageFrame destination;
- ///
- /// 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 RowIntervalAction(ref Rectangle bounds, ImageFrame source, ImageFrame destination)
+ public RowAction(ref Rectangle bounds, ImageFrame source, ImageFrame destination)
{
this.bounds = bounds;
this.source = source;
@@ -84,14 +74,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