Browse Source

Refactor processors to single row with buffer APIs

af/octree-no-pixelmap
Sergio Pedri 7 years ago
parent
commit
5708137dbd
  1. 22
      src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor{TPixel}.cs
  2. 22
      src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor{TPixel}.cs
  3. 26
      src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor{TPixel}.cs
  4. 22
      src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor{TPixel}.cs
  5. 23
      src/ImageSharp/Processing/Processors/Effects/PixelRowDelegateProcessor{TPixel,TDelegate}.cs
  6. 23
      src/ImageSharp/Processing/Processors/Filters/FilterProcessor{TPixel}.cs
  7. 18
      src/ImageSharp/Processing/Processors/Overlays/GlowProcessor{TPixel}.cs
  8. 18
      src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor{TPixel}.cs
  9. 22
      src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor{TPixel}.cs
  10. 33
      src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor{TPixel}.cs

22
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) protected override void OnFrameApply(ImageFrame<TPixel> source)
{ {
// Preliminary gamma highlight pass // Preliminary gamma highlight pass
ParallelRowIterator.IterateRows<ApplyGammaExposureRowIntervalAction, Vector4>( ParallelRowIterator.IterateRows2<ApplyGammaExposureRowAction, Vector4>(
this.SourceRectangle, this.SourceRectangle,
this.Configuration, 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 // 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); using Buffer2D<Vector4> processingBuffer = this.Configuration.MemoryAllocator.Allocate2D<Vector4>(source.Size(), AllocationOptions.Clean);
@ -416,7 +416,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
/// <summary> /// <summary>
/// A <see langword="struct"/> implementing the gamma exposure logic for <see cref="BokehBlurProcessor{T}"/>. /// A <see langword="struct"/> implementing the gamma exposure logic for <see cref="BokehBlurProcessor{T}"/>.
/// </summary> /// </summary>
private readonly struct ApplyGammaExposureRowIntervalAction : IRowIntervalAction<Vector4> private readonly struct ApplyGammaExposureRowAction : IRowAction<Vector4>
{ {
private readonly Rectangle bounds; private readonly Rectangle bounds;
private readonly Buffer2D<TPixel> targetPixels; private readonly Buffer2D<TPixel> targetPixels;
@ -424,7 +424,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
private readonly float gamma; private readonly float gamma;
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(InliningOptions.ShortMethod)]
public ApplyGammaExposureRowIntervalAction( public ApplyGammaExposureRowAction(
Rectangle bounds, Rectangle bounds,
Buffer2D<TPixel> targetPixels, Buffer2D<TPixel> targetPixels,
Configuration configuration, Configuration configuration,
@ -438,16 +438,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
/// <inheritdoc/> /// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)] [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 = span.Length;
int length = vectorSpan.Length;
for (int y = rows.Min; y < rows.Max; y++)
{
Span<TPixel> targetRowSpan = this.targetPixels.GetRowSpan(y).Slice(this.bounds.X); Span<TPixel> targetRowSpan = this.targetPixels.GetRowSpan(y).Slice(this.bounds.X);
PixelOperations<TPixel>.Instance.ToVector4(this.configuration, targetRowSpan.Slice(0, length), vectorSpan, PixelConversionModifiers.Premultiply); PixelOperations<TPixel>.Instance.ToVector4(this.configuration, targetRowSpan.Slice(0, length), span, PixelConversionModifiers.Premultiply);
ref Vector4 baseRef = ref MemoryMarshal.GetReference(vectorSpan); ref Vector4 baseRef = ref MemoryMarshal.GetReference(span);
for (int x = 0; x < this.bounds.Width; x++) for (int x = 0; x < this.bounds.Width; x++)
{ {
@ -457,8 +454,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
v.Z = MathF.Pow(v.Z, this.gamma); v.Z = MathF.Pow(v.Z, this.gamma);
} }
PixelOperations<TPixel>.Instance.FromVector4Destructive(this.configuration, vectorSpan.Slice(0, length), targetRowSpan); PixelOperations<TPixel>.Instance.FromVector4Destructive(this.configuration, span.Slice(0, length), targetRowSpan);
}
} }
} }

22
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()); var interest = Rectangle.Intersect(this.SourceRectangle, source.Bounds());
ParallelRowIterator.IterateRows<RowIntervalAction, Vector4>( ParallelRowIterator.IterateRows2<RowAction, Vector4>(
interest, interest,
this.Configuration, 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); Buffer2D<TPixel>.SwapOrCopyContent(source.PixelBuffer, targetPixels);
} }
@ -77,7 +77,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
/// <summary> /// <summary>
/// A <see langword="struct"/> implementing the convolution logic for <see cref="Convolution2DProcessor{T}"/>. /// A <see langword="struct"/> implementing the convolution logic for <see cref="Convolution2DProcessor{T}"/>.
/// </summary> /// </summary>
private readonly struct RowIntervalAction : IRowIntervalAction<Vector4> private readonly struct RowAction : IRowAction<Vector4>
{ {
private readonly Rectangle bounds; private readonly Rectangle bounds;
private readonly int maxY; private readonly int maxY;
@ -90,7 +90,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
private readonly bool preserveAlpha; private readonly bool preserveAlpha;
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(InliningOptions.ShortMethod)]
public RowIntervalAction( public RowAction(
Rectangle bounds, Rectangle bounds,
Buffer2D<TPixel> targetPixels, Buffer2D<TPixel> targetPixels,
Buffer2D<TPixel> sourcePixels, Buffer2D<TPixel> sourcePixels,
@ -112,16 +112,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
/// <inheritdoc/> /// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)] [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 = span.Length;
int length = vectorSpan.Length; ref Vector4 vectorSpanRef = ref MemoryMarshal.GetReference(span);
ref Vector4 vectorSpanRef = ref MemoryMarshal.GetReference(vectorSpan);
for (int y = rows.Min; y < rows.Max; y++)
{
Span<TPixel> targetRowSpan = this.targetPixels.GetRowSpan(y).Slice(this.bounds.X); Span<TPixel> targetRowSpan = this.targetPixels.GetRowSpan(y).Slice(this.bounds.X);
PixelOperations<TPixel>.Instance.ToVector4(this.configuration, targetRowSpan.Slice(0, length), vectorSpan); PixelOperations<TPixel>.Instance.ToVector4(this.configuration, targetRowSpan.Slice(0, length), span);
if (this.preserveAlpha) if (this.preserveAlpha)
{ {
@ -158,8 +155,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
} }
} }
PixelOperations<TPixel>.Instance.FromVector4Destructive(this.configuration, vectorSpan, targetRowSpan); PixelOperations<TPixel>.Instance.FromVector4Destructive(this.configuration, span, targetRowSpan);
}
} }
} }
} }

26
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()); var interest = Rectangle.Intersect(this.SourceRectangle, source.Bounds());
// Horizontal convolution // Horizontal convolution
ParallelRowIterator.IterateRows<RowIntervalAction, Vector4>( ParallelRowIterator.IterateRows2<RowAction, Vector4>(
interest, interest,
this.Configuration, 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 // Vertical convolution
ParallelRowIterator.IterateRows<RowIntervalAction, Vector4>( ParallelRowIterator.IterateRows2<RowAction, Vector4>(
interest, interest,
this.Configuration, 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> /// <summary>
/// A <see langword="struct"/> implementing the convolution logic for <see cref="Convolution2PassProcessor{T}"/>. /// A <see langword="struct"/> implementing the convolution logic for <see cref="Convolution2PassProcessor{T}"/>.
/// </summary> /// </summary>
private readonly struct RowIntervalAction : IRowIntervalAction<Vector4> private readonly struct RowAction : IRowAction<Vector4>
{ {
private readonly Rectangle bounds; private readonly Rectangle bounds;
private readonly Buffer2D<TPixel> targetPixels; private readonly Buffer2D<TPixel> targetPixels;
@ -89,7 +89,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
private readonly bool preserveAlpha; private readonly bool preserveAlpha;
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(InliningOptions.ShortMethod)]
public RowIntervalAction( public RowAction(
Rectangle bounds, Rectangle bounds,
Buffer2D<TPixel> targetPixels, Buffer2D<TPixel> targetPixels,
Buffer2D<TPixel> sourcePixels, Buffer2D<TPixel> sourcePixels,
@ -107,19 +107,16 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
/// <inheritdoc/> /// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)] [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 = span.Length;
int length = vectorSpan.Length; ref Vector4 vectorSpanRef = ref MemoryMarshal.GetReference(span);
ref Vector4 vectorSpanRef = ref MemoryMarshal.GetReference(vectorSpan);
int maxY = this.bounds.Bottom - 1; int maxY = this.bounds.Bottom - 1;
int maxX = this.bounds.Right - 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); Span<TPixel> targetRowSpan = this.targetPixels.GetRowSpan(y).Slice(this.bounds.X);
PixelOperations<TPixel>.Instance.ToVector4(this.configuration, targetRowSpan.Slice(0, length), vectorSpan); PixelOperations<TPixel>.Instance.ToVector4(this.configuration, targetRowSpan.Slice(0, length), span);
if (this.preserveAlpha) if (this.preserveAlpha)
{ {
@ -154,8 +151,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
} }
} }
PixelOperations<TPixel>.Instance.FromVector4Destructive(this.configuration, vectorSpan, targetRowSpan); PixelOperations<TPixel>.Instance.FromVector4Destructive(this.configuration, span, targetRowSpan);
}
} }
} }
} }

