Browse Source

Use double for resamplers

Former-commit-id: 6c024e150c3521c9a8f6ac12da96abfd7b4d1be7
Former-commit-id: 598e6e70606a95d16c6205d4eb04a960842246aa
Former-commit-id: 2c3e00cf2db86aaf7eedcbca3b7eef382d689885
af/merge-core
James Jackson-South 10 years ago
parent
commit
af355582c6
  1. 22
      src/ImageProcessorCore/Common/Helpers/ImageMaths.cs
  2. 18
      src/ImageProcessorCore/PackedVector/Bgra32.cs
  3. 12
      src/ImageProcessorCore/PackedVector/IPackedVector.cs
  4. 28
      src/ImageProcessorCore/Samplers/Processors/ResizeProcessor.cs
  5. 12
      src/ImageProcessorCore/Samplers/Resamplers/BicubicResampler.cs
  6. 4
      src/ImageProcessorCore/Samplers/Resamplers/BoxResampler.cs
  7. 8
      src/ImageProcessorCore/Samplers/Resamplers/CatmullRomResampler.cs
  8. 8
      src/ImageProcessorCore/Samplers/Resamplers/HermiteResampler.cs
  9. 6
      src/ImageProcessorCore/Samplers/Resamplers/IResampler.cs
  10. 6
      src/ImageProcessorCore/Samplers/Resamplers/Lanczos3Resampler.cs
  11. 6
      src/ImageProcessorCore/Samplers/Resamplers/Lanczos5Resampler.cs
  12. 6
      src/ImageProcessorCore/Samplers/Resamplers/Lanczos8Resampler.cs
  13. 8
      src/ImageProcessorCore/Samplers/Resamplers/MitchellNetravaliResampler.cs
  14. 4
      src/ImageProcessorCore/Samplers/Resamplers/NearestNeighborResampler.cs
  15. 8
      src/ImageProcessorCore/Samplers/Resamplers/RobidouxResampler.cs
  16. 8
      src/ImageProcessorCore/Samplers/Resamplers/RobidouxSharpResampler.cs
  17. 26
      src/ImageProcessorCore/Samplers/Resamplers/RobidouxSoftResampler.cs
  18. 8
      src/ImageProcessorCore/Samplers/Resamplers/SplineResampler.cs
  19. 4
      src/ImageProcessorCore/Samplers/Resamplers/TriangleResampler.cs
  20. 6
      src/ImageProcessorCore/Samplers/Resamplers/WelchResampler.cs

22
src/ImageProcessorCore/Common/Helpers/ImageMaths.cs

