mirror of https://github.com/SixLabors/ImageSharp
Browse Source
Former-commit-id: ffc9b65f1a7643d7a1581dc702d507ee247aab91 Former-commit-id: e079559f8b9293a40b86a946825d4cd734ef0e69 Former-commit-id: 7b795cc9803c78b1d2b434b4d7c1479ebd42809faf/merge-core
7 changed files with 169 additions and 3 deletions
@ -0,0 +1,56 @@ |
|||
// <copyright file="ImageMaths.cs" company="James South">
|
|||
// Copyright © James South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageProcessor |
|||
{ |
|||
using System; |
|||
|
|||
/// <summary>
|
|||
/// Provides common mathematical methods.
|
|||
/// </summary>
|
|||
internal static class ImageMaths |
|||
{ |
|||
/// <summary>
|
|||
/// Gets the result of a sine cardinal function for the given value.
|
|||
/// </summary>
|
|||
/// <param name="x">
|
|||
/// The value to calculate the result for.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// The <see cref="double"/>.
|
|||
/// </returns>
|
|||
public static double SinC(double x) |
|||
{ |
|||
const double Epsilon = .0001; |
|||
|
|||
if (Math.Abs(x) > Epsilon) |
|||
{ |
|||
x *= Math.PI; |
|||
return Clean(Math.Sin(x) / x); |
|||
} |
|||
|
|||
return 1.0; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Ensures that any passed double is correctly rounded to zero
|
|||
/// </summary>
|
|||
/// <param name="x">The value to clean.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="double"/>
|
|||
/// </returns>.
|
|||
private static double Clean(double x) |
|||
{ |
|||
const double Epsilon = .0001; |
|||
|
|||
if (Math.Abs(x) < Epsilon) |
|||
{ |
|||
return 0.0; |
|||
} |
|||
|
|||
return x; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,33 @@ |
|||
// <copyright file="BicubicResampler.cs" company="James South">
|
|||
// Copyright © James South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageProcessor.Samplers |
|||
{ |
|||
/// <summary>
|
|||
/// The function implements the Lanczos kernel algorithm as described on
|
|||
/// <see href="https://en.wikipedia.org/wiki/Lanczos_resampling#Algorithm">Wikipedia</see>
|
|||
/// </summary>
|
|||
public class Lanczos3Resampler : IResampler |
|||
{ |
|||
/// <inheritdoc/>
|
|||
public double Radius => 3; |
|||
|
|||
/// <inheritdoc/>
|
|||
public double GetValue(double x) |
|||
{ |
|||
if (x < 0) |
|||
{ |
|||
x = -x; |
|||
} |
|||
|
|||
if (x < 3) |
|||
{ |
|||
return ImageMaths.SinC(x) * ImageMaths.SinC(x / 3f); |
|||
} |
|||
|
|||
return 0; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,74 @@ |
|||
|
|||
namespace ImageProcessor.Tests.Filters |
|||
{ |
|||
using System.Collections.Generic; |
|||
using System.Diagnostics; |
|||
using System.IO; |
|||
|
|||
using Samplers; |
|||
|
|||
using Xunit; |
|||
|
|||
public class SamplerTests |
|||
{ |
|||
public static readonly List<string> Files = new List<string> |
|||
{ |
|||
{ "../../TestImages/Formats/Jpg/Backdrop.jpg" }, |
|||
{ "../../TestImages/Formats/Bmp/Car.bmp" }, |
|||
{ "../../TestImages/Formats/Png/cmyk.png" }, |
|||
//{ "../../TestImages/Formats/Gif/a.gif" },
|
|||
{ "../../TestImages/Formats/Gif/leaf.gif" }, |
|||
//{ "../../TestImages/Formats/Gif/ani.gif" },
|
|||
//{ "../../TestImages/Formats/Gif/ani2.gif" },
|
|||
//{ "../../TestImages/Formats/Gif/giphy.gif" },
|
|||
}; |
|||
|
|||
public static readonly TheoryData<string, IResampler> Samplers = |
|||
new TheoryData<string, IResampler> |
|||
{ |
|||
{ "Bicubic", new BicubicResampler() }, |
|||
{ "Lanczos3", new Lanczos3Resampler() } |
|||
}; |
|||
|
|||
[Theory] |
|||
[MemberData("Samplers")] |
|||
public void ResizeImage(string name, IResampler sampler) |
|||
{ |
|||
if (!Directory.Exists("Resized")) |
|||
{ |
|||
Directory.CreateDirectory("Resized"); |
|||
} |
|||
|
|||
foreach (string file in Files) |
|||
{ |
|||
using (FileStream stream = File.OpenRead(file)) |
|||
{ |
|||
Stopwatch watch = Stopwatch.StartNew(); |
|||
Image image = new Image(stream); |
|||
string filename = Path.GetFileNameWithoutExtension(file) + "-" + name + Path.GetExtension(file); |
|||
using (FileStream output = File.OpenWrite($"Resized/{filename}")) |
|||
{ |
|||
image.Resize(900, 900, sampler).Save(output); |
|||
} |
|||
|
|||
Trace.WriteLine($"{name}: {watch.ElapsedMilliseconds}ms"); |
|||
} |
|||
} |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(-2, 0)] |
|||
[InlineData(-1, 0)] |
|||
[InlineData(0, 1)] |
|||
[InlineData(1, 0)] |
|||
[InlineData(2, 0)] |
|||
[InlineData(2, 0)] |
|||
public static void Lanczos3WindowOscillatesCorrectly(double x, double expected) |
|||
{ |
|||
Lanczos3Resampler sampler = new Lanczos3Resampler(); |
|||
double result = sampler.GetValue(x); |
|||
|
|||
Assert.Equal(result, expected); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue