mirror of https://github.com/SixLabors/ImageSharp
4 changed files with 191 additions and 24 deletions
@ -0,0 +1,92 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System; |
|||
using System.Diagnostics; |
|||
using System.Runtime.CompilerServices; |
|||
using System.Runtime.InteropServices; |
|||
|
|||
namespace SixLabors.ImageSharp.Processing.Processors.Convolution |
|||
{ |
|||
/// <summary>
|
|||
/// A stack only, readonly, kernel matrix that can be indexed without
|
|||
/// bounds checks when compiled in release mode.
|
|||
/// </summary>
|
|||
internal readonly ref struct Kernel<T> |
|||
where T : struct, IEquatable<T> |
|||
{ |
|||
private readonly Span<T> values; |
|||
|
|||
public Kernel(DenseMatrix<T> matrix) |
|||
{ |
|||
this.Columns = matrix.Columns; |
|||
this.Rows = matrix.Rows; |
|||
this.values = matrix.Span; |
|||
} |
|||
|
|||
public int Columns |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get; |
|||
} |
|||
|
|||
public int Rows |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get; |
|||
} |
|||
|
|||
public ReadOnlySpan<T> Span |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get |
|||
{ |
|||
return this.values; |
|||
} |
|||
} |
|||
|
|||
public T this[int row, int column] |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get |
|||
{ |
|||
this.CheckCoordinates(row, column); |
|||
ref T vBase = ref MemoryMarshal.GetReference(this.values); |
|||
return Unsafe.Add(ref vBase, (row * this.Columns) + column); |
|||
} |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public void SetValue(int row, int column, T value) |
|||
{ |
|||
this.SetValue((row * this.Columns) + column, value); |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public void SetValue(int index, T value) |
|||
{ |
|||
ref T vBase = ref MemoryMarshal.GetReference(this.values); |
|||
Unsafe.Add(ref vBase, index) = value; |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public void Clear() |
|||
{ |
|||
this.values.Clear(); |
|||
} |
|||
|
|||
[Conditional("DEBUG")] |
|||
private void CheckCoordinates(int row, int column) |
|||
{ |
|||
if (row < 0 || row >= this.Rows) |
|||
{ |
|||
throw new ArgumentOutOfRangeException(nameof(row), row, $"{row} is outside the matrix bounds."); |
|||
} |
|||
|
|||
if (column < 0 || column >= this.Columns) |
|||
{ |
|||
throw new ArgumentOutOfRangeException(nameof(column), column, $"{column} is outside the matrix bounds."); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,46 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System; |
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
using System.Runtime.InteropServices; |
|||
|
|||
namespace SixLabors.ImageSharp.Processing.Processors.Convolution |
|||
{ |
|||
/// <summary>
|
|||
/// A stack only struct used for reducing reference indirection during convolution operations.
|
|||
/// </summary>
|
|||
internal readonly ref struct MedianConvolutionState |
|||
{ |
|||
private readonly Span<int> rowOffsetMap; |
|||
private readonly Span<int> columnOffsetMap; |
|||
private readonly int kernelHeight; |
|||
private readonly int kernelWidth; |
|||
|
|||
public MedianConvolutionState( |
|||
in DenseMatrix<Vector4> kernel, |
|||
KernelSamplingMap map) |
|||
{ |
|||
this.Kernel = new Kernel<Vector4>(kernel); |
|||
this.kernelHeight = kernel.Rows; |
|||
this.kernelWidth = kernel.Columns; |
|||
this.rowOffsetMap = map.GetRowOffsetSpan(); |
|||
this.columnOffsetMap = map.GetColumnOffsetSpan(); |
|||
} |
|||
|
|||
public readonly Kernel<Vector4> Kernel |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get; |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public readonly ref int GetSampleRow(int row) |
|||
=> ref Unsafe.Add(ref MemoryMarshal.GetReference(this.rowOffsetMap), row * this.kernelHeight); |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public readonly ref int GetSampleColumn(int column) |
|||
=> ref Unsafe.Add(ref MemoryMarshal.GetReference(this.columnOffsetMap), column * this.kernelWidth); |
|||
} |
|||
} |
|||
Loading…
Reference in new issue