mirror of https://github.com/SixLabors/ImageSharp
4 changed files with 34 additions and 427 deletions
@ -1,309 +0,0 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
using System.Runtime.InteropServices; |
|||
using SixLabors.ImageSharp.Memory; |
|||
using SixLabors.ImageSharp.PixelFormats; |
|||
using SixLabors.ImageSharp.Processing.Processors.Convolution; |
|||
|
|||
namespace SixLabors.ImageSharp |
|||
{ |
|||
/// <summary>
|
|||
/// Provides methods to perform convolution operations.
|
|||
/// </summary>
|
|||
internal static class Convolver |
|||
{ |
|||
/// <summary>
|
|||
/// Computes the sum of vectors in the span referenced by <paramref name="targetRowRef"/> weighted by the two kernel weight values.
|
|||
/// Using this method the convolution filter is not applied to alpha in addition to the color channels.
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|||
/// <param name="state">The 2D convolution kernels state.</param>
|
|||
/// <param name="sourcePixels">The source frame.</param>
|
|||
/// <param name="targetRowRef">The target row base reference.</param>
|
|||
/// <param name="row">The current row.</param>
|
|||
/// <param name="column">The current column.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static void Convolve2D3<TPixel>( |
|||
in Convolution2DState state, |
|||
Buffer2D<TPixel> sourcePixels, |
|||
ref Vector4 targetRowRef, |
|||
int row, |
|||
int column) |
|||
where TPixel : unmanaged, IPixel<TPixel> |
|||
{ |
|||
Vector4 vector = default; |
|||
|
|||
Convolve2DImpl( |
|||
in state, |
|||
sourcePixels, |
|||
row, |
|||
column, |
|||
ref vector); |
|||
|
|||
ref Vector4 target = ref Unsafe.Add(ref targetRowRef, column); |
|||
vector.W = target.W; |
|||
|
|||
Numerics.UnPremultiply(ref vector); |
|||
target = vector; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Computes the sum of vectors in the span referenced by <paramref name="targetRowRef"/> weighted by the two kernel weight values.
|
|||
/// Using this method the convolution filter is applied to alpha in addition to the color channels.
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|||
/// <param name="state">The 2D convolution kernels state.</param>
|
|||
/// <param name="sourcePixels">The source frame.</param>
|
|||
/// <param name="targetRowRef">The target row base reference.</param>
|
|||
/// <param name="row">The current row.</param>
|
|||
/// <param name="column">The current column.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static void Convolve2D4<TPixel>( |
|||
in Convolution2DState state, |
|||
Buffer2D<TPixel> sourcePixels, |
|||
ref Vector4 targetRowRef, |
|||
int row, |
|||
int column) |
|||
where TPixel : unmanaged, IPixel<TPixel> |
|||
{ |
|||
Vector4 vector = default; |
|||
|
|||
Convolve2DImpl( |
|||
in state, |
|||
sourcePixels, |
|||
row, |
|||
column, |
|||
ref vector); |
|||
|
|||
ref Vector4 target = ref Unsafe.Add(ref targetRowRef, column); |
|||
Numerics.UnPremultiply(ref vector); |
|||
target = vector; |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static void Convolve2DImpl<TPixel>( |
|||
in Convolution2DState state, |
|||
Buffer2D<TPixel> sourcePixels, |
|||
int row, |
|||
int column, |
|||
ref Vector4 targetVector) |
|||
where TPixel : unmanaged, IPixel<TPixel> |
|||
{ |
|||
ReadOnlyKernel kernelY = state.KernelY; |
|||
ReadOnlyKernel kernelX = state.KernelX; |
|||
int kernelHeight = kernelY.Rows; |
|||
int kernelWidth = kernelY.Columns; |
|||
|
|||
Vector4 vectorY = default; |
|||
Vector4 vectorX = default; |
|||
|
|||
ref int sampleOffsetRowBase = ref state.GetSampleRow(row); |
|||
for (int y = 0; y < kernelHeight; y++) |
|||
{ |
|||
int offsetY = Unsafe.Add(ref sampleOffsetRowBase, y); |
|||
ref TPixel sourceRowBase = ref MemoryMarshal.GetReference(sourcePixels.GetRowSpan(offsetY)); |
|||
ref int sampleOffsetColumnBase = ref state.GetSampleColumn(column); |
|||
|
|||
for (int x = 0; x < kernelWidth; x++) |
|||
{ |
|||
int offsetX = Unsafe.Add(ref sampleOffsetColumnBase, x); |
|||
var sample = Unsafe.Add(ref sourceRowBase, offsetX).ToVector4(); |
|||
Numerics.Premultiply(ref sample); |
|||
vectorX += kernelX[y, x] * sample; |
|||
vectorY += kernelY[y, x] * sample; |
|||
} |
|||
} |
|||
|
|||
targetVector = Vector4.SquareRoot((vectorX * vectorX) + (vectorY * vectorY)); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Computes the sum of vectors in the span referenced by <paramref name="targetRowRef"/> weighted by the kernel weight values.
|
|||
/// Using this method the convolution filter is not applied to alpha in addition to the color channels.
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|||
/// <param name="state">The convolution kernel state.</param>
|
|||
/// <param name="sourcePixels">The source frame.</param>
|
|||
/// <param name="targetRowRef">The target row base reference.</param>
|
|||
/// <param name="row">The current row.</param>
|
|||
/// <param name="column">The current column.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static void Convolve3<TPixel>( |
|||
in ConvolutionState state, |
|||
Buffer2D<TPixel> sourcePixels, |
|||
ref Vector4 targetRowRef, |
|||
int row, |
|||
int column) |
|||
where TPixel : unmanaged, IPixel<TPixel> |
|||
{ |
|||
Vector4 vector = default; |
|||
|
|||
ConvolveImpl( |
|||
state, |
|||
sourcePixels, |
|||
row, |
|||
column, |
|||
ref vector); |
|||
|
|||
ref Vector4 target = ref Unsafe.Add(ref targetRowRef, column); |
|||
vector.W = target.W; |
|||
|
|||
Numerics.UnPremultiply(ref vector); |
|||
target = vector; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Computes the sum of vectors in the span referenced by <paramref name="targetRowRef"/> weighted by the kernel weight values.
|
|||
/// Using this method the convolution filter is applied to alpha in addition to the color channels.
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|||
/// <param name="state">The convolution kernel state.</param>
|
|||
/// <param name="sourcePixels">The source frame.</param>
|
|||
/// <param name="targetRowRef">The target row base reference.</param>
|
|||
/// <param name="row">The current row.</param>
|
|||
/// <param name="column">The current column.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static void Convolve4<TPixel>( |
|||
in ConvolutionState state, |
|||
Buffer2D<TPixel> sourcePixels, |
|||
ref Vector4 targetRowRef, |
|||
int row, |
|||
int column) |
|||
where TPixel : unmanaged, IPixel<TPixel> |
|||
{ |
|||
Vector4 vector = default; |
|||
|
|||
ConvolveImpl( |
|||
state, |
|||
sourcePixels, |
|||
row, |
|||
column, |
|||
ref vector); |
|||
|
|||
ref Vector4 target = ref Unsafe.Add(ref targetRowRef, column); |
|||
Numerics.UnPremultiply(ref vector); |
|||
target = vector; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Computes the sum of vectors in the span referenced by <paramref name="sourceRow"/> weighted
|
|||
/// by the kernel weight values.
|
|||
/// Using this method the convolution filter is not applied to alpha in addition
|
|||
/// to the color channels.
|
|||
/// </summary>
|
|||
/// <param name="state">The convolution kernel state.</param>
|
|||
/// <param name="sourceRow">The source row.</param>
|
|||
/// <param name="targetRow">The target row.</param>
|
|||
/// <param name="kY">The current kernel row.</param>
|
|||
/// <param name="bX">The interest x-bounds relative to the interest image.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static void ConvolveRow3( |
|||
in ConvolutionState state, |
|||
Span<Vector4> sourceRow, |
|||
Span<Vector4> targetRow, |
|||
int kY, |
|||
int bX) |
|||
{ |
|||
ReadOnlyKernel kernel = state.Kernel; |
|||
ref Vector4 sourceBase = ref MemoryMarshal.GetReference(sourceRow); |
|||
ref Vector4 targetBase = ref MemoryMarshal.GetReference(targetRow); |
|||
|
|||
Numerics.Premultiply(sourceRow); |
|||
|
|||
for (int x = 0; x < sourceRow.Length; x++) |
|||
{ |
|||
Vector4 vector = default; |
|||
ref int sampleOffsetColumnBase = ref state.GetSampleColumn(x); |
|||
|
|||
for (int kX = 0; kX < kernel.Columns; kX++) |
|||
{ |
|||
int offsetX = Unsafe.Add(ref sampleOffsetColumnBase, kX) - bX; |
|||
Vector4 sample = Unsafe.Add(ref sourceBase, offsetX); |
|||
vector += kernel[kY, kX] * sample; |
|||
} |
|||
|
|||
ref Vector4 target = ref Unsafe.Add(ref targetBase, x); |
|||
vector.W = target.W; |
|||
Numerics.UnPremultiply(ref vector); |
|||
target = vector; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Computes the sum of vectors in the span referenced by <paramref name="sourceRow"/> weighted
|
|||
/// by the kernel weight values.
|
|||
/// Using this method the convolution filter is applied to alpha in addition to the
|
|||
/// color channels.
|
|||
/// </summary>
|
|||
/// <param name="state">The convolution kernel state.</param>
|
|||
/// <param name="sourceRow">The source row.</param>
|
|||
/// <param name="targetRow">The target row.</param>
|
|||
/// <param name="kY">The current kernel row.</param>
|
|||
/// <param name="bX">The interest x-bounds relative to the interest image.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static void ConvolveRow4<TPixel>( |
|||
in ConvolutionState state, |
|||
Span<Vector4> sourceRow, |
|||
Span<Vector4> targetRow, |
|||
int kY, |
|||
int bX) |
|||
where TPixel : unmanaged, IPixel<TPixel> |
|||
{ |
|||
ReadOnlyKernel kernel = state.Kernel; |
|||
|
|||
ref Vector4 sourceBase = ref MemoryMarshal.GetReference(sourceRow); |
|||
ref Vector4 targetBase = ref MemoryMarshal.GetReference(targetRow); |
|||
|
|||
Numerics.Premultiply(sourceRow); |
|||
|
|||
for (int x = 0; x < sourceRow.Length; x++) |
|||
{ |
|||
ref int sampleOffsetColumnBase = ref state.GetSampleColumn(x); |
|||
ref Vector4 target = ref Unsafe.Add(ref targetBase, x); |
|||
|
|||
for (int kX = 0; kX < kernel.Columns; kX++) |
|||
{ |
|||
int offsetX = Unsafe.Add(ref sampleOffsetColumnBase, kX) - bX; |
|||
Vector4 sample = Unsafe.Add(ref sourceBase, offsetX); |
|||
target += kernel[kY, kX] * sample; |
|||
} |
|||
} |
|||
|
|||
Numerics.UnPremultiply(targetRow); |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
private static void ConvolveImpl<TPixel>( |
|||
in ConvolutionState state, |
|||
Buffer2D<TPixel> sourcePixels, |
|||
int row, |
|||
int column, |
|||
ref Vector4 targetVector) |
|||
where TPixel : unmanaged, IPixel<TPixel> |
|||
{ |
|||
ReadOnlyKernel kernel = state.Kernel; |
|||
int kernelHeight = kernel.Rows; |
|||
int kernelWidth = kernel.Columns; |
|||
|
|||
ref int sampleOffsetRowBase = ref state.GetSampleRow(row); |
|||
for (int y = 0; y < kernelHeight; y++) |
|||
{ |
|||
int offsetY = Unsafe.Add(ref sampleOffsetRowBase, y); |
|||
ref TPixel sourceRowBase = ref MemoryMarshal.GetReference(sourcePixels.GetRowSpan(offsetY)); |
|||
ref int sampleOffsetColumnBase = ref state.GetSampleColumn(column); |
|||
|
|||
for (int x = 0; x < kernelWidth; x++) |
|||
{ |
|||
int offsetX = Unsafe.Add(ref sampleOffsetColumnBase, x); |
|||
var sample = Unsafe.Add(ref sourceRowBase, offsetX).ToVector4(); |
|||
Numerics.Premultiply(ref sample); |
|||
targetVector += kernel[y, x] * sample; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue