Browse Source

Update AdaptiveHistogramEqualizationProcessor and rename interfaces

af/octree-no-pixelmap
James Jackson-South 6 years ago
parent
commit
e2e47a0ecf
  1. 18
      src/ImageSharp/Advanced/IRowIntervalOperation.cs
  2. 20
      src/ImageSharp/Advanced/IRowIntervalOperation{TBuffer}.cs
  3. 52
      src/ImageSharp/Advanced/ParallelRowIterator.cs
  4. 6
      src/ImageSharp/ImageFrame{TPixel}.cs
  5. 6
      src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor{TPixel}.cs
  6. 26
      src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor{TPixel}.cs
  7. 8
      src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor{TPixel}.cs
  8. 12
      src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor{TPixel}.cs
  9. 8
      src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor{TPixel}.cs
  10. 6
      src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorCompassProcessor{TPixel}.cs
  11. 6
      src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor{TPixelBg,TPixelFg}.cs
  12. 6
      src/ImageSharp/Processing/Processors/Effects/OilPaintingProcessor{TPixel}.cs
  13. 8
      src/ImageSharp/Processing/Processors/Effects/PixelRowDelegateProcessor{TPixel,TDelegate}.cs
  14. 11
      src/ImageSharp/Processing/Processors/Effects/PixelateProcessor{TPixel}.cs
  15. 8
      src/ImageSharp/Processing/Processors/Filters/FilterProcessor{TPixel}.cs
  16. 299
      src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistogramEqualizationProcessor{TPixel}.cs
  17. 12
      src/ImageSharp/Processing/Processors/Normalization/GlobalHistogramEqualizationProcessor{TPixel}.cs
  18. 6
      src/ImageSharp/Processing/Processors/Overlays/BackgroundColorProcessor{TPixel}.cs
  19. 8
      src/ImageSharp/Processing/Processors/Overlays/GlowProcessor{TPixel}.cs
  20. 8
      src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor{TPixel}.cs
  21. 14
      src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor{TPixel}.cs
  22. 8
      src/ImageSharp/Processing/Processors/Transforms/CropProcessor{TPixel}.cs
  23. 6
      src/ImageSharp/Processing/Processors/Transforms/FlipProcessor{TPixel}.cs
  24. 14
      src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor{TPixel}.cs
  25. 6
      src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor{TPixel}.cs
  26. 18
      src/ImageSharp/Processing/Processors/Transforms/RotateProcessor{TPixel}.cs

18
src/ImageSharp/Advanced/IRowIntervalAction.cs → src/ImageSharp/Advanced/IRowIntervalOperation.cs

@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.Advanced
/// <summary>
/// Defines the contract for an action that operates on a row interval.
/// </summary>
public interface IRowIntervalAction
public interface IRowIntervalOperation
{
/// <summary>
/// Invokes the method passing the row interval.
@ -40,13 +40,13 @@ namespace SixLabors.ImageSharp.Advanced
}
}
internal readonly struct WrappingRowIntervalAction
internal readonly struct WrappingRowIntervalOperation
{
private readonly WrappingRowIntervalInfo info;
private readonly Action<RowInterval> action;
[MethodImpl(InliningOptions.ShortMethod)]
public WrappingRowIntervalAction(in WrappingRowIntervalInfo info, Action<RowInterval> action)
public WrappingRowIntervalOperation(in WrappingRowIntervalInfo info, Action<RowInterval> action)
{
this.info = info;
this.action = action;
@ -69,17 +69,17 @@ namespace SixLabors.ImageSharp.Advanced
}
}
internal readonly struct WrappingRowIntervalAction<T>
where T : struct, IRowIntervalAction
internal readonly struct WrappingRowIntervalOperation<T>
where T : struct, IRowIntervalOperation
{
private readonly WrappingRowIntervalInfo info;
private readonly T action;
private readonly T operation;
[MethodImpl(InliningOptions.ShortMethod)]
public WrappingRowIntervalAction(in WrappingRowIntervalInfo info, in T action)
public WrappingRowIntervalOperation(in WrappingRowIntervalInfo info, in T operation)
{
this.info = info;
this.action = action;
this.operation = operation;
}
[MethodImpl(InliningOptions.ShortMethod)]
@ -96,7 +96,7 @@ namespace SixLabors.ImageSharp.Advanced
var rows = new RowInterval(yMin, yMax);
// Skip the safety copy when invoking a potentially impure method on a readonly field
Unsafe.AsRef(this.action).Invoke(in rows);
Unsafe.AsRef(this.operation).Invoke(in rows);
}
}
}

20
src/ImageSharp/Advanced/IRowIntervalAction{TBuffer}.cs → src/ImageSharp/Advanced/IRowIntervalOperation{TBuffer}.cs

@ -12,7 +12,7 @@ namespace SixLabors.ImageSharp.Advanced
/// Defines the contract for an action that operates on a row interval with a temporary buffer.
/// </summary>
/// <typeparam name="TBuffer">The type of buffer elements.</typeparam>
public interface IRowIntervalAction<TBuffer>
public interface IRowIntervalOperation<TBuffer>
where TBuffer : unmanaged
{
/// <summary>
@ -23,7 +23,7 @@ namespace SixLabors.ImageSharp.Advanced
void Invoke(in RowInterval rows, Memory<TBuffer> memory);
}
internal readonly struct WrappingRowIntervalBufferAction<TBuffer>
internal readonly struct WrappingRowIntervalBufferOperation<TBuffer>
where TBuffer : unmanaged
{
private readonly WrappingRowIntervalInfo info;
@ -31,7 +31,7 @@ namespace SixLabors.ImageSharp.Advanced
private readonly Action<RowInterval, Memory<TBuffer>> action;
[MethodImpl(InliningOptions.ShortMethod)]
public WrappingRowIntervalBufferAction(
public WrappingRowIntervalBufferOperation(
in WrappingRowIntervalInfo info,
MemoryAllocator allocator,
Action<RowInterval, Memory<TBuffer>> action)
@ -59,23 +59,23 @@ namespace SixLabors.ImageSharp.Advanced
}
}
internal readonly struct WrappingRowIntervalBufferAction<T, TBuffer>
where T : struct, IRowIntervalAction<TBuffer>
internal readonly struct WrappingRowIntervalBufferOperation<T, TBuffer>
where T : struct, IRowIntervalOperation<TBuffer>
where TBuffer : unmanaged
{
private readonly WrappingRowIntervalInfo info;
private readonly MemoryAllocator allocator;
private readonly T action;
private readonly T operation;
[MethodImpl(InliningOptions.ShortMethod)]
public WrappingRowIntervalBufferAction(
public WrappingRowIntervalBufferOperation(
in WrappingRowIntervalInfo info,
MemoryAllocator allocator,
in T action)
in T operation)
{
this.info = info;
this.allocator = allocator;
this.action = action;
this.operation = operation;
}
[MethodImpl(InliningOptions.ShortMethod)]
@ -93,7 +93,7 @@ namespace SixLabors.ImageSharp.Advanced
using IMemoryOwner<TBuffer> buffer = this.allocator.Allocate<TBuffer>(this.info.MaxX);
Unsafe.AsRef(this.action).Invoke(in rows, buffer.Memory);
Unsafe.AsRef(this.operation).Invoke(in rows, buffer.Memory);
}
}
}