@ -55,11 +55,11 @@ namespace ImageProcessorCore
/// <param name="b">The B-Spline curve variable.</param>
/// <param name="c">The Cardinal curve variable.</param>
/// <returns>
/// The <see cref="float"/>.
/// The <see cref="double"/>.
/// </returns>
public static float GetBcValue(float x, float b, float c)
public static double GetBcValue(double x, double b, double c)
{
float temp;
double temp;
if (x < 0)
{
@ -87,16 +87,16 @@ namespace ImageProcessorCore
/// </summary>
/// <param name="x">The value to calculate the result for.</param>
/// <returns>
/// The <see cref="float"/>.
/// The <see cref="double"/>.
/// </returns>
public static float SinC(float x)
public static double SinC(double x)
{
const float Epsilon = .00001f;
const double Epsilon = .00001d;
if (Math.Abs(x) > Epsilon)
{
x *= (float)Math.PI;
return Clean((float)Math.Sin(x) / x);
x *= (double)Math.PI;
return Clean((double)Math.Sin(x) / x);
}
return 1.0f;
@ -272,11 +272,11 @@ namespace ImageProcessorCore
/// </summary>
/// <param name="x">The value to clean.</param>
/// <returns>
/// The <see cref="float"/>
/// The <see cref="double"/>
/// </returns>.
private static float Clean(float x)
private static double Clean(double x)
{
const float Epsilon = .00001f;
const double Epsilon = .00001d;
if (Math.Abs(x) < Epsilon)
{

18
src/ImageProcessorCore/PackedVector/Bgra32.cs

@ -160,6 +160,15 @@ namespace ImageProcessorCore
this.A = (byte)(this.A * value);
}
/// <inheritdoc/>
public void Multiply(double value)
{
this.B = (byte)(this.B * value);
this.G = (byte)(this.G * value);
this.R = (byte)(this.R * value);
this.A = (byte)(this.A * value);
}
/// <inheritdoc/>
public void Divide(Bgra32 value)
{
@ -178,6 +187,15 @@ namespace ImageProcessorCore
this.A = (byte)(this.A / value);
}
/// <inheritdoc/>
public void Divide(double value)
{
this.B = (byte)(this.B / value);
this.G = (byte)(this.G / value);
this.R = (byte)(this.R / value);
this.A = (byte)(this.A / value);
}
/// <inheritdoc/>
public uint PackedValue()
{

12
src/ImageProcessorCore/PackedVector/IPackedVector.cs

@ -49,6 +49,12 @@ namespace ImageProcessorCore
/// <param name="value">The value to multiply by.</param>
void Multiply(float value);
/// <summary>
/// Multiplies the given current instance by given the value.
/// </summary>
/// <param name="value">The value to multiply by.</param>
void Multiply(double value);
/// <summary>
/// Divides the given current instance by given the <see cref="T"/>.
/// </summary>
@ -60,6 +66,12 @@ namespace ImageProcessorCore
/// </summary>
/// <param name="value">The value to divide by.</param>
void Divide(float value);
/// <summary>
/// Divides the given current instance by given the value.
/// </summary>
/// <param name="value">The value to divide by.</param>
void Divide(double value);
}
/// <summary>

28
src/ImageProcessorCore/Samplers/Processors/ResizeProcessor.cs

@ -130,7 +130,7 @@ namespace ImageProcessorCore.Processors
{
// Ensure offsets are normalised for cropping and padding.
int offsetX = x - startX;
float sum = this.HorizontalWeights[offsetX].Sum;
double sum = this.HorizontalWeights[offsetX].Sum;
Weight[] horizontalValues = this.HorizontalWeights[offsetX].Values;
// Destination color components
@ -171,7 +171,7 @@ namespace ImageProcessorCore.Processors
{
// Ensure offsets are normalised for cropping and padding.
int offsetY = y - startY;
float sum = this.VerticalWeights[offsetY].Sum;
double sum = this.VerticalWeights[offsetY].Sum;
Weight[] verticalValues = this.VerticalWeights[offsetY].Values;
for (int x = 0; x < width; x++)
@ -229,12 +229,12 @@ namespace ImageProcessorCore.Processors
/// </returns>
protected Weights[] PrecomputeWeights(int destinationSize, int sourceSize)
{
float scale = (float)destinationSize / sourceSize;
double scale = (double)destinationSize / sourceSize;
IResampler sampler = this.Sampler;
float radius = sampler.Radius;
double radius = sampler.Radius;
double left;
double right;
float weight;
double weight;
int index;
int sum;
@ -244,13 +244,13 @@ namespace ImageProcessorCore.Processors
// visit every source pixel.
if (scale < 1)
{
float width = radius / scale;
float filterScale = 1 / scale;
double width = radius / scale;
double filterScale = 1 / scale;
// Make the weights slices, one source for each column or row.
for (int i = 0; i < destinationSize; i++)
{
float centre = i / scale;
double centre = i / scale;
left = Math.Ceiling(centre - width);
right = Math.Floor(centre + width);
@ -261,7 +261,7 @@ namespace ImageProcessorCore.Processors
for (double j = left; j <= right; j++)
{
weight = sampler.GetValue((float)((centre - j) / filterScale)) / filterScale;
weight = sampler.GetValue((centre - j) / filterScale) / filterScale;
if (j < 0)
{
index = (int)-j;
@ -285,7 +285,7 @@ namespace ImageProcessorCore.Processors
// Make the weights slices, one source for each column or row.
for (int i = 0; i < destinationSize; i++)
{
float centre = i / scale;
double centre = i / scale;
left = Math.Ceiling(centre - radius);
right = Math.Floor(centre + radius);
result[i] = new Weights
@ -295,7 +295,7 @@ namespace ImageProcessorCore.Processors
for (double j = left; j <= right; j++)
{
weight = sampler.GetValue((float)(centre - j));
weight = sampler.GetValue(centre - j);
if (j < 0)
{
index = (int)-j;
@ -328,7 +328,7 @@ namespace ImageProcessorCore.Processors
/// </summary>
/// <param name="index">The index.</param>
/// <param name="value">The value.</param>
public Weight(int index, float value)
public Weight(int index, double value)
{
this.Index = index;
this.Value = value;
@ -342,7 +342,7 @@ namespace ImageProcessorCore.Processors
/// <summary>
/// Gets the result of the interpolation algorithm.
/// </summary>
public float Value { get; }
public double Value { get; }
}
/// <summary>
@ -358,7 +358,7 @@ namespace ImageProcessorCore.Processors
/// <summary>
/// Gets or sets the sum.
/// </summary>
public float Sum { get; set; }
public double Sum { get; set; }
}
}
}

12
src/ImageProcessorCore/Samplers/Resamplers/BicubicResampler.cs

@ -13,28 +13,28 @@ namespace ImageProcessorCore
public class BicubicResampler : IResampler
{
/// <inheritdoc/>
public float Radius => 2;
public double Radius => 2;
/// <inheritdoc/>
public float GetValue(float x)
public double GetValue(double x)
{
// The coefficient.
float a = -0.5f;
double a = -0.5d;
if (x < 0)
{
x = -x;
}
float result = 0;
double result = 0;
if (x <= 1)
{
result = (((1.5f * x) - 2.5f) * x * x) + 1;
result = (((1.5d * x) - 2.5d) * x * x) + 1;
}
else if (x < 2)
{
result = (((((a * x) + 2.5f) * x) - 4) * x) + 2;
result = (((((a * x) + 2.5d) * x) - 4) * x) + 2;
}
return result;

4
src/ImageProcessorCore/Samplers/Resamplers/BoxResampler.cs

@ -12,10 +12,10 @@ namespace ImageProcessorCore
public class BoxResampler : IResampler
{
/// <inheritdoc/>
public float Radius => 0.5F;
public double Radius => 0.5d;
/// <inheritdoc/>
public float GetValue(float x)
public double GetValue(double x)
{
if (x > -0.5 && x <= 0.5)
{

8
src/ImageProcessorCore/Samplers/Resamplers/CatmullRomResampler.cs

@ -14,13 +14,13 @@ namespace ImageProcessorCore
public class CatmullRomResampler : IResampler
{
/// <inheritdoc/>
public float Radius => 2;
public double Radius => 2;
/// <inheritdoc/>
public float GetValue(float x)
public double GetValue(double x)
{
const float B = 0;
const float C = 1 / 2f;
const double B = 0;
const double C = 0.5d;
return ImageMaths.GetBcValue(x, B, C);
}

8
src/ImageProcessorCore/Samplers/Resamplers/HermiteResampler.cs

@ -13,13 +13,13 @@ namespace ImageProcessorCore.Processors
public class HermiteResampler : IResampler
{
/// <inheritdoc/>
public float Radius => 2;
public double Radius => 2;
/// <inheritdoc/>
public float GetValue(float x)
public double GetValue(double x)
{
const float B = 0;
const float C = 0;
const double B = 0;
const double C = 0;
return ImageMaths.GetBcValue(x, B, C);
}

6
src/ImageProcessorCore/Samplers/Resamplers/IResampler.cs

@ -13,15 +13,15 @@ namespace ImageProcessorCore
/// <summary>
/// Gets the radius in which to sample pixels.
/// </summary>
float Radius { get; }
double Radius { get; }
/// <summary>
/// Gets the result of the interpolation algorithm.
/// </summary>
/// <param name="x">The value to process.</param>
/// <returns>
/// The <see cref="float"/>
/// The <see cref="double"/>
/// </returns>
float GetValue(float x);
double GetValue(double x);
}
}

6
src/ImageProcessorCore/Samplers/Resamplers/Lanczos3Resampler.cs

@ -13,10 +13,10 @@ namespace ImageProcessorCore
public class Lanczos3Resampler : IResampler
{
/// <inheritdoc/>
public float Radius => 3;
public double Radius => 3;
/// <inheritdoc/>
public float GetValue(float x)
public double GetValue(double x)
{
if (x < 0)
{
@ -25,7 +25,7 @@ namespace ImageProcessorCore
if (x < 3)
{
return ImageMaths.SinC(x) * ImageMaths.SinC(x / 3f);
return ImageMaths.SinC(x) * ImageMaths.SinC(x / 3d);
}
return 0;

6
src/ImageProcessorCore/Samplers/Resamplers/Lanczos5Resampler.cs

@ -13,10 +13,10 @@ namespace ImageProcessorCore
public class Lanczos5Resampler : IResampler
{
/// <inheritdoc/>
public float Radius => 5;
public double Radius => 5;
/// <inheritdoc/>
public float GetValue(float x)
public double GetValue(double x)
{
if (x < 0)
{
@ -25,7 +25,7 @@ namespace ImageProcessorCore
if (x < 5)
{
return ImageMaths.SinC(x) * ImageMaths.SinC(x / 5f);
return ImageMaths.SinC(x) * ImageMaths.SinC(x / 5d);
}
return 0;

6
src/ImageProcessorCore/Samplers/Resamplers/Lanczos8Resampler.cs

@ -13,10 +13,10 @@ namespace ImageProcessorCore
public class Lanczos8Resampler : IResampler
{
/// <inheritdoc/>
public float Radius => 8;
public double Radius => 8;
/// <inheritdoc/>
public float GetValue(float x)
public double GetValue(double x)
{
if (x < 0)
{
@ -25,7 +25,7 @@ namespace ImageProcessorCore
if (x < 8)
{
return ImageMaths.SinC(x) * ImageMaths.SinC(x / 8f);
return ImageMaths.SinC(x) * ImageMaths.SinC(x / 8d);
}
return 0;

8
src/ImageProcessorCore/Samplers/Resamplers/MitchellNetravaliResampler.cs

@ -12,13 +12,13 @@ namespace ImageProcessorCore
public class MitchellNetravaliResampler : IResampler
{
/// <inheritdoc/>
public float Radius => 2;
public double Radius => 2;
/// <inheritdoc/>
public float GetValue(float x)
public double GetValue(double x)
{
const float B = 1 / 3f;
const float C = 1 / 3f;
const double B = 0.333333333333333D;
const double C = 0.333333333333333D;
return ImageMaths.GetBcValue(x, B, C);
}

4
src/ImageProcessorCore/Samplers/Resamplers/NearestNeighborResampler.cs

@ -12,10 +12,10 @@ namespace ImageProcessorCore
public class NearestNeighborResampler : IResampler
{
/// <inheritdoc/>
public float Radius => 1;
public double Radius => 1;
/// <inheritdoc/>
public float GetValue(float x)
public double GetValue(double x)
{
return x;
}

8
src/ImageProcessorCore/Samplers/Resamplers/RobidouxResampler.cs

@ -12,13 +12,13 @@ namespace ImageProcessorCore
public class RobidouxResampler : IResampler
{
/// <inheritdoc/>
public float Radius => 2;
public double Radius => 2;
/// <inheritdoc/>
public float GetValue(float x)
public double GetValue(double x)
{
const float B = 0.3782158F;
const float C = 0.3108921F;
const double B = 0.37821575509399867D;
const double C = 0.31089212245300067D;
return ImageMaths.GetBcValue(x, B, C);
}

8
src/ImageProcessorCore/Samplers/Resamplers/RobidouxSharpResampler.cs

@ -12,13 +12,13 @@ namespace ImageProcessorCore
public class RobidouxSharpResampler : IResampler
{
/// <inheritdoc/>
public float Radius => 2;
public double Radius => 2;
/// <inheritdoc/>
public float GetValue(float x)
public double GetValue(double x)
{
const float B = 0.26201451F;
const float C = 0.36899274F;
const double B = 0.2620145123990142D;
const double C = 0.3689927438004929D;
return ImageMaths.GetBcValue(x, B, C);
}

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

@ -1,26 +0,0 @@
// <copyright file="RobidouxSoftResampler.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageProcessorCore
{
/// <summary>
/// The function implements the Robidoux Soft algorithm.
/// <see href="http://www.imagemagick.org/Usage/filter/#robidoux"/>
/// </summary>
public class RobidouxSoftResampler : IResampler
{
/// <inheritdoc/>
public float Radius => 2;
/// <inheritdoc/>
public float GetValue(float x)
{
const float B = 0.6796f;
const float C = 0.1602f;
return ImageMaths.GetBcValue(x, B, C);
}
}
}

8
src/ImageProcessorCore/Samplers/Resamplers/SplineResampler.cs

@ -12,13 +12,13 @@ namespace ImageProcessorCore
public class SplineResampler : IResampler
{
/// <inheritdoc/>
public float Radius => 2;
public double Radius => 2;
/// <inheritdoc/>
public float GetValue(float x)
public double GetValue(double x)
{
const float B = 1;
const float C = 0;
const double B = 1;
const double C = 0;
return ImageMaths.GetBcValue(x, B, C);
}

4
src/ImageProcessorCore/Samplers/Resamplers/TriangleResampler.cs

@ -13,10 +13,10 @@ namespace ImageProcessorCore
public class TriangleResampler : IResampler
{
/// <inheritdoc/>
public float Radius => 1;
public double Radius => 1;
/// <inheritdoc/>
public float GetValue(float x)
public double GetValue(double x)
{
if (x < 0)
{

6
src/ImageProcessorCore/Samplers/Resamplers/WelchResampler.cs

@ -12,10 +12,10 @@ namespace ImageProcessorCore
public class WelchResampler : IResampler
{
/// <inheritdoc/>
public float Radius => 3;
public double Radius => 3;
/// <inheritdoc/>
public float GetValue(float x)
public double GetValue(double x)
{
if (x < 0)
{
@ -24,7 +24,7 @@ namespace ImageProcessorCore
if (x < 3)
{
return ImageMaths.SinC(x) * (1.0f - (x * x / 9.0f));
return ImageMaths.SinC(x) * (1.0d - (x * x / 9.0d));
}
return 0;

Loading…
Cancel
Save