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