22
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()); var interest = Rectangle.Intersect(this.SourceRectangle, source.Bounds());
ParallelRowIterator.IterateRows<RowIntervalAction, Vector4>( ParallelRowIterator.IterateRows2<RowAction, Vector4>(
interest, interest,
this.Configuration, 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); Buffer2D<TPixel>.SwapOrCopyContent(source.PixelBuffer, targetPixels);
} }
@ -68,7 +68,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
/// <summary> /// <summary>
/// A <see langword="struct"/> implementing the convolution logic for <see cref="ConvolutionProcessor{T}"/>. /// A <see langword="struct"/> implementing the convolution logic for <see cref="ConvolutionProcessor{T}"/>.
/// </summary> /// </summary>
private readonly struct RowIntervalAction : IRowIntervalAction<Vector4> private readonly struct RowAction : IRowAction<Vector4>
{ {
private readonly Rectangle bounds; private readonly Rectangle bounds;
private readonly int maxY; private readonly int maxY;
@ -80,7 +80,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
private readonly bool preserveAlpha; private readonly bool preserveAlpha;
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(InliningOptions.ShortMethod)]
public RowIntervalAction( public RowAction(
Rectangle bounds, Rectangle bounds,
Buffer2D<TPixel> targetPixels, Buffer2D<TPixel> targetPixels,
Buffer2D<TPixel> sourcePixels, Buffer2D<TPixel> sourcePixels,
@ -100,16 +100,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
/// <inheritdoc/> /// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)] [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 = span.Length;
int length = vectorSpan.Length; ref Vector4 vectorSpanRef = ref MemoryMarshal.GetReference(span);
ref Vector4 vectorSpanRef = ref MemoryMarshal.GetReference(vectorSpan);
for (int y = rows.Min; y < rows.Max; y++)
{
Span<TPixel> targetRowSpan = this.targetPixels.GetRowSpan(y).Slice(this.bounds.X); Span<TPixel> targetRowSpan = this.targetPixels.GetRowSpan(y).Slice(this.bounds.X);
PixelOperations<TPixel>.Instance.ToVector4(this.configuration, targetRowSpan.Slice(0, length), vectorSpan); PixelOperations<TPixel>.Instance.ToVector4(this.configuration, targetRowSpan.Slice(0, length), span);
if (this.preserveAlpha) if (this.preserveAlpha)
{ {
@ -144,8 +141,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
} }
} }
PixelOperations<TPixel>.Instance.FromVector4Destructive(this.configuration, vectorSpan, targetRowSpan); PixelOperations<TPixel>.Instance.FromVector4Destructive(this.configuration, span, targetRowSpan);
}
} }
} }
} }

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

