mirror of https://github.com/SixLabors/ImageSharp
1 changed files with 0 additions and 109 deletions
@ -1,109 +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; |
|
||||
|
|
||||
namespace SixLabors.ImageSharp |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// Extension methods for <see cref="Buffer2D{T}"/>.
|
|
||||
/// TODO: One day rewrite all this to use SIMD intrinsics. There's a lot of scope for improvement.
|
|
||||
/// </summary>
|
|
||||
internal static class Buffer2DUtils |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// Computes the sum of vectors in <paramref name="targetRow"/> weighted by the kernel weight values.
|
|
||||
/// </summary>
|
|
||||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|
||||
/// <param name="kernel">The 1D convolution kernel.</param>
|
|
||||
/// <param name="sourcePixels">The source frame.</param>
|
|
||||
/// <param name="targetRow">The target row.</param>
|
|
||||
/// <param name="row">The current row.</param>
|
|
||||
/// <param name="column">The current column.</param>
|
|
||||
/// <param name="minRow">The minimum working area row.</param>
|
|
||||
/// <param name="maxRow">The maximum working area row.</param>
|
|
||||
/// <param name="minColumn">The minimum working area column.</param>
|
|
||||
/// <param name="maxColumn">The maximum working area column.</param>
|
|
||||
public static void Convolve4<TPixel>( |
|
||||
Span<Complex64> kernel, |
|
||||
Buffer2D<TPixel> sourcePixels, |
|
||||
Span<ComplexVector4> targetRow, |
|
||||
int row, |
|
||||
int column, |
|
||||
int minRow, |
|
||||
int maxRow, |
|
||||
int minColumn, |
|
||||
int maxColumn) |
|
||||
where TPixel : unmanaged, IPixel<TPixel> |
|
||||
{ |
|
||||
ComplexVector4 vector = default; |
|
||||
int kernelLength = kernel.Length; |
|
||||
int radiusY = kernelLength >> 1; |
|
||||
int sourceOffsetColumnBase = column + minColumn; |
|
||||
ref Complex64 baseRef = ref MemoryMarshal.GetReference(kernel); |
|
||||
|
|
||||
for (int i = 0; i < kernelLength; i++) |
|
||||
{ |
|
||||
int offsetY = Numerics.Clamp(row + i - radiusY, minRow, maxRow); |
|
||||
int offsetX = Numerics.Clamp(sourceOffsetColumnBase, minColumn, maxColumn); |
|
||||
Span<TPixel> sourceRowSpan = sourcePixels.GetRowSpan(offsetY); |
|
||||
var currentColor = sourceRowSpan[offsetX].ToVector4(); |
|
||||
|
|
||||
vector.Sum(Unsafe.Add(ref baseRef, i) * currentColor); |
|
||||
} |
|
||||
|
|
||||
targetRow[column] = vector; |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Computes the sum of vectors in <paramref name="targetRow"/> weighted by the kernel weight values and accumulates the partial results.
|
|
||||
/// </summary>
|
|
||||
/// <param name="kernel">The 1D convolution kernel.</param>
|
|
||||
/// <param name="sourceValues">The source frame.</param>
|
|
||||
/// <param name="targetRow">The target row.</param>
|
|
||||
/// <param name="row">The current row.</param>
|
|
||||
/// <param name="column">The current column.</param>
|
|
||||
/// <param name="minRow">The minimum working area row.</param>
|
|
||||
/// <param name="maxRow">The maximum working area row.</param>
|
|
||||
/// <param name="minColumn">The minimum working area column.</param>
|
|
||||
/// <param name="maxColumn">The maximum working area column.</param>
|
|
||||
/// <param name="z">The weight factor for the real component of the complex pixel values.</param>
|
|
||||
/// <param name="w">The weight factor for the imaginary component of the complex pixel values.</param>
|
|
||||
public static void Convolve4AndAccumulatePartials( |
|
||||
Span<Complex64> kernel, |
|
||||
Buffer2D<ComplexVector4> sourceValues, |
|
||||
Span<Vector4> targetRow, |
|
||||
int row, |
|
||||
int column, |
|
||||
int minRow, |
|
||||
int maxRow, |
|
||||
int minColumn, |
|
||||
int maxColumn, |
|
||||
float z, |
|
||||
float w) |
|
||||
{ |
|
||||
ComplexVector4 vector = default; |
|
||||
int kernelLength = kernel.Length; |
|
||||
int radiusX = kernelLength >> 1; |
|
||||
int sourceOffsetColumnBase = column + minColumn; |
|
||||
|
|
||||
int offsetY = Numerics.Clamp(row, minRow, maxRow); |
|
||||
ref ComplexVector4 sourceRef = ref MemoryMarshal.GetReference(sourceValues.GetRowSpan(offsetY)); |
|
||||
ref Complex64 baseRef = ref MemoryMarshal.GetReference(kernel); |
|
||||
|
|
||||
for (int x = 0; x < kernelLength; x++) |
|
||||
{ |
|
||||
int offsetX = Numerics.Clamp(sourceOffsetColumnBase + x - radiusX, minColumn, maxColumn); |
|
||||
vector.Sum(Unsafe.Add(ref baseRef, x) * Unsafe.Add(ref sourceRef, offsetX)); |
|
||||
} |
|
||||
|
|
||||
targetRow[column] += vector.WeightedSum(z, w); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
Loading…
Reference in new issue