52
src/ImageSharp/Advanced/ParallelRowIterator.cs

@ -5,7 +5,6 @@ using System;
using System.Buffers;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Memory;
namespace SixLabors.ImageSharp.Advanced
@ -21,13 +20,13 @@ namespace SixLabors.ImageSharp.Advanced
/// <summary>
/// Iterate through the rows of a rectangle in optimized batches defined by <see cref="RowInterval"/>-s.
/// </summary>
/// <typeparam name="T">The type of row action to perform.</typeparam>
/// <typeparam name="T">The type of row operation to perform.</typeparam>
/// <param name="rectangle">The <see cref="Rectangle"/>.</param>
/// <param name="configuration">The <see cref="Configuration"/> to get the parallel settings from.</param>
/// <param name="body">The method body defining the iteration logic on a single <see cref="RowInterval"/>.</param>
[MethodImpl(InliningOptions.ShortMethod)]
public static void IterateRows<T>(Rectangle rectangle, Configuration configuration, in T body)
where T : struct, IRowIntervalAction
where T : struct, IRowIntervalOperation
{
var parallelSettings = ParallelExecutionSettings.FromConfiguration(configuration);
IterateRows(rectangle, in parallelSettings, in body);
@ -36,15 +35,15 @@ namespace SixLabors.ImageSharp.Advanced
/// <summary>
/// Iterate through the rows of a rectangle in optimized batches defined by <see cref="RowInterval"/>-s.
/// </summary>
/// <typeparam name="T">The type of row action to perform.</typeparam>
/// <typeparam name="T">The type of row operation to perform.</typeparam>
/// <param name="rectangle">The <see cref="Rectangle"/>.</param>
/// <param name="parallelSettings">The <see cref="ParallelExecutionSettings"/>.</param>
/// <param name="body">The method body defining the iteration logic on a single <see cref="RowInterval"/>.</param>
/// <param name="operation">The method body defining the iteration logic on a single <see cref="RowInterval"/>.</param>
public static void IterateRows<T>(
Rectangle rectangle,
in ParallelExecutionSettings parallelSettings,
in T body)
where T : struct, IRowIntervalAction
in T operation)
where T : struct, IRowIntervalOperation
{
ValidateRectangle(rectangle);
@ -60,14 +59,14 @@ namespace SixLabors.ImageSharp.Advanced
if (numOfSteps == 1)
{
var rows = new RowInterval(top, bottom);
Unsafe.AsRef(body).Invoke(in rows);
Unsafe.AsRef(operation).Invoke(in rows);
return;
}
int verticalStep = DivideCeil(rectangle.Height, numOfSteps);
var parallelOptions = new ParallelOptions { MaxDegreeOfParallelism = numOfSteps };
var rowInfo = new WrappingRowIntervalInfo(top, bottom, verticalStep);
var rowAction = new WrappingRowIntervalAction<T>(in rowInfo, in body);
var rowAction = new WrappingRowIntervalOperation<T>(in rowInfo, in operation);
Parallel.For(
0,
@ -78,30 +77,35 @@ namespace SixLabors.ImageSharp.Advanced
/// <summary>
/// Iterate through the rows of a rectangle in optimized batches defined by <see cref="RowInterval"/>-s
/// instantiating a temporary buffer for each <paramref name="body"/> invocation.
/// instantiating a temporary buffer for each <paramref name="operation"/> invocation.
/// </summary>
/// <typeparam name="T">The type of row action to perform.</typeparam>
/// <typeparam name="T">The type of row operation to perform.</typeparam>
/// <typeparam name="TBuffer">The type of buffer elements.</typeparam>
/// <param name="rectangle">The <see cref="Rectangle"/>.</param>
/// <param name="configuration">The <see cref="Configuration"/> to get the parallel settings from.</param>
/// <param name="body">The method body defining the iteration logic on a single <see cref="RowInterval"/>.</param>
public static void IterateRows<T, TBuffer>(Rectangle rectangle, Configuration configuration, in T body)
where T : struct, IRowIntervalAction<TBuffer>
/// <param name="operation">The method body defining the iteration logic on a single <see cref="RowInterval"/>.</param>
public static void IterateRows<T, TBuffer>(Rectangle rectangle, Configuration configuration, in T operation)
where T : struct, IRowIntervalOperation<TBuffer>
where TBuffer : unmanaged
{
var parallelSettings = ParallelExecutionSettings.FromConfiguration(configuration);
IterateRows<T, TBuffer>(rectangle, in parallelSettings, in body);
IterateRows<T, TBuffer>(rectangle, in parallelSettings, in operation);
}
/// <summary>
/// Iterate through the rows of a rectangle in optimized batches defined by <see cref="RowInterval"/>-s
/// instantiating a temporary buffer for each <paramref name="body"/> invocation.
/// instantiating a temporary buffer for each <paramref name="operation"/> invocation.
/// </summary>
internal static void IterateRows<T, TBuffer>(
/// <typeparam name="T">The type of row operation to perform.</typeparam>
/// <typeparam name="TBuffer">The type of buffer elements.</typeparam>
/// <param name="rectangle">The <see cref="Rectangle"/>.</param>
/// <param name="parallelSettings">The <see cref="ParallelExecutionSettings"/>.</param>
/// <param name="operation">The method body defining the iteration logic on a single <see cref="RowInterval"/>.</param>
public static void IterateRows<T, TBuffer>(
Rectangle rectangle,
in ParallelExecutionSettings parallelSettings,
in T body)
where T : struct, IRowIntervalAction<TBuffer>
in T operation)
where T : struct, IRowIntervalOperation<TBuffer>
where TBuffer : unmanaged
{
ValidateRectangle(rectangle);
@ -121,7 +125,7 @@ namespace SixLabors.ImageSharp.Advanced
var rows = new RowInterval(top, bottom);
using (IMemoryOwner<TBuffer> buffer = allocator.Allocate<TBuffer>(width))
{
Unsafe.AsRef(body).Invoke(rows, buffer.Memory);
Unsafe.AsRef(operation).Invoke(rows, buffer.Memory);
}
return;
@ -130,13 +134,13 @@ 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<T, TBuffer>(in rowInfo, allocator, in body);
var rowOperation = new WrappingRowIntervalBufferOperation<T, TBuffer>(in rowInfo, allocator, in operation);
Parallel.For(
0,
numOfSteps,
parallelOptions,
rowAction.Invoke);
rowOperation.Invoke);
}
/// <summary>
@ -183,7 +187,7 @@ namespace SixLabors.ImageSharp.Advanced
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, body);
var rowAction = new WrappingRowIntervalOperation(in rowInfo, body);
Parallel.For(
0,
@ -242,7 +246,7 @@ namespace SixLabors.ImageSharp.Advanced
int verticalStep = DivideCeil(rectangle.Height, numOfSteps);
var parallelOptions = new ParallelOptions { MaxDegreeOfParallelism = numOfSteps };
var rowInfo = new WrappingRowIntervalInfo(top, bottom, verticalStep, width);
var rowAction = new WrappingRowIntervalBufferAction<TBuffer>(in rowInfo, allocator, body);
var rowAction = new WrappingRowIntervalBufferOperation<TBuffer>(in rowInfo, allocator, body);
Parallel.For(
0,

6
src/ImageSharp/ImageFrame{TPixel}.cs

@ -263,7 +263,7 @@ namespace SixLabors.ImageSharp
ParallelRowIterator.IterateRows(
this.Bounds(),
configuration,
new RowIntervalAction<TPixel2>(this, target, configuration));
new RowIntervalOperation<TPixel2>(this, target, configuration));
return target;
}
@ -289,7 +289,7 @@ namespace SixLabors.ImageSharp
/// <summary>
/// A <see langword="struct"/> implementing the clone logic for <see cref="ImageFrame{TPixel}"/>.
/// </summary>
private readonly struct RowIntervalAction<TPixel2> : IRowIntervalAction
private readonly struct RowIntervalOperation<TPixel2> : IRowIntervalOperation
where TPixel2 : struct, IPixel<TPixel2>
{
private readonly ImageFrame<TPixel> source;
@ -297,7 +297,7 @@ namespace SixLabors.ImageSharp
private readonly Configuration configuration;
[MethodImpl(InliningOptions.ShortMethod)]
public RowIntervalAction(
public RowIntervalOperation(
ImageFrame<TPixel> source,
ImageFrame<TPixel2> target,
Configuration configuration)

6
src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor{TPixel}.cs

@ -54,13 +54,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Binarization
ParallelRowIterator.IterateRows(
workingRect,
configuration,
new RowIntervalAction(source, upper, lower, threshold, startX, endX, isAlphaOnly));
new RowIntervalOperation(source, upper, lower, threshold, startX, endX, isAlphaOnly));
}
/// <summary>
/// A <see langword="struct"/> implementing the clone logic for <see cref="BinaryThresholdProcessor{TPixel}"/>.
/// </summary>
private readonly struct RowIntervalAction : IRowIntervalAction
private readonly struct RowIntervalOperation : IRowIntervalOperation
{
private readonly ImageFrame<TPixel> source;
private readonly TPixel upper;
@ -71,7 +71,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Binarization
private readonly bool isAlphaOnly;
[MethodImpl(InliningOptions.ShortMethod)]
public RowIntervalAction(
public RowIntervalOperation(
ImageFrame<TPixel> source,
TPixel upper,
TPixel lower,

26
src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor{TPixel}.cs

@ -268,10 +268,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
protected override void OnFrameApply(ImageFrame<TPixel> source)
{
// Preliminary gamma highlight pass
ParallelRowIterator.IterateRows<ApplyGammaExposureRowIntervalAction, Vector4>(
ParallelRowIterator.IterateRows<ApplyGammaExposureRowIntervalOperation, Vector4>(
this.SourceRectangle,
this.Configuration,
new ApplyGammaExposureRowIntervalAction(this.SourceRectangle, source.PixelBuffer, this.Configuration, this.gamma));
new ApplyGammaExposureRowIntervalOperation(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<Vector4> processingBuffer = this.Configuration.MemoryAllocator.Allocate2D<Vector4>(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 ApplyInverseGammaExposureRowIntervalOperation(this.SourceRectangle, source.PixelBuffer, processingBuffer, this.Configuration, inverseGamma));
}
/// <summary>
@ -317,20 +317,20 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
ParallelRowIterator.IterateRows(
sourceRectangle,
configuration,
new ApplyVerticalConvolutionRowIntervalAction(ref sourceRectangle, firstPassBuffer, source.PixelBuffer, kernel));
new ApplyVerticalConvolutionRowIntervalOperation(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 ApplyHorizontalConvolutionRowIntervalOperation(ref sourceRectangle, processingBuffer, firstPassBuffer, kernel, parameters.Z, parameters.W));
}
}
/// <summary>
/// A <see langword="struct"/> implementing the vertical convolution logic for <see cref="BokehBlurProcessor{T}"/>.
/// </summary>
private readonly struct ApplyVerticalConvolutionRowIntervalAction : IRowIntervalAction
private readonly struct ApplyVerticalConvolutionRowIntervalOperation : IRowIntervalOperation
{
private readonly Rectangle bounds;
private readonly Buffer2D<ComplexVector4> targetValues;
@ -340,7 +340,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
private readonly int maxX;
[MethodImpl(InliningOptions.ShortMethod)]
public ApplyVerticalConvolutionRowIntervalAction(
public ApplyVerticalConvolutionRowIntervalOperation(
ref Rectangle bounds,
Buffer2D<ComplexVector4> targetValues,
Buffer2D<TPixel> sourcePixels,
@ -373,7 +373,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
/// <summary>
/// A <see langword="struct"/> implementing the horizontal convolution logic for <see cref="BokehBlurProcessor{T}"/>.
/// </summary>
private readonly struct ApplyHorizontalConvolutionRowIntervalAction : IRowIntervalAction
private readonly struct ApplyHorizontalConvolutionRowIntervalOperation : IRowIntervalOperation
{
private readonly Rectangle bounds;
private readonly Buffer2D<Vector4> targetValues;
@ -385,7 +385,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
private readonly int maxX;
[MethodImpl(InliningOptions.ShortMethod)]
public ApplyHorizontalConvolutionRowIntervalAction(
public ApplyHorizontalConvolutionRowIntervalOperation(
ref Rectangle bounds,
Buffer2D<Vector4> targetValues,
Buffer2D<ComplexVector4> sourceValues,
@ -422,7 +422,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
/// <summary>
/// A <see langword="struct"/> implementing the gamma exposure logic for <see cref="BokehBlurProcessor{T}"/>.
/// </summary>
private readonly struct ApplyGammaExposureRowIntervalAction : IRowIntervalAction<Vector4>
private readonly struct ApplyGammaExposureRowIntervalOperation : IRowIntervalOperation<Vector4>
{
private readonly Rectangle bounds;
private readonly Buffer2D<TPixel> targetPixels;
@ -430,7 +430,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
private readonly float gamma;
[MethodImpl(InliningOptions.ShortMethod)]
public ApplyGammaExposureRowIntervalAction(
public ApplyGammaExposureRowIntervalOperation(
Rectangle bounds,
Buffer2D<TPixel> targetPixels,
Configuration configuration,
@ -471,7 +471,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
/// <summary>
/// A <see langword="struct"/> implementing the inverse gamma exposure logic for <see cref="BokehBlurProcessor{T}"/>.
/// </summary>
private readonly struct ApplyInverseGammaExposureRowIntervalAction : IRowIntervalAction
private readonly struct ApplyInverseGammaExposureRowIntervalOperation : IRowIntervalOperation
{
private readonly Rectangle bounds;
private readonly Buffer2D<TPixel> targetPixels;
@ -480,7 +480,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
private readonly float inverseGamma;
[MethodImpl(InliningOptions.ShortMethod)]
public ApplyInverseGammaExposureRowIntervalAction(
public ApplyInverseGammaExposureRowIntervalOperation(
Rectangle bounds,
Buffer2D<TPixel> targetPixels,
Buffer2D<Vector4> sourceValues,

8
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<RowIntervalAction, Vector4>(
ParallelRowIterator.IterateRows<RowIntervalOperation, Vector4>(
interest,
this.Configuration,
new RowIntervalAction(interest, targetPixels, source.PixelBuffer, this.KernelY, this.KernelX, this.Configuration, this.PreserveAlpha));
new RowIntervalOperation(interest, targetPixels, source.PixelBuffer, this.KernelY, this.KernelX, this.Configuration, this.PreserveAlpha));
Buffer2D<TPixel>.SwapOrCopyContent(source.PixelBuffer, targetPixels);
}
@ -77,7 +77,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
/// <summary>
/// A <see langword="struct"/> implementing the convolution logic for <see cref="Convolution2DProcessor{T}"/>.
/// </summary>
private readonly struct RowIntervalAction : IRowIntervalAction<Vector4>
private readonly struct RowIntervalOperation : IRowIntervalOperation<Vector4>
{
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 RowIntervalOperation(
Rectangle bounds,
Buffer2D<TPixel> targetPixels,
Buffer2D<TPixel> sourcePixels,

12
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<RowIntervalAction, Vector4>(
ParallelRowIterator.IterateRows<RowIntervalOperation, Vector4>(
interest,
this.Configuration,
new RowIntervalAction(interest, firstPassPixels, source.PixelBuffer, this.KernelX, this.Configuration, this.PreserveAlpha));
new RowIntervalOperation(interest, firstPassPixels, source.PixelBuffer, this.KernelX, this.Configuration, this.PreserveAlpha));
// Vertical convolution
ParallelRowIterator.IterateRows<RowIntervalAction, Vector4>(
ParallelRowIterator.IterateRows<RowIntervalOperation, Vector4>(
interest,
this.Configuration,
new RowIntervalAction(interest, source.PixelBuffer, firstPassPixels, this.KernelY, this.Configuration, this.PreserveAlpha));
new RowIntervalOperation(interest, source.PixelBuffer, firstPassPixels, this.KernelY, this.Configuration, this.PreserveAlpha));
}
/// <summary>
/// A <see langword="struct"/> implementing the convolution logic for <see cref="Convolution2PassProcessor{T}"/>.
/// </summary>
private readonly struct RowIntervalAction : IRowIntervalAction<Vector4>
private readonly struct RowIntervalOperation : IRowIntervalOperation<Vector4>
{
private readonly Rectangle bounds;
private readonly Buffer2D<TPixel> targetPixels;
@ -89,7 +89,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
private readonly bool preserveAlpha;
[MethodImpl(InliningOptions.ShortMethod)]
public RowIntervalAction(
public RowIntervalOperation(
Rectangle bounds,
Buffer2D<TPixel> targetPixels,
Buffer2D<TPixel> sourcePixels,

8
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<RowIntervalAction, Vector4>(
ParallelRowIterator.IterateRows<RowIntervalOperation, Vector4>(
interest,
this.Configuration,
new RowIntervalAction(interest, targetPixels, source.PixelBuffer, this.KernelXY, this.Configuration, this.PreserveAlpha));
new RowIntervalOperation(interest, targetPixels, source.PixelBuffer, this.KernelXY, this.Configuration, this.PreserveAlpha));
Buffer2D<TPixel>.SwapOrCopyContent(source.PixelBuffer, targetPixels);
}
@ -68,7 +68,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
/// <summary>
/// A <see langword="struct"/> implementing the convolution logic for <see cref="ConvolutionProcessor{T}"/>.
/// </summary>
private readonly struct RowIntervalAction : IRowIntervalAction<Vector4>
private readonly struct RowIntervalOperation : IRowIntervalOperation<Vector4>
{
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 RowIntervalOperation(
Rectangle bounds,
Buffer2D<TPixel> targetPixels,
Buffer2D<TPixel> sourcePixels,

6
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 RowIntervalOperation(source.PixelBuffer, pass.PixelBuffer, minX, maxX, shiftY, shiftX));
}
}
/// <summary>
/// A <see langword="struct"/> implementing the convolution logic for <see cref="EdgeDetectorCompassProcessor{T}"/>.
/// </summary>
private readonly struct RowIntervalAction : IRowIntervalAction
private readonly struct RowIntervalOperation : IRowIntervalOperation
{
private readonly Buffer2D<TPixel> targetPixels;
private readonly Buffer2D<TPixel> passPixels;
@ -122,7 +122,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
private readonly int shiftX;
[MethodImpl(InliningOptions.ShortMethod)]
public RowIntervalAction(
public RowIntervalOperation(
Buffer2D<TPixel> targetPixels,
Buffer2D<TPixel> passPixels,
int minX,

6
src/ImageSharp/Processing/Processors/Drawing/DrawImageProcessor{TPixelBg,TPixelFg}.cs

@ -102,13 +102,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing
ParallelRowIterator.IterateRows(
workingRect,
configuration,
new RowIntervalAction(source, targetImage, blender, configuration, minX, width, locationY, targetX, this.Opacity));
new RowIntervalOperation(source, targetImage, blender, configuration, minX, width, locationY, targetX, this.Opacity));
}
/// <summary>
/// A <see langword="struct"/> implementing the draw logic for <see cref="DrawImageProcessor{TPixelBg,TPixelFg}"/>.
/// </summary>
private readonly struct RowIntervalAction : IRowIntervalAction
private readonly struct RowIntervalOperation : IRowIntervalOperation
{
private readonly ImageFrame<TPixelBg> sourceFrame;
private readonly Image<TPixelFg> targetImage;
@ -121,7 +121,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing
private readonly float opacity;
[MethodImpl(InliningOptions.ShortMethod)]
public RowIntervalAction(
public RowIntervalOperation(
ImageFrame<TPixelBg> sourceFrame,
Image<TPixelFg> targetImage,
PixelBlender<TPixelBg> blender,

6
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 RowIntervalOperation(this.SourceRectangle, targetPixels, source, this.Configuration, brushSize >> 1, this.definition.Levels));
Buffer2D<TPixel>.SwapOrCopyContent(source.PixelBuffer, targetPixels);
}
@ -58,7 +58,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Effects
/// <summary>
/// A <see langword="struct"/> implementing the convolution logic for <see cref="OilPaintingProcessor{T}"/>.
/// </summary>
private readonly struct RowIntervalAction : IRowIntervalAction
private readonly struct RowIntervalOperation : IRowIntervalOperation
{
private readonly Rectangle bounds;
private readonly Buffer2D<TPixel> targetPixels;
@ -68,7 +68,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Effects
private readonly int levels;
[MethodImpl(InliningOptions.ShortMethod)]
public RowIntervalAction(
public RowIntervalOperation(
Rectangle bounds,
Buffer2D<TPixel> targetPixels,
ImageFrame<TPixel> source,

8
src/ImageSharp/Processing/Processors/Effects/PixelRowDelegateProcessor{TPixel,TDelegate}.cs

@ -51,16 +51,16 @@ namespace SixLabors.ImageSharp.Processing.Processors.Effects
{
var interest = Rectangle.Intersect(this.SourceRectangle, source.Bounds());
ParallelRowIterator.IterateRows<RowIntervalAction, Vector4>(
ParallelRowIterator.IterateRows<RowIntervalOperation, Vector4>(
interest,
this.Configuration,
new RowIntervalAction(interest.X, source, this.Configuration, this.modifiers, this.rowDelegate));
new RowIntervalOperation(interest.X, source, this.Configuration, this.modifiers, this.rowDelegate));
}
/// <summary>
/// A <see langword="struct"/> implementing the convolution logic for <see cref="PixelRowDelegateProcessor{TPixel,TDelegate}"/>.
/// </summary>
private readonly struct RowIntervalAction : IRowIntervalAction<Vector4>
private readonly struct RowIntervalOperation : IRowIntervalOperation<Vector4>
{
private readonly int startX;
private readonly ImageFrame<TPixel> source;
@ -69,7 +69,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Effects
private readonly TDelegate rowProcessor;
[MethodImpl(InliningOptions.ShortMethod)]
public RowIntervalAction(
public RowIntervalOperation(
int startX,
ImageFrame<TPixel> source,
Configuration configuration,

11
src/ImageSharp/Processing/Processors/Effects/PixelateProcessor{TPixel}.cs

@ -5,7 +5,6 @@ using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.PixelFormats;
@ -29,9 +28,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Effects
/// <param name="sourceRectangle">The source area to process for the current processor instance.</param>
public PixelateProcessor(Configuration configuration, PixelateProcessor definition, Image<TPixel> source, Rectangle sourceRectangle)
: base(configuration, source, sourceRectangle)
{
this.definition = definition;
}
=> this.definition = definition;
private int Size => this.definition.Size;
@ -51,10 +48,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Effects
Parallel.ForEach(
range,
this.Configuration.GetParallelOptions(),
new RowAction(interest, size, source).Invoke);
new RowOperation(interest, size, source).Invoke);
}
private readonly struct RowAction
private readonly struct RowOperation
{
private readonly int minX;
private readonly int maxX;
@ -66,7 +63,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Effects
private readonly ImageFrame<TPixel> source;
[MethodImpl(InliningOptions.ShortMethod)]
public RowAction(
public RowOperation(
Rectangle bounds,
int size,
ImageFrame<TPixel> source)

8
src/ImageSharp/Processing/Processors/Filters/FilterProcessor{TPixel}.cs

@ -37,16 +37,16 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters
{
var interest = Rectangle.Intersect(this.SourceRectangle, source.Bounds());
ParallelRowIterator.IterateRows<RowIntervalAction, Vector4>(
ParallelRowIterator.IterateRows<RowIntervalOperation, Vector4>(
interest,
this.Configuration,
new RowIntervalAction(interest.X, source, this.definition.Matrix, this.Configuration));
new RowIntervalOperation(interest.X, source, this.definition.Matrix, this.Configuration));
}
/// <summary>
/// A <see langword="struct"/> implementing the convolution logic for <see cref="FilterProcessor{TPixel}"/>.
/// </summary>
private readonly struct RowIntervalAction : IRowIntervalAction<Vector4>
private readonly struct RowIntervalOperation : IRowIntervalOperation<Vector4>
{
private readonly int startX;
private readonly ImageFrame<TPixel> source;
@ -54,7 +54,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters
private readonly Configuration configuration;
[MethodImpl(InliningOptions.ShortMethod)]
public RowIntervalAction(
public RowIntervalOperation(
int startX,
ImageFrame<TPixel> source,
ColorMatrix matrix,

299
src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistogramEqualizationProcessor{TPixel}.cs

@ -7,8 +7,7 @@ using System.Collections.Generic;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
@ -81,56 +80,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization
yStart += tileHeight;
}
Parallel.For(
0,
tileYStartPositions.Count,
new ParallelOptions { MaxDegreeOfParallelism = this.Configuration.MaxDegreeOfParallelism },
index =>
{
int y = tileYStartPositions[index].y;
int cdfYY = tileYStartPositions[index].cdfY;
// It's unfortunate that we have to do this per iteration.
ref TPixel sourceBase = ref source.GetPixelReference(0, 0);
int cdfX = 0;
int x = halfTileWidth;
for (int tile = 0; tile < tileCount - 1; tile++)
{
int tileY = 0;
int yEnd = Math.Min(y + tileHeight, sourceHeight);
int xEnd = Math.Min(x + tileWidth, sourceWidth);
for (int dy = y; dy < yEnd; dy++)
{
int dyOffSet = dy * sourceWidth;
int tileX = 0;
for (int dx = x; dx < xEnd; dx++)
{
ref TPixel pixel = ref Unsafe.Add(ref sourceBase, dyOffSet + dx);
float luminanceEqualized = InterpolateBetweenFourTiles(
pixel,
cdfData,
tileCount,
tileCount,
tileX,
tileY,
cdfX,
cdfYY,
tileWidth,
tileHeight,
luminanceLevels);
pixel.FromVector4(new Vector4(luminanceEqualized, luminanceEqualized, luminanceEqualized, pixel.ToVector4().W));
tileX++;
}
tileY++;
}
cdfX++;
x += tileWidth;
}
});
ParallelRowIterator.IterateRows(
new Rectangle(0, 0, sourceWidth, tileYStartPositions.Count),
this.Configuration,
new RowIntervalOperation(cdfData, tileYStartPositions, tileWidth, tileHeight, tileCount, halfTileWidth, luminanceLevels, source));
ref TPixel pixelsBase = ref source.GetPixelReference(0, 0);
@ -416,6 +369,95 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization
private static float LinearInterpolation(float left, float right, float t)
=> left + ((right - left) * t);
private readonly struct RowIntervalOperation : IRowIntervalOperation
{
private readonly CdfTileData cdfData;
private readonly List<(int y, int cdfY)> tileYStartPositions;
private readonly int tileWidth;
private readonly int tileHeight;
private readonly int tileCount;
private readonly int halfTileWidth;
private readonly int luminanceLevels;
private readonly ImageFrame<TPixel> source;
private readonly int sourceWidth;
private readonly int sourceHeight;
[MethodImpl(InliningOptions.ShortMethod)]
public RowIntervalOperation(
CdfTileData cdfData,
List<(int y, int cdfY)> tileYStartPositions,
int tileWidth,
int tileHeight,
int tileCount,
int halfTileWidth,
int luminanceLevels,
ImageFrame<TPixel> source)
{
this.cdfData = cdfData;
this.tileYStartPositions = tileYStartPositions;
this.tileWidth = tileWidth;
this.tileHeight = tileHeight;
this.tileCount = tileCount;
this.halfTileWidth = halfTileWidth;
this.luminanceLevels = luminanceLevels;
this.source = source;
this.sourceWidth = source.Width;
this.sourceHeight = source.Height;
}
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void Invoke(in RowInterval rows)
{
ref TPixel sourceBase = ref this.source.GetPixelReference(0, 0);
for (int index = rows.Min; index < rows.Max; index++)
{
(int y, int cdfY) tileYStartPosition = this.tileYStartPositions[index];
int y = tileYStartPosition.y;
int cdfYY = tileYStartPosition.cdfY;
int cdfX = 0;
int x = this.halfTileWidth;
for (int tile = 0; tile < this.tileCount - 1; tile++)
{
int tileY = 0;
int yEnd = Math.Min(y + this.tileHeight, this.sourceHeight);
int xEnd = Math.Min(x + this.tileWidth, this.sourceWidth);
for (int dy = y; dy < yEnd; dy++)
{
int dyOffSet = dy * this.sourceWidth;
int tileX = 0;
for (int dx = x; dx < xEnd; dx++)
{
ref TPixel pixel = ref Unsafe.Add(ref sourceBase, dyOffSet + dx);
float luminanceEqualized = InterpolateBetweenFourTiles(
pixel,
this.cdfData,
this.tileCount,
this.tileCount,
tileX,
tileY,
cdfX,
cdfYY,
this.tileWidth,
this.tileHeight,
this.luminanceLevels);
pixel.FromVector4(new Vector4(luminanceEqualized, luminanceEqualized, luminanceEqualized, pixel.ToVector4().W));
tileX++;
}
tileY++;
}
cdfX++;
x += this.tileWidth;
}
}
}
}
/// <summary>
/// Contains the results of the cumulative distribution function for all tiles.
/// </summary>
@ -470,57 +512,21 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization
public void CalculateLookupTables(ImageFrame<TPixel> source, HistogramEqualizationProcessor<TPixel> processor)
{
int sourceWidth = this.sourceWidth;
int sourceHeight = this.sourceHeight;
int tileWidth = this.tileWidth;
int tileHeight = this.tileHeight;
int luminanceLevels = this.luminanceLevels;
Parallel.For(
0,
this.tileYStartPositions.Count,
new ParallelOptions { MaxDegreeOfParallelism = this.configuration.MaxDegreeOfParallelism },
index =>
{
int cdfX = 0;
int cdfY = this.tileYStartPositions[index].cdfY;
int y = this.tileYStartPositions[index].y;
int endY = Math.Min(y + tileHeight, sourceHeight);
ref TPixel sourceBase = ref source.GetPixelReference(0, 0);
ref int cdfMinBase = ref MemoryMarshal.GetReference(this.cdfMinBuffer2D.GetRowSpan(cdfY));
using (IMemoryOwner<int> histogramBuffer = this.memoryAllocator.Allocate<int>(luminanceLevels))
{
Span<int> histogram = histogramBuffer.GetSpan();
ref int histogramBase = ref MemoryMarshal.GetReference(histogram);
for (int x = 0; x < sourceWidth; x += tileWidth)
{
histogram.Clear();
ref int cdfBase = ref MemoryMarshal.GetReference(this.GetCdfLutSpan(cdfX, index));
int xlimit = Math.Min(x + tileWidth, sourceWidth);
for (int dy = y; dy < endY; dy++)
{
int dyOffset = dy * sourceWidth;
for (int dx = x; dx < xlimit; dx++)
{
int luminance = GetLuminance(Unsafe.Add(ref sourceBase, dyOffset + dx), luminanceLevels);
histogram[luminance]++;
}
}
if (processor.ClipHistogramEnabled)
{
processor.ClipHistogram(histogram, processor.ClipLimit);
}
Unsafe.Add(ref cdfMinBase, cdfX) = processor.CalculateCdf(ref cdfBase, ref histogramBase, histogram.Length - 1);
cdfX++;
}
}
});
var rowOperation = new RowIntervalOperation(
processor,
this.memoryAllocator,
this.cdfMinBuffer2D,
this.cdfLutBuffer2D,
this.tileYStartPositions,
this.tileWidth,
this.tileHeight,
this.luminanceLevels,
source);
ParallelRowIterator.IterateRows(
new Rectangle(0, 0, this.sourceWidth, this.tileYStartPositions.Count),
this.configuration,
in rowOperation);
}
[MethodImpl(InliningOptions.ShortMethod)]
@ -548,6 +554,93 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization
this.cdfMinBuffer2D.Dispose();
this.cdfLutBuffer2D.Dispose();
}
private readonly struct RowIntervalOperation : IRowIntervalOperation
{
private readonly HistogramEqualizationProcessor<TPixel> processor;
private readonly MemoryAllocator allocator;
private readonly Buffer2D<int> cdfMinBuffer2D;
private readonly Buffer2D<int> cdfLutBuffer2D;
private readonly List<(int y, int cdfY)> tileYStartPositions;
private readonly int tileWidth;
private readonly int tileHeight;
private readonly int luminanceLevels;
private readonly ImageFrame<TPixel> source;
private readonly int sourceWidth;
private readonly int sourceHeight;
[MethodImpl(InliningOptions.ShortMethod)]
public RowIntervalOperation(
HistogramEqualizationProcessor<TPixel> processor,
MemoryAllocator allocator,
Buffer2D<int> cdfMinBuffer2D,
Buffer2D<int> cdfLutBuffer2D,
List<(int y, int cdfY)> tileYStartPositions,
int tileWidth,
int tileHeight,
int luminanceLevels,
ImageFrame<TPixel> source)
{
this.processor = processor;
this.allocator = allocator;
this.cdfMinBuffer2D = cdfMinBuffer2D;
this.cdfLutBuffer2D = cdfLutBuffer2D;
this.tileYStartPositions = tileYStartPositions;
this.tileWidth = tileWidth;
this.tileHeight = tileHeight;
this.luminanceLevels = luminanceLevels;
this.source = source;
this.sourceWidth = source.Width;
this.sourceHeight = source.Height;
}
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void Invoke(in RowInterval rows)
{
ref TPixel sourceBase = ref this.source.GetPixelReference(0, 0);
for (int index = rows.Min; index < rows.Max; index++)
{
int cdfX = 0;
int cdfY = this.tileYStartPositions[index].cdfY;
int y = this.tileYStartPositions[index].y;
int endY = Math.Min(y + this.tileHeight, this.sourceHeight);
ref int cdfMinBase = ref MemoryMarshal.GetReference(this.cdfMinBuffer2D.GetRowSpan(cdfY));
using IMemoryOwner<int> histogramBuffer = this.allocator.Allocate<int>(this.luminanceLevels);
Span<int> histogram = histogramBuffer.GetSpan();
ref int histogramBase = ref MemoryMarshal.GetReference(histogram);
for (int x = 0; x < this.sourceWidth; x += this.tileWidth)
{
histogram.Clear();
Span<int> cdfLutSpan = this.cdfLutBuffer2D.GetRowSpan(index).Slice(cdfX * this.luminanceLevels, this.luminanceLevels);
ref int cdfBase = ref MemoryMarshal.GetReference(cdfLutSpan);
int xlimit = Math.Min(x + this.tileWidth, this.sourceWidth);
for (int dy = y; dy < endY; dy++)
{
int dyOffset = dy * this.sourceWidth;
for (int dx = x; dx < xlimit; dx++)
{
int luminance = GetLuminance(Unsafe.Add(ref sourceBase, dyOffset + dx), this.luminanceLevels);
histogram[luminance]++;
}
}
if (this.processor.ClipHistogramEnabled)
{
this.processor.ClipHistogram(histogram, this.processor.ClipLimit);
}
Unsafe.Add(ref cdfMinBase, cdfX) = this.processor.CalculateCdf(ref cdfBase, ref histogramBase, histogram.Length - 1);
cdfX++;
}
}
}
}
}
}
}

12
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 GrayscaleLevelsRowIntervalOperation(workingRect, histogramBuffer, source, this.LuminanceLevels));
Span<int> 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 CdfApplicationRowIntervalOperation(workingRect, cdfBuffer, source, this.LuminanceLevels, numberOfPixelsMinusCdfMin));
}
/// <summary>
/// A <see langword="struct"/> implementing the grayscale levels logic for <see cref="GlobalHistogramEqualizationProcessor{TPixel}"/>.
/// </summary>
private readonly struct GrayscaleLevelsRowIntervalAction : IRowIntervalAction
private readonly struct GrayscaleLevelsRowIntervalOperation : IRowIntervalOperation
{
private readonly Rectangle bounds;
private readonly IMemoryOwner<int> histogramBuffer;
@ -91,7 +91,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization
private readonly int luminanceLevels;
[MethodImpl(InliningOptions.ShortMethod)]
public GrayscaleLevelsRowIntervalAction(
public GrayscaleLevelsRowIntervalOperation(
in Rectangle bounds,
IMemoryOwner<int> histogramBuffer,
ImageFrame<TPixel> source,
@ -124,7 +124,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization
/// <summary>
/// A <see langword="struct"/> implementing the cdf application levels logic for <see cref="GlobalHistogramEqualizationProcessor{TPixel}"/>.
/// </summary>
private readonly struct CdfApplicationRowIntervalAction : IRowIntervalAction
private readonly struct CdfApplicationRowIntervalOperation : IRowIntervalOperation
{
private readonly Rectangle bounds;
private readonly IMemoryOwner<int> cdfBuffer;
@ -133,7 +133,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization
private readonly float numberOfPixelsMinusCdfMin;
[MethodImpl(InliningOptions.ShortMethod)]
public CdfApplicationRowIntervalAction(
public CdfApplicationRowIntervalOperation(
in Rectangle bounds,
IMemoryOwner<int> cdfBuffer,
ImageFrame<TPixel> source,

6
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 RowIntervalOperation(configuration, interest, blender, amount, colors, source));
}
private readonly struct RowIntervalAction : IRowIntervalAction
private readonly struct RowIntervalOperation : IRowIntervalOperation
{
private readonly Configuration configuration;
private readonly Rectangle bounds;
@ -65,7 +65,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays
private readonly ImageFrame<TPixel> source;
[MethodImpl(InliningOptions.ShortMethod)]
public RowIntervalAction(
public RowIntervalOperation(
Configuration configuration,
Rectangle bounds,
PixelBlender<TPixel> blender,

8
src/ImageSharp/Processing/Processors/Overlays/GlowProcessor{TPixel}.cs

@ -55,13 +55,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays
using IMemoryOwner<TPixel> rowColors = allocator.Allocate<TPixel>(interest.Width);
rowColors.GetSpan().Fill(glowColor);
ParallelRowIterator.IterateRows<RowIntervalAction, float>(
ParallelRowIterator.IterateRows<RowIntervalOperation, float>(
interest,
configuration,
new RowIntervalAction(configuration, interest, rowColors, this.blender, center, maxDistance, blendPercent, source));
new RowIntervalOperation(configuration, interest, rowColors, this.blender, center, maxDistance, blendPercent, source));
}
private readonly struct RowIntervalAction : IRowIntervalAction<float>
private readonly struct RowIntervalOperation : IRowIntervalOperation<float>
{
private readonly Configuration configuration;
private readonly Rectangle bounds;
@ -73,7 +73,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays
private readonly ImageFrame<TPixel> source;
[MethodImpl(InliningOptions.ShortMethod)]
public RowIntervalAction(
public RowIntervalOperation(
Configuration configuration,
Rectangle bounds,
IMemoryOwner<TPixel> colors,

8
src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor{TPixel}.cs

@ -63,13 +63,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays
using IMemoryOwner<TPixel> rowColors = allocator.Allocate<TPixel>(interest.Width);
rowColors.GetSpan().Fill(vignetteColor);
ParallelRowIterator.IterateRows<RowIntervalAction, float>(
ParallelRowIterator.IterateRows<RowIntervalOperation, float>(
interest,
configuration,
new RowIntervalAction(configuration, interest, rowColors, this.blender, center, maxDistance, blendPercent, source));
new RowIntervalOperation(configuration, interest, rowColors, this.blender, center, maxDistance, blendPercent, source));
}
private readonly struct RowIntervalAction : IRowIntervalAction<float>
private readonly struct RowIntervalOperation : IRowIntervalOperation<float>
{
private readonly Configuration configuration;
private readonly Rectangle bounds;
@ -81,7 +81,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays
private readonly ImageFrame<TPixel> source;
[MethodImpl(InliningOptions.ShortMethod)]
public RowIntervalAction(
public RowIntervalOperation(
Configuration configuration,
Rectangle bounds,
IMemoryOwner<TPixel> colors,

14
src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor{TPixel}.cs

@ -61,23 +61,23 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
ParallelRowIterator.IterateRows(
targetBounds,
configuration,
new NearestNeighborRowIntervalAction(this.SourceRectangle, ref matrix, width, source, destination));
new NearestNeighborRowIntervalOperation(this.SourceRectangle, ref matrix, width, source, destination));
return;
}
using var kernelMap = new TransformKernelMap(configuration, source.Size(), destination.Size(), this.resampler);
ParallelRowIterator.IterateRows<RowIntervalAction, Vector4>(
ParallelRowIterator.IterateRows<RowIntervalOperation, Vector4>(
targetBounds,
configuration,
new RowIntervalAction(configuration, kernelMap, ref matrix, width, source, destination));
new RowIntervalOperation(configuration, kernelMap, ref matrix, width, source, destination));
}
/// <summary>
/// A <see langword="struct"/> implementing the nearest neighbor resampler logic for <see cref="AffineTransformProcessor{T}"/>.
/// </summary>
private readonly struct NearestNeighborRowIntervalAction : IRowIntervalAction
private readonly struct NearestNeighborRowIntervalOperation : IRowIntervalOperation
{
private readonly Rectangle bounds;
private readonly Matrix3x2 matrix;
@ -86,7 +86,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
private readonly ImageFrame<TPixel> destination;
[MethodImpl(InliningOptions.ShortMethod)]
public NearestNeighborRowIntervalAction(
public NearestNeighborRowIntervalOperation(
Rectangle bounds,
ref Matrix3x2 matrix,
int maxX,
@ -124,7 +124,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
/// <summary>
/// A <see langword="struct"/> implementing the transformation logic for <see cref="AffineTransformProcessor{T}"/>.
/// </summary>
private readonly struct RowIntervalAction : IRowIntervalAction<Vector4>
private readonly struct RowIntervalOperation : IRowIntervalOperation<Vector4>
{
private readonly Configuration configuration;
private readonly TransformKernelMap kernelMap;
@ -134,7 +134,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
private readonly ImageFrame<TPixel> destination;
[MethodImpl(InliningOptions.ShortMethod)]
public RowIntervalAction(
public RowIntervalOperation(
Configuration configuration,
TransformKernelMap kernelMap,
ref Matrix3x2 matrix,

8
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 rowAction = new RowIntervalAction(ref bounds, source, destination);
var rowAction = new RowIntervalOperation(ref bounds, source, destination);
ParallelRowIterator.IterateRows(
bounds,
@ -62,20 +62,20 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
/// <summary>
/// A <see langword="struct"/> implementing the processor logic for <see cref="CropProcessor{T}"/>.
/// </summary>
private readonly struct RowIntervalAction : IRowIntervalAction
private readonly struct RowIntervalOperation : IRowIntervalOperation
{
private readonly Rectangle bounds;
private readonly ImageFrame<TPixel> source;
private readonly ImageFrame<TPixel> destination;
/// <summary>
/// Initializes a new instance of the <see cref="RowIntervalAction"/> struct.
/// Initializes a new instance of the <see cref="RowIntervalOperation"/> struct.
/// </summary>
/// <param name="bounds">The target processing bounds for the current instance.</param>
/// <param name="source">The source <see cref="Image{TPixel}"/> for the current instance.</param>
/// <param name="destination">The destination <see cref="Image{TPixel}"/> for the current instance.</param>
[MethodImpl(InliningOptions.ShortMethod)]
public RowIntervalAction(ref Rectangle bounds, ImageFrame<TPixel> source, ImageFrame<TPixel> destination)
public RowIntervalOperation(ref Rectangle bounds, ImageFrame<TPixel> source, ImageFrame<TPixel> destination)
{
this.bounds = bounds;
this.source = source;

6
src/ImageSharp/Processing/Processors/Transforms/FlipProcessor{TPixel}.cs

@ -79,15 +79,15 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
ParallelRowIterator.IterateRows(
source.Bounds(),
configuration,
new RowIntervalAction(source));
new RowIntervalOperation(source));
}
private readonly struct RowIntervalAction : IRowIntervalAction
private readonly struct RowIntervalOperation : IRowIntervalOperation
{
private readonly ImageFrame<TPixel> source;
[MethodImpl(InliningOptions.ShortMethod)]
public RowIntervalAction(ImageFrame<TPixel> source) => this.source = source;
public RowIntervalOperation(ImageFrame<TPixel> source) => this.source = source;
[MethodImpl(InliningOptions.ShortMethod)]
public void Invoke(in RowInterval rows)

14
src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor{TPixel}.cs

@ -63,20 +63,20 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
ParallelRowIterator.IterateRows(
targetBounds,
configuration,
new NearestNeighborRowIntervalAction(ref sourceBounds, ref matrix, width, source, destination));
new NearestNeighborRowIntervalOperation(ref sourceBounds, ref matrix, width, source, destination));
return;
}
using var kernelMap = new TransformKernelMap(configuration, source.Size(), destination.Size(), this.resampler);
ParallelRowIterator.IterateRows<RowIntervalAction, Vector4>(
ParallelRowIterator.IterateRows<RowIntervalOperation, Vector4>(
targetBounds,
configuration,
new RowIntervalAction(configuration, kernelMap, ref matrix, width, source, destination));
new RowIntervalOperation(configuration, kernelMap, ref matrix, width, source, destination));
}
private readonly struct NearestNeighborRowIntervalAction : IRowIntervalAction
private readonly struct NearestNeighborRowIntervalOperation : IRowIntervalOperation
{
private readonly Rectangle bounds;
private readonly Matrix4x4 matrix;
@ -85,7 +85,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
private readonly ImageFrame<TPixel> destination;
[MethodImpl(InliningOptions.ShortMethod)]
public NearestNeighborRowIntervalAction(
public NearestNeighborRowIntervalOperation(
ref Rectangle bounds,
ref Matrix4x4 matrix,
int maxX,
@ -121,7 +121,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
}
}
private readonly struct RowIntervalAction : IRowIntervalAction<Vector4>
private readonly struct RowIntervalOperation : IRowIntervalOperation<Vector4>
{
private readonly Configuration configuration;
private readonly TransformKernelMap kernelMap;
@ -131,7 +131,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
private readonly ImageFrame<TPixel> destination;
[MethodImpl(InliningOptions.ShortMethod)]
public RowIntervalAction(
public RowIntervalOperation(
Configuration configuration,
TransformKernelMap kernelMap,
ref Matrix4x4 matrix,

6
src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor{TPixel}.cs

@ -98,7 +98,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
ParallelRowIterator.IterateRows(
interest,
configuration,
new RowIntervalAction(sourceRectangle, this.targetRectangle, widthFactor, heightFactor, source, destination));
new RowIntervalOperation(sourceRectangle, this.targetRectangle, widthFactor, heightFactor, source, destination));
return;
}
@ -147,7 +147,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
base.Dispose(disposing);
}
private readonly struct RowIntervalAction : IRowIntervalAction
private readonly struct RowIntervalOperation : IRowIntervalOperation
{
private readonly Rectangle sourceBounds;
private readonly Rectangle destinationBounds;
@ -157,7 +157,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
private readonly ImageFrame<TPixel> destination;
[MethodImpl(InliningOptions.ShortMethod)]
public RowIntervalAction(
public RowIntervalOperation(
Rectangle sourceBounds,
Rectangle destinationBounds,
float widthFactor,

18
src/ImageSharp/Processing/Processors/Transforms/RotateProcessor{TPixel}.cs

@ -134,7 +134,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
ParallelRowIterator.IterateRows(
source.Bounds(),
configuration,
new Rotate180RowIntervalAction(source.Width, source.Height, source, destination));
new Rotate180RowIntervalOperation(source.Width, source.Height, source, destination));
}
/// <summary>
@ -148,7 +148,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
ParallelRowIterator.IterateRows(
source.Bounds(),
configuration,
new Rotate270RowIntervalAction(destination.Bounds(), source.Width, source.Height, source, destination));
new Rotate270RowIntervalOperation(destination.Bounds(), source.Width, source.Height, source, destination));
}
/// <summary>
@ -162,10 +162,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
ParallelRowIterator.IterateRows(
source.Bounds(),
configuration,
new Rotate90RowIntervalAction(destination.Bounds(), source.Width, source.Height, source, destination));
new Rotate90RowIntervalOperation(destination.Bounds(), source.Width, source.Height, source, destination));
}
private readonly struct Rotate180RowIntervalAction : IRowIntervalAction
private readonly struct Rotate180RowIntervalOperation : IRowIntervalOperation
{
private readonly int width;
private readonly int height;
@ -173,7 +173,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
private readonly ImageFrame<TPixel> destination;
[MethodImpl(InliningOptions.ShortMethod)]
public Rotate180RowIntervalAction(
public Rotate180RowIntervalOperation(
int width,
int height,
ImageFrame<TPixel> source,
@ -201,7 +201,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
}
}
private readonly struct Rotate270RowIntervalAction : IRowIntervalAction
private readonly struct Rotate270RowIntervalOperation : IRowIntervalOperation
{
private readonly Rectangle bounds;
private readonly int width;
@ -210,7 +210,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
private readonly ImageFrame<TPixel> destination;
[MethodImpl(InliningOptions.ShortMethod)]
public Rotate270RowIntervalAction(
public Rotate270RowIntervalOperation(
Rectangle bounds,
int width,
int height,
@ -245,7 +245,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
}
}
private readonly struct Rotate90RowIntervalAction : IRowIntervalAction
private readonly struct Rotate90RowIntervalOperation : IRowIntervalOperation
{
private readonly Rectangle bounds;
private readonly int width;
@ -254,7 +254,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
private readonly ImageFrame<TPixel> destination;
[MethodImpl(InliningOptions.ShortMethod)]
public Rotate90RowIntervalAction(
public Rotate90RowIntervalOperation(
Rectangle bounds,
int width,
int height,

Loading…
Cancel
Save