@ -5,7 +5,6 @@ using System;
using System.Numerics; using System.Numerics;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Processing.Processors.Effects namespace SixLabors.ImageSharp.Processing.Processors.Effects
@ -51,16 +50,16 @@ namespace SixLabors.ImageSharp.Processing.Processors.Effects
{ {
var interest = Rectangle.Intersect(this.SourceRectangle, source.Bounds()); var interest = Rectangle.Intersect(this.SourceRectangle, source.Bounds());
ParallelRowIterator.IterateRows<RowIntervalAction, Vector4>( ParallelRowIterator.IterateRows2<RowAction, Vector4>(
interest, interest,
this.Configuration, 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> /// <summary>
/// A <see langword="struct"/> implementing the convolution logic for <see cref="PixelRowDelegateProcessor{TPixel,TDelegate}"/>. /// A <see langword="struct"/> implementing the convolution logic for <see cref="PixelRowDelegateProcessor{TPixel,TDelegate}"/>.
/// </summary> /// </summary>
private readonly struct RowIntervalAction : IRowIntervalAction<Vector4> private readonly struct RowAction : IRowAction<Vector4>
{ {
private readonly int startX; private readonly int startX;
private readonly ImageFrame<TPixel> source; private readonly ImageFrame<TPixel> source;
@ -69,7 +68,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Effects
private readonly TDelegate rowProcessor; private readonly TDelegate rowProcessor;
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(InliningOptions.ShortMethod)]
public RowIntervalAction( public RowAction(
int startX, int startX,
ImageFrame<TPixel> source, ImageFrame<TPixel> source,
Configuration configuration, Configuration configuration,
@ -85,20 +84,16 @@ namespace SixLabors.ImageSharp.Processing.Processors.Effects
/// <inheritdoc/> /// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)] [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++) int length = span.Length;
{
Span<Vector4> vectorSpan = memory.Span;
int length = vectorSpan.Length;
Span<TPixel> rowSpan = this.source.GetPixelRowSpan(y).Slice(this.startX, length); Span<TPixel> rowSpan = this.source.GetPixelRowSpan(y).Slice(this.startX, length);
PixelOperations<TPixel>.Instance.ToVector4(this.configuration, rowSpan, vectorSpan, this.modifiers); PixelOperations<TPixel>.Instance.ToVector4(this.configuration, rowSpan, span, this.modifiers);
// Run the user defined pixel shader to the current row of pixels // Run the user defined pixel shader to the current row of pixels
Unsafe.AsRef(this.rowProcessor).Invoke(vectorSpan, new Point(this.startX, y)); Unsafe.AsRef(this.rowProcessor).Invoke(span, new Point(this.startX, y));
PixelOperations<TPixel>.Instance.FromVector4Destructive(this.configuration, vectorSpan, rowSpan, this.modifiers); PixelOperations<TPixel>.Instance.FromVector4Destructive(this.configuration, span, rowSpan, this.modifiers);
}
} }
} }
} }

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

@ -5,7 +5,6 @@ using System;
using System.Numerics; using System.Numerics;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Processing.Processors.Filters namespace SixLabors.ImageSharp.Processing.Processors.Filters
@ -37,16 +36,16 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters
{ {
var interest = Rectangle.Intersect(this.SourceRectangle, source.Bounds()); var interest = Rectangle.Intersect(this.SourceRectangle, source.Bounds());
ParallelRowIterator.IterateRows<RowIntervalAction, Vector4>( ParallelRowIterator.IterateRows2<RowAction, Vector4>(
interest, interest,
this.Configuration, this.Configuration,
new RowIntervalAction(interest.X, source, this.definition.Matrix, this.Configuration)); new RowAction(interest.X, source, this.definition.Matrix, this.Configuration));
} }
/// <summary> /// <summary>
/// A <see langword="struct"/> implementing the convolution logic for <see cref="FilterProcessor{TPixel}"/>. /// A <see langword="struct"/> implementing the convolution logic for <see cref="FilterProcessor{TPixel}"/>.
/// </summary> /// </summary>
private readonly struct RowIntervalAction : IRowIntervalAction<Vector4> private readonly struct RowAction : IRowAction<Vector4>
{ {
private readonly int startX; private readonly int startX;
private readonly ImageFrame<TPixel> source; private readonly ImageFrame<TPixel> source;
@ -54,7 +53,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters
private readonly Configuration configuration; private readonly Configuration configuration;
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(InliningOptions.ShortMethod)]
public RowIntervalAction( public RowAction(
int startX, int startX,
ImageFrame<TPixel> source, ImageFrame<TPixel> source,
ColorMatrix matrix, ColorMatrix matrix,
@ -68,19 +67,15 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters
/// <inheritdoc/> /// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)] [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++) int length = span.Length;
{
Span<Vector4> vectorSpan = memory.Span;
int length = vectorSpan.Length;
Span<TPixel> rowSpan = this.source.GetPixelRowSpan(y).Slice(this.startX, length); Span<TPixel> rowSpan = this.source.GetPixelRowSpan(y).Slice(this.startX, length);
PixelOperations<TPixel>.Instance.ToVector4(this.configuration, rowSpan, vectorSpan); 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);
}
} }
} }
} }

