mirror of https://github.com/SixLabors/ImageSharp
5 changed files with 198 additions and 93 deletions
@ -0,0 +1,91 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
using System.Buffers; |
|||
using System.Runtime.CompilerServices; |
|||
using SixLabors.ImageSharp.Memory; |
|||
|
|||
namespace SixLabors.ImageSharp.Processing.Processors.Convolution |
|||
{ |
|||
/// <summary>
|
|||
/// Provides a map of the convolution kernel sampling offsets.
|
|||
/// </summary>
|
|||
internal sealed class KernelOffsetMap : IDisposable |
|||
{ |
|||
private readonly MemoryAllocator allocator; |
|||
private bool isDisposed; |
|||
private IMemoryOwner<int> yOffsets; |
|||
private IMemoryOwner<int> xOffsets; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="KernelOffsetMap"/> class.
|
|||
/// </summary>
|
|||
/// <param name="allocator">The memory allocator.</param>
|
|||
public KernelOffsetMap(MemoryAllocator allocator) => this.allocator = allocator; |
|||
|
|||
public void BuildOffsetMap(in DenseMatrix<float> matrix, Rectangle bounds) |
|||
{ |
|||
int matrixHeight = matrix.Rows; |
|||
int matrixWidth = matrix.Columns; |
|||
this.yOffsets = this.allocator.Allocate<int>(bounds.Height * matrixHeight); |
|||
this.xOffsets = this.allocator.Allocate<int>(bounds.Width * matrixWidth); |
|||
|
|||
int minY = bounds.Y; |
|||
int maxY = bounds.Bottom - 1; |
|||
int minX = bounds.X; |
|||
int maxX = bounds.Right - 1; |
|||
|
|||
int radiusY = matrixHeight >> 1; |
|||
int radiusX = matrixWidth >> 1; |
|||
|
|||
// Calculate the potential sampling y-offsets.
|
|||
Span<int> ySpan = this.yOffsets.GetSpan(); |
|||
for (int row = 0; row < bounds.Height; row++) |
|||
{ |
|||
for (int y = 0; y < matrixHeight; y++) |
|||
{ |
|||
ySpan[(row * matrixHeight) + y] = row + y + minY - radiusY; |
|||
} |
|||
} |
|||
|
|||
if (matrixHeight > 1) |
|||
{ |
|||
Numerics.Clamp(ySpan, minY, maxY); |
|||
} |
|||
|
|||
// Calculate the potential sampling x-offsets.
|
|||
Span<int> xSpan = this.xOffsets.GetSpan(); |
|||
for (int column = 0; column < bounds.Width; column++) |
|||
{ |
|||
for (int x = 0; x < matrixWidth; x++) |
|||
{ |
|||
xSpan[(column * matrixWidth) + x] = column + x + minX - radiusX; |
|||
} |
|||
} |
|||
|
|||
if (matrixWidth > 1) |
|||
{ |
|||
Numerics.Clamp(xSpan, minX, maxX); |
|||
} |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public Span<int> GetYOffsetSpan() => this.yOffsets.GetSpan(); |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public Span<int> GetXOffsetSpan() => this.xOffsets.GetSpan(); |
|||
|
|||
/// <inheritdoc/>
|
|||
public void Dispose() |
|||
{ |
|||
if (!this.isDisposed) |
|||
{ |
|||
this.yOffsets.Dispose(); |
|||
this.xOffsets.Dispose(); |
|||
|
|||
this.isDisposed = true; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue