Browse Source

Adding some resamplers

Former-commit-id: 81377f2d574fe5778b5a24c968c53bd967e8f08d
Former-commit-id: 0dbdf15a7d41f51a7ca109a1b6fc39954c6cfa69
Former-commit-id: 48d223ff221f92f49f12685d44c09839bb76b2e4
pull/17/head
James Jackson-South 10 years ago
parent
commit
7d7c9fef6c
  1. 35
      src/ImageProcessor/Common/Helpers/ImageMaths.cs
  2. 17
      src/ImageProcessor/ImageProcessor.csproj
  3. 3
      src/ImageProcessor/ImageProcessor.csproj.DotSettings
  4. 2
      src/ImageProcessor/Samplers/Resamplers/BicubicResampler.cs
  5. 32
      src/ImageProcessor/Samplers/Resamplers/BoxResampler.cs
  6. 26
      src/ImageProcessor/Samplers/Resamplers/CatmullRomResampler.cs
  7. 26
      src/ImageProcessor/Samplers/Resamplers/HermiteResampler.cs
  8. 0
      src/ImageProcessor/Samplers/Resamplers/IResampler.cs
  9. 6
      src/ImageProcessor/Samplers/Resamplers/Lanczos3Resampler.cs
  10. 26
      src/ImageProcessor/Samplers/Resamplers/MitchellNetravaliResampler.cs
  11. 26
      src/ImageProcessor/Samplers/Resamplers/RobidouxResampler.cs
  12. 26
      src/ImageProcessor/Samplers/Resamplers/RobidouxSharpResampler.cs
  13. 26
      src/ImageProcessor/Samplers/Resamplers/RobidouxSoftResampler.cs
  14. 26
      src/ImageProcessor/Samplers/Resamplers/SplineResampler.cs
  15. 32
      src/ImageProcessor/Samplers/Resamplers/TriangleResampler.cs
  16. 33
      src/ImageProcessor/Samplers/Resamplers/WelchResampler.cs
  17. 19
      src/ImageProcessor/Samplers/Resize.cs
  18. 13
      tests/ImageProcessor.Tests/Processors/Samplers/SamplerTests.cs

35
src/ImageProcessor/Common/Helpers/ImageMaths.cs

@ -12,6 +12,41 @@ namespace ImageProcessor
/// </summary>
internal static class ImageMaths
{
/// <summary>
/// Returns the result of a B-C filter against the given value.
/// <see href="http://www.imagemagick.org/Usage/filter/#cubic_bc"/>
/// </summary>
/// <param name="x">The value to process.</param>
/// <param name="b">The B-Spline curve variable.</param>
/// <param name="c">The Cardinal curve variable.</param>
/// <returns>
/// The <see cref="double"/>.
/// </returns>
public static double GetBcValue(double x, double b, double c)
{
double temp;
if (x < 0)
{
x = -x;
}
temp = x * x;
if (x < 1)
{
x = ((12 - (9 * b) - (6 * c)) * (x * temp)) + ((-18 + (12 * b) + (6 * c)) * temp) + (6 - (2 * b));
return x / 6;
}
if (x < 2)
{
x = ((-b - (6 * c)) * (x * temp)) + (((6 * b) + (30 * c)) * temp) + (((-12 * b) - (48 * c)) * x) + ((8 * b) + (24 * c));
return x / 6;
}
return 0;
}
/// <summary>
/// Gets the result of a sine cardinal function for the given value.
/// </summary>

17
src/ImageProcessor/ImageProcessor.csproj

@ -181,10 +181,20 @@
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Numerics\Rectangle.cs" />
<Compile Include="Numerics\Size.cs" />
<Compile Include="Samplers\Lanczos5Resampler.cs" />
<Compile Include="Samplers\BicubicResampler.cs" />
<Compile Include="Samplers\Resamplers\WelchResampler.cs" />
<Compile Include="Samplers\Resamplers\CatmullRomResampler.cs" />
<Compile Include="Samplers\Resamplers\RobidouxSoftResampler.cs" />
<Compile Include="Samplers\Resamplers\RobidouxSharpResampler.cs" />
<Compile Include="Samplers\Resamplers\RobidouxResampler.cs" />
<Compile Include="Samplers\Resamplers\SplineResampler.cs" />
<Compile Include="Samplers\Resamplers\HermiteResampler.cs" />
<Compile Include="Samplers\Resamplers\MitchellNetravaliResampler.cs" />
<Compile Include="Samplers\Resamplers\TriangleResampler.cs" />
<Compile Include="Samplers\Resamplers\BoxResampler.cs" />
<Compile Include="Samplers\Resamplers\Lanczos3Resampler.cs" />
<Compile Include="Samplers\Resamplers\BicubicResampler.cs" />
<Compile Include="Samplers\ImageSampleExtensions.cs" />
<Compile Include="Samplers\IResampler.cs" />
<Compile Include="Samplers\Resamplers\IResampler.cs" />
<Compile Include="Samplers\Resize.cs" />
</ItemGroup>
<ItemGroup>
@ -197,7 +207,6 @@
<None Include="Formats\Gif\README.md" />
<None Include="Formats\Jpg\README.md" />
<None Include="packages.config" />
<AdditionalFiles Include="stylecop.json" />
</ItemGroup>
<ItemGroup>
<None Include="Formats\Bmp\README.md" />

3
src/ImageProcessor/ImageProcessor.csproj.DotSettings

@ -12,4 +12,5 @@
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=formats_005Cjpg/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=formats_005Cjpg_005Clibjpeg/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=formats_005Cpng/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=numerics/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=numerics/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=samplers_005Cresamplers/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

2
src/ImageProcessor/Samplers/BicubicResampler.cs → src/ImageProcessor/Samplers/Resamplers/BicubicResampler.cs

@ -12,7 +12,7 @@ namespace ImageProcessor.Samplers
public class BicubicResampler : IResampler
{
/// <inheritdoc/>
public double Radius => 4;
public double Radius => 2;
/// <inheritdoc/>
public double GetValue(double x)

32
src/ImageProcessor/Samplers/Resamplers/BoxResampler.cs

@ -0,0 +1,32 @@
// <copyright file="BoxResampler.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 box (nearest neighbour) algorithm.
/// </summary>
public class BoxResampler : IResampler
{
/// <inheritdoc/>
public double Radius => 0.5;
/// <inheritdoc/>
public double GetValue(double x)
{
if (x < 0)
{
x = -x;
}
if (x <= 0.5)
{
return 1;
}
return 0;
}
}
}

26
src/ImageProcessor/Samplers/Resamplers/CatmullRomResampler.cs

@ -0,0 +1,26 @@
// <copyright file="CatmullRomResampler.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 Catmull-Rom algorithm.
/// <see href="http://www.imagemagick.org/Usage/filter/#cubic_bc"/>
/// </summary>
public class CatmullRomResampler : IResampler
{
/// <inheritdoc/>
public double Radius => 2;
/// <inheritdoc/>
public double GetValue(double x)
{
const double B = 0;
const double C = 1 / 2d;
return ImageMaths.GetBcValue(x, B, C);
}
}
}

