Browse Source

Refactor processors to single row with buffer APIs

af/octree-no-pixelmap
Sergio Pedri 6 years ago
parent
commit
5708137dbd
  1. 38
      src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor{TPixel}.cs
  2. 84
      src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor{TPixel}.cs
  3. 84
      src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor{TPixel}.cs
  4. 80
      src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor{TPixel}.cs
  5. 27
      src/ImageSharp/Processing/Processors/Effects/PixelRowDelegateProcessor{TPixel,TDelegate}.cs
  6. 25
      src/ImageSharp/Processing/Processors/Filters/FilterProcessor{TPixel}.cs
  7. 36
      src/ImageSharp/Processing/Processors/Overlays/GlowProcessor{TPixel}.cs
  8. 38
      src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor{TPixel}.cs
  9. 58
      src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor{TPixel}.cs
  10. 69
      src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor{TPixel}.cs

38
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.IterateRows2<ApplyGammaExposureRowAction, Vector4>(
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<Vector4> processingBuffer = this.Configuration.MemoryAllocator.Allocate2D<Vector4>(source.Size(), AllocationOptions.Clean);
@ -416,7 +416,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 ApplyGammaExposureRowAction : IRowAction<Vector4>
{
private readonly Rectangle bounds;
private readonly Buffer2D<TPixel> targetPixels;
@ -424,7 +424,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
private readonly float gamma;
[MethodImpl(InliningOptions.ShortMethod)]
public ApplyGammaExposureRowIntervalAction(
public ApplyGammaExposureRowAction(
Rectangle bounds,
Buffer2D<TPixel> targetPixels,
Configuration configuration,
@ -438,27 +438,23 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void Invoke(in RowInterval rows, Memory<Vector4> memory)
public void Invoke(int y, Span<Vector4> span)
{
Span<Vector4> vectorSpan = memory.Span;
int length = vectorSpan.Length;
int length = span.Length;
for (int y = rows.Min; y < rows.Max; y++)
{
Span<TPixel> targetRowSpan = this.targetPixels.GetRowSpan(y).Slice(this.bounds.X);
PixelOperations<TPixel>.Instance.ToVector4(this.configuration, targetRowSpan.Slice(0, length), vectorSpan, PixelConversionModifiers.Premultiply);
ref Vector4 baseRef = ref MemoryMarshal.GetReference(vectorSpan);
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<TPixel> targetRowSpan = this.targetPixels.GetRowSpan(y).Slice(this.bounds.X);
PixelOperations<TPixel>.Instance.ToVector4(this.configuration, targetRowSpan.Slice(0, length), span, PixelConversionModifiers.Premultiply);
ref Vector4 baseRef = ref MemoryMarshal.GetReference(span);
PixelOperations<TPixel>.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<TPixel>.Instance.FromVector4Destructive(this.configuration, span.Slice(0, length), targetRowSpan);
}
}

84
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.IterateRows2<RowAction, Vector4>(
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<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 RowAction : IRowAction<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 RowAction(
Rectangle bounds,
Buffer2D<TPixel> targetPixels,
Buffer2D<TPixel> sourcePixels,
@ -112,54 +112,50 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void Invoke(in RowInterval rows, Memory<Vector4> memory)
public void Invoke(int y, Span<Vector4> span)
{
Span<Vector4> 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<TPixel> targetRowSpan = this.targetPixels.GetRowSpan(y).Slice(this.bounds.X);
PixelOperations<TPixel>.Instance.ToVector4(this.configuration, targetRowSpan.Slice(0, length), vectorSpan);
Span<TPixel> targetRowSpan = this.targetPixels.GetRowSpan(y).Slice(this.bounds.X);
PixelOperations<TPixel>.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<TPixel>.Instance.FromVector4Destructive(this.configuration, vectorSpan, targetRowSpan);
}
PixelOperations<TPixel>.Instance.FromVector4Destructive(this.configuration, span, targetRowSpan);
}
}
}

84
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.IterateRows2<RowAction, Vector4>(
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<RowIntervalAction, Vector4>(
ParallelRowIterator.IterateRows2<RowAction, Vector4>(
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));
}
/// <summary>
/// A <see langword="struct"/> implementing the convolution logic for <see cref="Convolution2PassProcessor{T}"/>.
/// </summary>
private readonly struct RowIntervalAction : IRowIntervalAction<Vector4>
private readonly struct RowAction : IRowAction<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 RowAction(
Rectangle bounds,
Buffer2D<TPixel> targetPixels,
Buffer2D<TPixel> sourcePixels,
@ -107,55 +107,51 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void Invoke(in RowInterval rows, Memory<Vector4> memory)
public void Invoke(int y, Span<Vector4> span)
{
Span<Vector4> 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<TPixel> targetRowSpan = this.targetPixels.GetRowSpan(y).Slice(this.bounds.X);
PixelOperations<TPixel>.Instance.ToVector4(this.configuration, targetRowSpan.Slice(0, length), vectorSpan);
Span<TPixel> targetRowSpan = this.targetPixels.GetRowSpan(y).Slice(this.bounds.X);
PixelOperations<TPixel>.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<TPixel>.Instance.FromVector4Destructive(this.configuration, vectorSpan, targetRowSpan);
}
PixelOperations<TPixel>.Instance.FromVector4Destructive(this.configuration, span, targetRowSpan);
}
}
}

80
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.IterateRows2<RowAction, Vector4>(
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<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 RowAction : IRowAction<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 RowAction(
Rectangle bounds,
Buffer2D<TPixel> targetPixels,
Buffer2D<TPixel> sourcePixels,
@ -100,52 +100,48 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void Invoke(in RowInterval rows, Memory<Vector4> memory)
public void Invoke(int y, Span<Vector4> span)
{
Span<Vector4> 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<TPixel> targetRowSpan = this.targetPixels.GetRowSpan(y).Slice(this.bounds.X);
PixelOperations<TPixel>.Instance.ToVector4(this.configuration, targetRowSpan.Slice(0, length), vectorSpan);
Span<TPixel> targetRowSpan = this.targetPixels.GetRowSpan(y).Slice(this.bounds.X);
PixelOperations<TPixel>.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<TPixel>.Instance.FromVector4Destructive(this.configuration, vectorSpan, targetRowSpan);
}
PixelOperations<TPixel>.Instance.FromVector4Destructive(this.configuration, span, targetRowSpan);
}
}
}

