mirror of https://github.com/SixLabors/ImageSharp
4 changed files with 145 additions and 22 deletions
@ -0,0 +1,99 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
|
|||
using SixLabors.ImageSharp.Processing.Processors.Transforms; |
|||
|
|||
namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms |
|||
{ |
|||
public partial class KernelMapTests |
|||
{ |
|||
/// <summary>
|
|||
/// Simplified reference implementation for <see cref="KernelMap"/> functionality.
|
|||
/// </summary>
|
|||
public class ReferenceKernelMap |
|||
{ |
|||
private readonly ReferenceKernel[] kernels; |
|||
|
|||
public ReferenceKernelMap(ReferenceKernel[] kernels) |
|||
{ |
|||
this.kernels = kernels; |
|||
} |
|||
|
|||
public int DestinationSize => this.kernels.Length; |
|||
|
|||
public ReferenceKernel GetKernel(int destinationIndex) => this.kernels[destinationIndex]; |
|||
|
|||
public static ReferenceKernelMap Calculate(IResampler sampler, int destinationSize, int sourceSize) |
|||
{ |
|||
float ratio = (float)sourceSize / destinationSize; |
|||
float scale = ratio; |
|||
|
|||
if (scale < 1F) |
|||
{ |
|||
scale = 1F; |
|||
} |
|||
|
|||
float radius = MathF.Ceiling(scale * sampler.Radius); |
|||
|
|||
var result = new List<ReferenceKernel>(); |
|||
|
|||
for (int i = 0; i < destinationSize; i++) |
|||
{ |
|||
float center = ((i + .5F) * ratio) - .5F; |
|||
|
|||
// Keep inside bounds.
|
|||
int left = (int)MathF.Ceiling(center - radius); |
|||
if (left < 0) |
|||
{ |
|||
left = 0; |
|||
} |
|||
|
|||
int right = (int)MathF.Floor(center + radius); |
|||
if (right > sourceSize - 1) |
|||
{ |
|||
right = sourceSize - 1; |
|||
} |
|||
|
|||
float sum = 0; |
|||
|
|||
float[] values = new float[right - left + 1]; |
|||
|
|||
for (int j = left; j <= right; j++) |
|||
{ |
|||
float weight = sampler.GetValue((j - center) / scale); |
|||
sum += weight; |
|||
|
|||
values[j - left] = weight; |
|||
} |
|||
|
|||
result.Add(new ReferenceKernel(left, values)); |
|||
|
|||
if (sum > 0) |
|||
{ |
|||
for (int w = 0; w < values.Length; w++) |
|||
{ |
|||
values[w] /= sum; |
|||
} |
|||
} |
|||
} |
|||
|
|||
return new ReferenceKernelMap(result.ToArray()); |
|||
} |
|||
} |
|||
|
|||
public struct ReferenceKernel |
|||
{ |
|||
public ReferenceKernel(int left, float[] values) |
|||
{ |
|||
this.Left = left; |
|||
this.Values = values; |
|||
} |
|||
|
|||
public int Left { get; } |
|||
|
|||
public float[] Values { get; } |
|||
|
|||
public int Length => this.Values.Length; |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue