Browse Source

Refactored BokehBlurProcessor<TPixel>

pull/1574/head
Sergio Pedri 7 years ago
parent
commit
36f354d07a
  1. 114
      src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor{TPixel}.cs

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

@ -72,8 +72,8 @@ 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
var gammaOperation = new ApplyGammaExposureRowIntervalOperation(this.SourceRectangle, source.PixelBuffer, this.Configuration, this.gamma); var gammaOperation = new ApplyGammaExposureRowOperation(this.SourceRectangle, source.PixelBuffer, this.Configuration, this.gamma);
ParallelRowIterator.IterateRowIntervals<ApplyGammaExposureRowIntervalOperation, Vector4>( ParallelRowIterator.IterateRows<ApplyGammaExposureRowOperation, Vector4>(
this.Configuration, this.Configuration,
this.SourceRectangle, this.SourceRectangle,
in gammaOperation); in gammaOperation);
@ -87,8 +87,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
float inverseGamma = 1 / this.gamma; float inverseGamma = 1 / this.gamma;
// Apply the inverse gamma exposure pass, and write the final pixel data // Apply the inverse gamma exposure pass, and write the final pixel data
var operation = new ApplyInverseGammaExposureRowIntervalOperation(this.SourceRectangle, source.PixelBuffer, processingBuffer, this.Configuration, inverseGamma); var operation = new ApplyInverseGammaExposureRowOperation(this.SourceRectangle, source.PixelBuffer, processingBuffer, this.Configuration, inverseGamma);
ParallelRowIterator.IterateRowIntervals( ParallelRowIterator.IterateRows(
this.Configuration, this.Configuration,
this.SourceRectangle, this.SourceRectangle,
in operation); in operation);
@ -120,15 +120,15 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
Vector4 parameters = Unsafe.Add(ref paramsRef, i); Vector4 parameters = Unsafe.Add(ref paramsRef, i);
// Compute the vertical 1D convolution // Compute the vertical 1D convolution
var verticalOperation = new ApplyVerticalConvolutionRowIntervalOperation(sourceRectangle, firstPassBuffer, source.PixelBuffer, kernel); var verticalOperation = new ApplyVerticalConvolutionRowOperation(sourceRectangle, firstPassBuffer, source.PixelBuffer, kernel);
ParallelRowIterator.IterateRowIntervals( ParallelRowIterator.IterateRows(
configuration, configuration,
sourceRectangle, sourceRectangle,
in verticalOperation); in verticalOperation);
// Compute the horizontal 1D convolutions and accumulate the partial results on the target buffer // Compute the horizontal 1D convolutions and accumulate the partial results on the target buffer
var horizontalOperation = new ApplyHorizontalConvolutionRowIntervalOperation(sourceRectangle, processingBuffer, firstPassBuffer, kernel, parameters.Z, parameters.W); var horizontalOperation = new ApplyHorizontalConvolutionRowOperation(sourceRectangle, processingBuffer, firstPassBuffer, kernel, parameters.Z, parameters.W);
ParallelRowIterator.IterateRowIntervals( ParallelRowIterator.IterateRows(
configuration, configuration,
sourceRectangle, sourceRectangle,
in horizontalOperation); in horizontalOperation);
@ -138,7 +138,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
/// <summary> /// <summary>
/// A <see langword="struct"/> implementing the vertical convolution logic for <see cref="BokehBlurProcessor{T}"/>. /// A <see langword="struct"/> implementing the vertical convolution logic for <see cref="BokehBlurProcessor{T}"/>.
/// </summary> /// </summary>
private readonly struct ApplyVerticalConvolutionRowIntervalOperation : IRowIntervalOperation private readonly struct ApplyVerticalConvolutionRowOperation : IRowOperation
{ {
private readonly Rectangle bounds; private readonly Rectangle bounds;
private readonly Buffer2D<ComplexVector4> targetValues; private readonly Buffer2D<ComplexVector4> targetValues;
@ -148,7 +148,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
private readonly int maxX; private readonly int maxX;
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(InliningOptions.ShortMethod)]
public ApplyVerticalConvolutionRowIntervalOperation( public ApplyVerticalConvolutionRowOperation(
Rectangle bounds, Rectangle bounds,
Buffer2D<ComplexVector4> targetValues, Buffer2D<ComplexVector4> targetValues,
Buffer2D<TPixel> sourcePixels, Buffer2D<TPixel> sourcePixels,
@ -164,16 +164,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
/// <inheritdoc/> /// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(InliningOptions.ShortMethod)]
public void Invoke(in RowInterval rows) public void Invoke(int y)
{ {
for (int y = rows.Min; y < rows.Max; y++) Span<ComplexVector4> targetRowSpan = this.targetValues.GetRowSpan(y).Slice(this.bounds.X);
{
Span<ComplexVector4> targetRowSpan = this.targetValues.GetRowSpan(y).Slice(this.bounds.X);
for (int x = 0; x < this.bounds.Width; x++) for (int x = 0; x < this.bounds.Width; x++)
{ {
Buffer2DUtils.Convolve4(this.kernel, this.sourcePixels, targetRowSpan, y, x, this.bounds.Y, this.maxY, this.bounds.X, this.maxX); Buffer2DUtils.Convolve4(this.kernel, this.sourcePixels, targetRowSpan, y, x, this.bounds.Y, this.maxY, this.bounds.X, this.maxX);
}
} }
} }
} }
@ -181,7 +178,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
/// <summary> /// <summary>
/// A <see langword="struct"/> implementing the horizontal convolution logic for <see cref="BokehBlurProcessor{T}"/>. /// A <see langword="struct"/> implementing the horizontal convolution logic for <see cref="BokehBlurProcessor{T}"/>.
/// </summary> /// </summary>
private readonly struct ApplyHorizontalConvolutionRowIntervalOperation : IRowIntervalOperation private readonly struct ApplyHorizontalConvolutionRowOperation : IRowOperation
{ {
private readonly Rectangle bounds; private readonly Rectangle bounds;
private readonly Buffer2D<Vector4> targetValues; private readonly Buffer2D<Vector4> targetValues;
@ -193,7 +190,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
private readonly int maxX; private readonly int maxX;
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(InliningOptions.ShortMethod)]
public ApplyHorizontalConvolutionRowIntervalOperation( public ApplyHorizontalConvolutionRowOperation(
Rectangle bounds, Rectangle bounds,
Buffer2D<Vector4> targetValues, Buffer2D<Vector4> targetValues,
Buffer2D<ComplexVector4> sourceValues, Buffer2D<ComplexVector4> sourceValues,
@ -213,16 +210,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
/// <inheritdoc/> /// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(InliningOptions.ShortMethod)]
public void Invoke(in RowInterval rows) public void Invoke(int y)
{ {
for (int y = rows.Min; y < rows.Max; y++) Span<Vector4> targetRowSpan = this.targetValues.GetRowSpan(y).Slice(this.bounds.X);
{
Span<Vector4> targetRowSpan = this.targetValues.GetRowSpan(y).Slice(this.bounds.X);
for (int x = 0; x < this.bounds.Width; x++) for (int x = 0; x < this.bounds.Width; x++)
{ {
Buffer2DUtils.Convolve4AndAccumulatePartials(this.kernel, this.sourceValues, targetRowSpan, y, x, this.bounds.Y, this.maxY, this.bounds.X, this.maxX, this.z, this.w); Buffer2DUtils.Convolve4AndAccumulatePartials(this.kernel, this.sourceValues, targetRowSpan, y, x, this.bounds.Y, this.maxY, this.bounds.X, this.maxX, this.z, this.w);
}
} }
} }
} }
@ -230,7 +224,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
/// <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 ApplyGammaExposureRowIntervalOperation : IRowIntervalOperation<Vector4> private readonly struct ApplyGammaExposureRowOperation : IRowOperation<Vector4>
{ {
private readonly Rectangle bounds; private readonly Rectangle bounds;
private readonly Buffer2D<TPixel> targetPixels; private readonly Buffer2D<TPixel> targetPixels;
@ -238,7 +232,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
private readonly float gamma; private readonly float gamma;
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(InliningOptions.ShortMethod)]
public ApplyGammaExposureRowIntervalOperation( public ApplyGammaExposureRowOperation(
Rectangle bounds, Rectangle bounds,
Buffer2D<TPixel> targetPixels, Buffer2D<TPixel> targetPixels,
Configuration configuration, Configuration configuration,
@ -252,31 +246,28 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
/// <inheritdoc/> /// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(InliningOptions.ShortMethod)]
public void Invoke(in RowInterval rows, Span<Vector4> span) public void Invoke(int y, Span<Vector4> 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, span.Length), span, PixelConversionModifiers.Premultiply);
ref Vector4 baseRef = ref MemoryMarshal.GetReference(span);
for (int x = 0; x < this.bounds.Width; x++)
{ {
Span<TPixel> targetRowSpan = this.targetPixels.GetRowSpan(y).Slice(this.bounds.X); ref Vector4 v = ref Unsafe.Add(ref baseRef, x);
PixelOperations<TPixel>.Instance.ToVector4(this.configuration, targetRowSpan.Slice(0, span.Length), span, PixelConversionModifiers.Premultiply); v.X = MathF.Pow(v.X, this.gamma);
ref Vector4 baseRef = ref MemoryMarshal.GetReference(span); v.Y = MathF.Pow(v.Y, this.gamma);
v.Z = MathF.Pow(v.Z, this.gamma);
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, targetRowSpan);
} }
PixelOperations<TPixel>.Instance.FromVector4Destructive(this.configuration, span, targetRowSpan);
} }
} }
/// <summary> /// <summary>
/// A <see langword="struct"/> implementing the inverse gamma exposure logic for <see cref="BokehBlurProcessor{T}"/>. /// A <see langword="struct"/> implementing the inverse gamma exposure logic for <see cref="BokehBlurProcessor{T}"/>.
/// </summary> /// </summary>
private readonly struct ApplyInverseGammaExposureRowIntervalOperation : IRowIntervalOperation private readonly struct ApplyInverseGammaExposureRowOperation : IRowOperation
{ {
private readonly Rectangle bounds; private readonly Rectangle bounds;
private readonly Buffer2D<TPixel> targetPixels; private readonly Buffer2D<TPixel> targetPixels;
@ -285,7 +276,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
private readonly float inverseGamma; private readonly float inverseGamma;
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(InliningOptions.ShortMethod)]
public ApplyInverseGammaExposureRowIntervalOperation( public ApplyInverseGammaExposureRowOperation(
Rectangle bounds, Rectangle bounds,
Buffer2D<TPixel> targetPixels, Buffer2D<TPixel> targetPixels,
Buffer2D<Vector4> sourceValues, Buffer2D<Vector4> sourceValues,
@ -301,28 +292,25 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
/// <inheritdoc/> /// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(InliningOptions.ShortMethod)]
public void Invoke(in RowInterval rows) public void Invoke(int y)
{ {
Vector4 low = Vector4.Zero; Vector4 low = Vector4.Zero;
var high = new Vector4(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity); var high = new Vector4(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity);
for (int y = rows.Min; y < rows.Max; y++) Span<TPixel> targetPixelSpan = this.targetPixels.GetRowSpan(y).Slice(this.bounds.X);
Span<Vector4> sourceRowSpan = this.sourceValues.GetRowSpan(y).Slice(this.bounds.X);
ref Vector4 sourceRef = ref MemoryMarshal.GetReference(sourceRowSpan);
for (int x = 0; x < this.bounds.Width; x++)
{ {
Span<TPixel> targetPixelSpan = this.targetPixels.GetRowSpan(y).Slice(this.bounds.X); ref Vector4 v = ref Unsafe.Add(ref sourceRef, x);
Span<Vector4> sourceRowSpan = this.sourceValues.GetRowSpan(y).Slice(this.bounds.X); var clamp = Vector4.Clamp(v, low, high);
ref Vector4 sourceRef = ref MemoryMarshal.GetReference(sourceRowSpan); v.X = MathF.Pow(clamp.X, this.inverseGamma);
v.Y = MathF.Pow(clamp.Y, this.inverseGamma);
for (int x = 0; x < this.bounds.Width; x++) v.Z = MathF.Pow(clamp.Z, this.inverseGamma);
{
ref Vector4 v = ref Unsafe.Add(ref sourceRef, x);
var clamp = Vector4.Clamp(v, low, high);
v.X = MathF.Pow(clamp.X, this.inverseGamma);
v.Y = MathF.Pow(clamp.Y, this.inverseGamma);
v.Z = MathF.Pow(clamp.Z, this.inverseGamma);
}
PixelOperations<TPixel>.Instance.FromVector4Destructive(this.configuration, sourceRowSpan.Slice(0, this.bounds.Width), targetPixelSpan, PixelConversionModifiers.Premultiply);
} }
PixelOperations<TPixel>.Instance.FromVector4Destructive(this.configuration, sourceRowSpan.Slice(0, this.bounds.Width), targetPixelSpan, PixelConversionModifiers.Premultiply);
} }
} }
} }

Loading…
Cancel
Save