18
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); using IMemoryOwner<TPixel> rowColors = allocator.Allocate<TPixel>(interest.Width);
rowColors.GetSpan().Fill(glowColor); rowColors.GetSpan().Fill(glowColor);
ParallelRowIterator.IterateRows<RowIntervalAction, float>( ParallelRowIterator.IterateRows2<RowAction, float>(
interest, interest,
configuration, 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 Configuration configuration;
private readonly Rectangle bounds; private readonly Rectangle bounds;
@ -73,7 +73,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays
private readonly ImageFrame<TPixel> source; private readonly ImageFrame<TPixel> source;
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(InliningOptions.ShortMethod)]
public RowIntervalAction( public RowAction(
Configuration configuration, Configuration configuration,
Rectangle bounds, Rectangle bounds,
IMemoryOwner<TPixel> colors, IMemoryOwner<TPixel> colors,
@ -94,17 +94,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays
} }
[MethodImpl(InliningOptions.ShortMethod)] [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(); 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)); float distance = Vector2.Distance(this.center, new Vector2(i + this.bounds.X, y));
amountsSpan[i] = (this.blendPercent * (1 - (.95F * (distance / this.maxDistance)))).Clamp(0, 1); span[i] = (this.blendPercent * (1 - (.95F * (distance / this.maxDistance)))).Clamp(0, 1);
} }
Span<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);
@ -114,8 +111,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays
destination, destination,
destination, destination,
colorSpan, colorSpan,
amountsSpan); span);
}
} }
} }
} }

18
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); using IMemoryOwner<TPixel> rowColors = allocator.Allocate<TPixel>(interest.Width);
rowColors.GetSpan().Fill(vignetteColor); rowColors.GetSpan().Fill(vignetteColor);
ParallelRowIterator.IterateRows<RowIntervalAction, float>( ParallelRowIterator.IterateRows2<RowAction, float>(
interest, interest,
configuration, 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 Configuration configuration;
private readonly Rectangle bounds; private readonly Rectangle bounds;
@ -81,7 +81,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays
private readonly ImageFrame<TPixel> source; private readonly ImageFrame<TPixel> source;
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(InliningOptions.ShortMethod)]
public RowIntervalAction( public RowAction(
Configuration configuration, Configuration configuration,
Rectangle bounds, Rectangle bounds,
IMemoryOwner<TPixel> colors, IMemoryOwner<TPixel> colors,
@ -102,17 +102,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays
} }
[MethodImpl(InliningOptions.ShortMethod)] [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(); 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)); float distance = Vector2.Distance(this.center, new Vector2(i + this.bounds.X, y));
amountsSpan[i] = (this.blendPercent * (.9F * (distance / this.maxDistance))).Clamp(0, 1); span[i] = (this.blendPercent * (.9F * (distance / this.maxDistance))).Clamp(0, 1);
} }
Span<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);
@ -122,8 +119,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays
destination, destination,
destination, destination,
colorSpan, colorSpan,
amountsSpan); span);
}
} }
} }
} }

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

@ -5,7 +5,6 @@ using System;
using System.Numerics; using System.Numerics;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Processing.Processors.Transforms 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); using var kernelMap = new TransformKernelMap(configuration, source.Size(), destination.Size(), this.resampler);
ParallelRowIterator.IterateRows<RowIntervalAction, Vector4>( ParallelRowIterator.IterateRows2<RowAction, Vector4>(
targetBounds, targetBounds,
configuration, configuration,
new RowIntervalAction(configuration, kernelMap, ref matrix, width, source, destination)); new RowAction(configuration, kernelMap, ref matrix, width, source, destination));
} }
/// <summary> /// <summary>
@ -101,7 +100,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
} }
/// <inheritdoc/> /// <inheritdoc/>
/// <param name="rows"></param>
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(InliningOptions.ShortMethod)]
public void Invoke(int y) public void Invoke(int y)
{ {
@ -121,7 +119,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
/// <summary> /// <summary>
/// A <see langword="struct"/> implementing the transformation logic for <see cref="AffineTransformProcessor{T}"/>. /// A <see langword="struct"/> implementing the transformation logic for <see cref="AffineTransformProcessor{T}"/>.
/// </summary> /// </summary>
private readonly struct RowIntervalAction : IRowIntervalAction<Vector4> private readonly struct RowAction : IRowAction<Vector4>
{ {
private readonly Configuration configuration; private readonly Configuration configuration;
private readonly TransformKernelMap kernelMap; private readonly TransformKernelMap kernelMap;
@ -131,7 +129,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
private readonly ImageFrame<TPixel> destination; private readonly ImageFrame<TPixel> destination;
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(InliningOptions.ShortMethod)]
public RowIntervalAction( public RowAction(
Configuration configuration, Configuration configuration,
TransformKernelMap kernelMap, TransformKernelMap kernelMap,
ref Matrix3x2 matrix, ref Matrix3x2 matrix,
@ -149,13 +147,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
/// <inheritdoc/> /// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)] [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); Span<TPixel> targetRowSpan = this.destination.GetPixelRowSpan(y);
PixelOperations<TPixel>.Instance.ToVector4(this.configuration, targetRowSpan, vectorSpan); PixelOperations<TPixel>.Instance.ToVector4(this.configuration, targetRowSpan, span);
ref float ySpanRef = ref this.kernelMap.GetYStartReference(y); ref float ySpanRef = ref this.kernelMap.GetYStartReference(y);
ref float xSpanRef = ref this.kernelMap.GetXStartReference(y); ref float xSpanRef = ref this.kernelMap.GetXStartReference(y);
@ -170,15 +165,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
ref ySpanRef, ref ySpanRef,
ref xSpanRef, ref xSpanRef,
this.source.PixelBuffer, this.source.PixelBuffer,
vectorSpan); span);
} }
PixelOperations<TPixel>.Instance.FromVector4Destructive( PixelOperations<TPixel>.Instance.FromVector4Destructive(
this.configuration, this.configuration,
vectorSpan, span,
targetRowSpan); targetRowSpan);
} }
} }
} }
} }
}

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