26
src/ImageProcessor/Samplers/Resamplers/HermiteResampler.cs

@ -0,0 +1,26 @@
// <copyright file="HermiteResampler.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 hermite algorithm.
/// <see href="http://www.imagemagick.org/Usage/filter/#cubic_bc"/>
/// </summary>
public class HermiteResampler : IResampler
{
/// <inheritdoc/>
public double Radius => 2;
/// <inheritdoc/>
public double GetValue(double x)
{
const double B = 0;
const double C = 0;
return ImageMaths.GetBcValue(x, B, C);
}
}
}

0
src/ImageProcessor/Samplers/IResampler.cs → src/ImageProcessor/Samplers/Resamplers/IResampler.cs

6
src/ImageProcessor/Samplers/Lanczos5Resampler.cs → src/ImageProcessor/Samplers/Resamplers/Lanczos3Resampler.cs

@ -1,4 +1,4 @@
// <copyright file="BicubicResampler.cs" company="James South">
// <copyright file="Lanczos3Resampler.cs" company="James South">
// Copyright © James South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
@ -9,10 +9,10 @@ namespace ImageProcessor.Samplers
/// 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 Lanczos5Resampler : IResampler
public class Lanczos3Resampler : IResampler
{
/// <inheritdoc/>
public double Radius => 5;
public double Radius => 3;
/// <inheritdoc/>
public double GetValue(double x)

26
src/ImageProcessor/Samplers/Resamplers/MitchellNetravaliResampler.cs

@ -0,0 +1,26 @@
// <copyright file="MitchellResampler.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 mitchell algorithm as described on
/// <see href="https://de.wikipedia.org/wiki/Mitchell-Netravali-Filter">Wikipedia</see>
/// </summary>
public class MitchellNetravaliResampler : IResampler
{
/// <inheritdoc/>
public double Radius => 2;
/// <inheritdoc/>
public double GetValue(double x)
{
const double B = 1 / 3d;
const double C = 1 / 3d;
return ImageMaths.GetBcValue(x, B, C);
}
}
}

26
src/ImageProcessor/Samplers/Resamplers/RobidouxResampler.cs

@ -0,0 +1,26 @@
// <copyright file="RobidouxResampler.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 Robidoux algorithm.
/// <see href="http://www.imagemagick.org/Usage/filter/#robidoux"/>
/// </summary>
public class RobidouxResampler : IResampler
{
/// <inheritdoc/>
public double Radius => 2;
/// <inheritdoc/>
public double GetValue(double x)
{
const double B = 0.3782;
const double C = 0.3109;
return ImageMaths.GetBcValue(x, B, C);
}
}
}

26
src/ImageProcessor/Samplers/Resamplers/RobidouxSharpResampler.cs

@ -0,0 +1,26 @@
// <copyright file="RobidouxSharpResampler.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 Robidoux Sharp algorithm.
/// <see href="http://www.imagemagick.org/Usage/filter/#robidoux"/>
/// </summary>
public class RobidouxSharpResampler : IResampler
{
/// <inheritdoc/>
public double Radius => 2;
/// <inheritdoc/>
public double GetValue(double x)
{
const double B = 0.2620;
const double C = 0.3690;
return ImageMaths.GetBcValue(x, B, C);
}
}
}

