mirror of https://github.com/SixLabors/ImageSharp
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
107 lines
3.9 KiB
107 lines
3.9 KiB
// Copyright (c) Six Labors.
|
|
// Licensed under the Six Labors Split License.
|
|
|
|
using System.Runtime.CompilerServices;
|
|
using SixLabors.ImageSharp.PixelFormats;
|
|
|
|
namespace SixLabors.ImageSharp.Processing.Processors.Transforms;
|
|
|
|
/// <summary>
|
|
/// Cubic filters contain a collection of different filters of varying B-Spline and
|
|
/// Cardinal values. With these two values you can generate any smoothly fitting
|
|
/// (continuious first derivative) piece-wise cubic filter.
|
|
/// <see href="https://usage.imagemagick.org/filter/#cubic_bc"/>
|
|
/// <see href="https://www.cs.utexas.edu/~fussell/courses/cs384g-fall2013/lectures/mitchell/Mitchell.pdf"/>
|
|
/// </summary>
|
|
public readonly struct CubicResampler : IResampler
|
|
{
|
|
private readonly float bspline;
|
|
private readonly float cardinal;
|
|
|
|
/// <summary>
|
|
/// The Catmull-Rom filter is a well known standard Cubic Filter often used as a interpolation function.
|
|
/// This filter produces a reasonably sharp edge, but without a the pronounced gradient change on large
|
|
/// scale image enlargements that a 'Lagrange' filter can produce.
|
|
/// </summary>
|
|
public static readonly CubicResampler CatmullRom = new(2, 0, .5F);
|
|
|
|
/// <summary>
|
|
/// The Hermite filter is type of smoothed triangular interpolation Filter,
|
|
/// This filter rounds off strong edges while preserving flat 'color levels' in the original image.
|
|
/// </summary>
|
|
public static readonly CubicResampler Hermite = new(2, 0, 0);
|
|
|
|
/// <summary>
|
|
/// The function implements the Mitchell-Netravali algorithm as described on
|
|
/// <see href="https://de.wikipedia.org/wiki/Mitchell-Netravali-Filter">Wikipedia</see>
|
|
/// </summary>
|
|
public static readonly CubicResampler MitchellNetravali = new(2, .3333333F, .3333333F);
|
|
|
|
/// <summary>
|
|
/// The function implements the Robidoux algorithm.
|
|
/// <see href="https://usage.imagemagick.org/filter/#robidoux"/>
|
|
/// </summary>
|
|
public static readonly CubicResampler Robidoux = new(2, .37821575509399867F, .31089212245300067F);
|
|
|
|
/// <summary>
|
|
/// The function implements the Robidoux Sharp algorithm.
|
|
/// <see href="https://usage.imagemagick.org/filter/#robidoux"/>
|
|
/// </summary>
|
|
public static readonly CubicResampler RobidouxSharp = new(2, .2620145123990142F, .3689927438004929F);
|
|
|
|
/// <summary>
|
|
/// The function implements the spline algorithm.
|
|
/// <see href="https://usage.imagemagick.org/filter/#cubic_bc"/>
|
|
/// </summary>
|
|
public static readonly CubicResampler Spline = new(2, 1, 0);
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="CubicResampler"/> struct.
|
|
/// </summary>
|
|
/// <param name="radius">The sampling radius.</param>
|
|
/// <param name="bspline">The B-Spline value.</param>
|
|
/// <param name="cardinal">The Cardinal cubic value.</param>
|
|
public CubicResampler(float radius, float bspline, float cardinal)
|
|
{
|
|
this.Radius = radius;
|
|
this.bspline = bspline;
|
|
this.cardinal = cardinal;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public float Radius { get; }
|
|
|
|
/// <inheritdoc/>
|
|
[MethodImpl(InliningOptions.ShortMethod)]
|
|
public float GetValue(float x)
|
|
{
|
|
float b = this.bspline;
|
|
float c = this.cardinal;
|
|
|
|
if (x < 0F)
|
|
{
|
|
x = -x;
|
|
}
|
|
|
|
float temp = x * x;
|
|
if (x < 1F)
|
|
{
|
|
x = ((12 - (9 * b) - (6 * c)) * (x * temp)) + ((-18 + (12 * b) + (6 * c)) * temp) + (6 - (2 * b));
|
|
return x / 6F;
|
|
}
|
|
|
|
if (x < 2F)
|
|
{
|
|
x = ((-b - (6 * c)) * (x * temp)) + (((6 * b) + (30 * c)) * temp) + (((-12 * b) - (48 * c)) * x) + ((8 * b) + (24 * c));
|
|
return x / 6F;
|
|
}
|
|
|
|
return 0F;
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
[MethodImpl(InliningOptions.ShortMethod)]
|
|
public void ApplyTransform<TPixel>(IResamplingTransformImageProcessor<TPixel> processor)
|
|
where TPixel : unmanaged, IPixel<TPixel>
|
|
=> processor.ApplyTransform(in this);
|
|
}
|
|
|