@ -5,7 +5,6 @@ using System;
using System.Numerics; using System.Numerics;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Processing.Processors.Transforms namespace SixLabors.ImageSharp.Processing.Processors.Transforms
@ -17,9 +16,9 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
internal class ProjectiveTransformProcessor<TPixel> : TransformProcessor<TPixel> internal class ProjectiveTransformProcessor<TPixel> : TransformProcessor<TPixel>
where TPixel : struct, IPixel<TPixel> where TPixel : struct, IPixel<TPixel>
{ {
private Size targetSize; private readonly Size targetSize;
private readonly IResampler resampler; private readonly IResampler resampler;
private Matrix4x4 transformMatrix; private readonly Matrix4x4 transformMatrix;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="ProjectiveTransformProcessor{TPixel}"/> class. /// 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); using var kernelMap = new TransformKernelMap(configuration, source.Size(), destination.Size(), this.resampler);
ParallelRowIterator.IterateRows<RowIntervalAction, Vector4>( ParallelRowIterator.IterateRows2<RowAction, Vector4>(
targetBounds, targetBounds,
configuration, 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 struct NearestNeighborRowAction : IRowAction
{ {
private readonly Rectangle bounds; private readonly Rectangle bounds;
@ -99,6 +101,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
this.destination = destination; this.destination = destination;
} }
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(InliningOptions.ShortMethod)]
public void Invoke(int y) 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 Configuration configuration;
private readonly TransformKernelMap kernelMap; private readonly TransformKernelMap kernelMap;
@ -128,7 +134,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
private readonly ImageFrame<TPixel> destination; private readonly ImageFrame<TPixel> destination;
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(InliningOptions.ShortMethod)]
public RowIntervalAction( public RowAction(
Configuration configuration, Configuration configuration,
TransformKernelMap kernelMap, TransformKernelMap kernelMap,
ref Matrix4x4 matrix, ref Matrix4x4 matrix,
@ -144,14 +150,12 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
this.destination = destination; this.destination = destination;
} }
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)] [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); Span<TPixel> targetRowSpan = this.destination.GetPixelRowSpan(y);
PixelOperations<TPixel>.Instance.ToVector4(this.configuration, targetRowSpan, vectorSpan); PixelOperations<TPixel>.Instance.ToVector4(this.configuration, targetRowSpan, span);
ref float ySpanRef = ref this.kernelMap.GetYStartReference(y); ref float ySpanRef = ref this.kernelMap.GetYStartReference(y);
ref float xSpanRef = ref this.kernelMap.GetXStartReference(y); ref float xSpanRef = ref this.kernelMap.GetXStartReference(y);
@ -166,15 +170,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
ref ySpanRef, ref ySpanRef,
ref xSpanRef, ref xSpanRef,
this.source.PixelBuffer, this.source.PixelBuffer,
vectorSpan); span);
} }
PixelOperations<TPixel>.Instance.FromVector4Destructive( PixelOperations<TPixel>.Instance.FromVector4Destructive(
this.configuration, this.configuration,
vectorSpan, span,
targetRowSpan); targetRowSpan);
} }
} }
} }
} }
}

Loading…
Cancel
Save