26
src/ImageProcessor/Samplers/Resamplers/RobidouxSoftResampler.cs

@ -0,0 +1,26 @@
// <copyright file="RobidouxSoftResampler.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 Robidoux Soft algorithm.
/// <see href="http://www.imagemagick.org/Usage/filter/#robidoux"/>
/// </summary>
public class RobidouxSoftResampler : IResampler
{
/// <inheritdoc/>
public double Radius => 2;
/// <inheritdoc/>
public double GetValue(double x)
{
const double B = 0.6796;
const double C = 0.1602;
return ImageMaths.GetBcValue(x, B, C);
}
}
}

26
src/ImageProcessor/Samplers/Resamplers/SplineResampler.cs

@ -0,0 +1,26 @@
// <copyright file="SplineResampler.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 spline algorithm.
/// <see href="http://www.imagemagick.org/Usage/filter/#cubic_bc"/>
/// </summary>
public class SplineResampler : IResampler
{
/// <inheritdoc/>
public double Radius => 2;
/// <inheritdoc/>
public double GetValue(double x)
{
const double B = 1;
const double C = 0;
return ImageMaths.GetBcValue(x, B, C);
}
}
}

32
src/ImageProcessor/Samplers/Resamplers/TriangleResampler.cs

@ -0,0 +1,32 @@
// <copyright file="TriangleResampler.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 triangle (bilinear) algorithm.
/// </summary>
public class TriangleResampler : IResampler
{
/// <inheritdoc/>
public double Radius => 1;
/// <inheritdoc/>
public double GetValue(double x)
{
if (x < 0)
{
x = -x;
}
if (x < 1)
{
return 1 - x;
}
return 0;
}
}
}

33
src/ImageProcessor/Samplers/Resamplers/WelchResampler.cs

@ -0,0 +1,33 @@
// <copyright file="WelchResampler.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 welch algorithm.
/// <see href="http://www.imagemagick.org/Usage/filter/"/>
/// </summary>
public class WelchResampler : IResampler
{
/// <inheritdoc/>
public double Radius => 3;
/// <inheritdoc/>
public double GetValue(double x)
{
if (x < 0)
{
x = -x;
}
if (x < 3)
{
return ImageMaths.SinC(x) * (1.0 - (x * x / 9.0));
}
return 0;
}
}
}

19
src/ImageProcessor/Samplers/Resize.cs

@ -12,6 +12,11 @@ namespace ImageProcessor.Samplers
/// </summary>
public class Resize : ParallelImageProcessor
{
/// <summary>
/// The epsilon for comparing floating point numbers.
/// </summary>
private const float Epsilon = 0.0001f;
/// <summary>
/// Initializes a new instance of the <see cref="Resize"/> class.
/// </summary>
@ -78,11 +83,16 @@ namespace ImageProcessor.Samplers
double b = 0;
double a = 0;
for (int yy = left; yy < right; yy++)
for (int yy = left; yy <= right; yy++)
{
// Get Y cooefficient
double kernel1 = this.Sampler.GetValue(dy - yy);
if (Math.Abs(kernel1) < Epsilon)
{
continue;
}
int originY2 = originY1 + yy;
if (originY2 < 0)
{
@ -94,11 +104,16 @@ namespace ImageProcessor.Samplers
originY2 = maxHeight;
}
for (int xx = left; xx < right; xx++)
for (int xx = left; xx <= right; xx++)
{
// Get X cooefficient
double kernel2 = kernel1 * this.Sampler.GetValue(xx - dx);
if (Math.Abs(kernel2) < Epsilon)
{
continue;
}
int originX2 = originX1 + xx;
if (originX2 < 0)
{

13
tests/ImageProcessor.Tests/Processors/Samplers/SamplerTests.cs

@ -14,7 +14,16 @@ namespace ImageProcessor.Tests
new TheoryData<string, IResampler>
{
{ "Bicubic", new BicubicResampler() },
//{ "Lanczos3", new Lanczos5Resampler() }
{ "Bilinear", new TriangleResampler() },
{ "NearestNeighbour", new BoxResampler() },
{ "Lanczos3", new Lanczos3Resampler() },
{ "MitchellNetravali", new MitchellNetravaliResampler() },
{ "Hermite", new HermiteResampler() },
{ "Spline", new SplineResampler() },
{ "Robidoux", new RobidouxResampler() },
{ "RobidouxSharp", new RobidouxSharpResampler() },
{ "RobidouxSoft", new RobidouxSoftResampler() },
{ "Welch", new WelchResampler() }
};
[Theory]
@ -52,7 +61,7 @@ namespace ImageProcessor.Tests
[InlineData(2, 0)]
public static void Lanczos3WindowOscillatesCorrectly(double x, double expected)
{
Lanczos5Resampler sampler = new Lanczos5Resampler();
Lanczos3Resampler sampler = new Lanczos3Resampler();
double result = sampler.GetValue(x);
Assert.Equal(result, expected);

Loading…
Cancel
Save