27
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<RowIntervalAction, Vector4>(
ParallelRowIterator.IterateRows2<RowAction, Vector4>(
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));
}
/// <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 RowAction : IRowAction<Vector4>
{
private readonly int startX;
private readonly ImageFrame<TPixel> 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<TPixel> source,
Configuration configuration,
@ -85,20 +84,16 @@ namespace SixLabors.ImageSharp.Processing.Processors.Effects
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void Invoke(in RowInterval rows, Memory<Vector4> memory)
public void Invoke(int y, Span<Vector4> span)
{
for (int y = rows.Min; y < rows.Max; y++)
{
Span<Vector4> vectorSpan = memory.Span;
int length = vectorSpan.Length;
Span<TPixel> rowSpan = this.source.GetPixelRowSpan(y).Slice(this.startX, length);
PixelOperations<TPixel>.Instance.ToVector4(this.configuration, rowSpan, vectorSpan, this.modifiers);
int length = span.Length;
Span<TPixel> rowSpan = this.source.GetPixelRowSpan(y).Slice(this.startX, length);
PixelOperations<TPixel>.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<TPixel>.Instance.FromVector4Destructive(this.configuration, vectorSpan, rowSpan, this.modifiers);
}
PixelOperations<TPixel>.Instance.FromVector4Destructive(this.configuration, span, rowSpan, this.modifiers);
}
}
}

25
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<RowIntervalAction, Vector4>(
ParallelRowIterator.IterateRows2<RowAction, Vector4>(
interest,
this.Configuration,
new RowIntervalAction(interest.X, source, this.definition.Matrix, this.Configuration));
new RowAction(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 RowAction : IRowAction<Vector4>
{
private readonly int startX;
private readonly ImageFrame<TPixel> 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<TPixel> source,
ColorMatrix matrix,
@ -68,19 +67,15 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void Invoke(in RowInterval rows, Memory<Vector4> memory)
public void Invoke(int y, Span<Vector4> span)
{
for (int y = rows.Min; y < rows.Max; y++)
{
Span<Vector4> vectorSpan = memory.Span;
int length = vectorSpan.Length;
Span<TPixel> rowSpan = this.source.GetPixelRowSpan(y).Slice(this.startX, length);
PixelOperations<TPixel>.Instance.ToVector4(this.configuration, rowSpan, vectorSpan);
int length = span.Length;
Span<TPixel> rowSpan = this.source.GetPixelRowSpan(y).Slice(this.startX, length);
PixelOperations<TPixel>.Instance.ToVector4(this.configuration, rowSpan, span);
Vector4Utils.Transform(vectorSpan, ref Unsafe.AsRef(this.matrix));
Vector4Utils.Transform(span, ref Unsafe.AsRef(this.matrix));
PixelOperations<TPixel>.Instance.FromVector4Destructive(this.configuration, vectorSpan, rowSpan);
}
PixelOperations<TPixel>.Instance.FromVector4Destructive(this.configuration, span, rowSpan);
}
}
}

36
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.IterateRows2<RowAction, float>(
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<float>
private readonly struct RowAction : IRowAction<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 RowAction(
Configuration configuration,
Rectangle bounds,
IMemoryOwner<TPixel> colors,
@ -94,28 +94,24 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays
}
[MethodImpl(InliningOptions.ShortMethod)]
public void Invoke(in RowInterval rows, Memory<float> memory)
public void Invoke(int y, Span<float> span)
{
Span<float> amountsSpan = memory.Span;
Span<TPixel> 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<TPixel> destination = this.source.GetPixelRowSpan(y).Slice(this.bounds.X, this.bounds.Width);
Span<TPixel> 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);
}
}
}

38
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.IterateRows2<RowAction, float>(
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<float>
private readonly struct RowAction : IRowAction<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 RowAction(
Configuration configuration,
Rectangle bounds,
IMemoryOwner<TPixel> colors,
@ -102,28 +102,24 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays
}
[MethodImpl(InliningOptions.ShortMethod)]
public void Invoke(in RowInterval rows, Memory<float> memory)
public void Invoke(int y, Span<float> span)
{
Span<float> amountsSpan = memory.Span;
Span<TPixel> 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<TPixel> 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<TPixel> destination = this.source.GetPixelRowSpan(y).Slice(this.bounds.X, this.bounds.Width);
this.blender.Blend(
this.configuration,
destination,
destination,
colorSpan,
span);
}
}
}

58
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
@ -68,10 +67,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
using var kernelMap = new TransformKernelMap(configuration, source.Size(), destination.Size(), this.resampler);
ParallelRowIterator.IterateRows<RowIntervalAction, Vector4>(
ParallelRowIterator.IterateRows2<RowAction, Vector4>(
targetBounds,
configuration,
new RowIntervalAction(configuration, kernelMap, ref matrix, width, source, destination));
new RowAction(configuration, kernelMap, ref matrix, width, source, destination));
}
/// <summary>
@ -101,7 +100,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
}
/// <inheritdoc/>
/// <param name="rows"></param>
[MethodImpl(InliningOptions.ShortMethod)]
public void Invoke(int y)
{
@ -121,7 +119,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 RowAction : IRowAction<Vector4>
{
private readonly Configuration configuration;
private readonly TransformKernelMap kernelMap;
@ -131,7 +129,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
private readonly ImageFrame<TPixel> destination;
[MethodImpl(InliningOptions.ShortMethod)]
public RowIntervalAction(
public RowAction(
Configuration configuration,
TransformKernelMap kernelMap,
ref Matrix3x2 matrix,
@ -149,35 +147,31 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void Invoke(in RowInterval rows, Memory<Vector4> memory)
public void Invoke(int y, Span<Vector4> span)
{
Span<Vector4> vectorSpan = memory.Span;
for (int y = rows.Min; y < rows.Max; y++)
{
Span<TPixel> targetRowSpan = this.destination.GetPixelRowSpan(y);
PixelOperations<TPixel>.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<TPixel> targetRowSpan = this.destination.GetPixelRowSpan(y);
PixelOperations<TPixel>.Instance.ToVector4(this.configuration, targetRowSpan, span);
ref float ySpanRef = ref this.kernelMap.GetYStartReference(y);
ref float xSpanRef = ref this.kernelMap.GetXStartReference(y);
PixelOperations<TPixel>.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<TPixel>.Instance.FromVector4Destructive(
this.configuration,
span,
targetRowSpan);
}
}
}

69
src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor{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
@ -17,9 +16,9 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
internal class ProjectiveTransformProcessor<TPixel> : TransformProcessor<TPixel>
where TPixel : struct, IPixel<TPixel>
{
private Size targetSize;
private readonly Size targetSize;
private readonly IResampler resampler;
private Matrix4x4 transformMatrix;
private readonly Matrix4x4 transformMatrix;
/// <summary>
/// Initializes a new instance of the <see cref="ProjectiveTransformProcessor{TPixel}"/> class.
@ -70,12 +69,15 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
using var kernelMap = new TransformKernelMap(configuration, source.Size(), destination.Size(), this.resampler);
ParallelRowIterator.IterateRows<RowIntervalAction, Vector4>(
ParallelRowIterator.IterateRows2<RowAction, Vector4>(
targetBounds,
configuration,
new RowIntervalAction(configuration, kernelMap, ref matrix, width, source, destination));
new RowAction(configuration, kernelMap, ref matrix, width, source, destination));
}
/// <summary>
/// A <see langword="struct"/> implementing the nearest neighbor interpolation logic for <see cref="ProjectiveTransformProcessor{T}"/>.
/// </summary>
private readonly struct NearestNeighborRowAction : IRowAction
{
private readonly Rectangle bounds;
@ -99,6 +101,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
this.destination = destination;
}
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void Invoke(int y)
{
@ -118,7 +121,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
}
}
private readonly struct RowIntervalAction : IRowIntervalAction<Vector4>
/// <summary>
/// A <see langword="struct"/> implementing the convolution logic for <see cref="ProjectiveTransformProcessor{T}"/>.
/// </summary>
private readonly struct RowAction : IRowAction<Vector4>
{
private readonly Configuration configuration;
private readonly TransformKernelMap kernelMap;
@ -128,7 +134,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
private readonly ImageFrame<TPixel> destination;
[MethodImpl(InliningOptions.ShortMethod)]
public RowIntervalAction(
public RowAction(
Configuration configuration,
TransformKernelMap kernelMap,
ref Matrix4x4 matrix,
@ -144,36 +150,33 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
this.destination = destination;
}
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void Invoke(in RowInterval rows, Memory<Vector4> memory)
public void Invoke(int y, Span<Vector4> span)
{
Span<Vector4> vectorSpan = memory.Span;
for (int y = rows.Min; y < rows.Max; y++)
{
Span<TPixel> targetRowSpan = this.destination.GetPixelRowSpan(y);
PixelOperations<TPixel>.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.
Vector2 point = TransformUtils.ProjectiveTransform2D(x, y, this.matrix);
this.kernelMap.Convolve(
point,
x,
ref ySpanRef,
ref xSpanRef,
this.source.PixelBuffer,
vectorSpan);
}
Span<TPixel> targetRowSpan = this.destination.GetPixelRowSpan(y);
PixelOperations<TPixel>.Instance.ToVector4(this.configuration, targetRowSpan, span);
ref float ySpanRef = ref this.kernelMap.GetYStartReference(y);
ref float xSpanRef = ref this.kernelMap.GetXStartReference(y);
PixelOperations<TPixel>.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.
Vector2 point = TransformUtils.ProjectiveTransform2D(x, y, this.matrix);
this.kernelMap.Convolve(
point,
x,
ref ySpanRef,
ref xSpanRef,
this.source.PixelBuffer,
span);
}
PixelOperations<TPixel>.Instance.FromVector4Destructive(
this.configuration,
span,
targetRowSpan);
}
}
}

Loading…
Cancel
Save