|
|
|
@ -6,8 +6,6 @@ |
|
|
|
namespace ImageProcessorCore.Samplers |
|
|
|
{ |
|
|
|
using System; |
|
|
|
using System.Collections.Generic; |
|
|
|
using System.Threading.Tasks; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Provides methods that allow the resampling of images using various algorithms.
|
|
|
|
@ -54,58 +52,57 @@ namespace ImageProcessorCore.Samplers |
|
|
|
/// </returns>
|
|
|
|
protected Weights[] PrecomputeWeights(int destinationSize, int sourceSize) |
|
|
|
{ |
|
|
|
float xscale = destinationSize / (float)sourceSize; |
|
|
|
float width; |
|
|
|
float scale = (float)destinationSize / sourceSize; |
|
|
|
IResampler sampler = this.Sampler; |
|
|
|
float fwidth = sampler.Radius; |
|
|
|
float fscale; |
|
|
|
float radius = sampler.Radius; |
|
|
|
double left; |
|
|
|
double right; |
|
|
|
double weight = 0; |
|
|
|
int n = 0; |
|
|
|
int k; |
|
|
|
double weight; |
|
|
|
int index; |
|
|
|
int sum; |
|
|
|
|
|
|
|
Weights[] result = new Weights[destinationSize]; |
|
|
|
|
|
|
|
// When expanding, broaden the effective kernel support so that we still
|
|
|
|
// When shrinking, broaden the effective kernel support so that we still
|
|
|
|
// visit every source pixel.
|
|
|
|
if (xscale < 0) |
|
|
|
if (scale < 1) |
|
|
|
{ |
|
|
|
width = sampler.Radius / xscale; |
|
|
|
fscale = 1 / xscale; |
|
|
|
float width = radius / scale; |
|
|
|
float filterScale = 1 / scale; |
|
|
|
|
|
|
|
// Make the weights slices, one source for each column or row.
|
|
|
|
for (int i = 0; i < destinationSize; i++) |
|
|
|
{ |
|
|
|
float centre = i / xscale; |
|
|
|
float centre = i / scale; |
|
|
|
left = Math.Ceiling(centre - width); |
|
|
|
right = Math.Floor(centre + width); |
|
|
|
float sum = 0; |
|
|
|
result[i] = new Weights(); |
|
|
|
List<Weight> builder = new List<Weight>(); |
|
|
|
|
|
|
|
result[i] = new Weights |
|
|
|
{ |
|
|
|
Sum = 0, |
|
|
|
Values = new Weight[(int)Math.Floor(2 * width + 1)] |
|
|
|
}; |
|
|
|
|
|
|
|
for (double j = left; j <= right; j++) |
|
|
|
{ |
|
|
|
weight = centre - j; |
|
|
|
weight = sampler.GetValue((float)weight / fscale) / fscale; |
|
|
|
weight = sampler.GetValue((float)(weight / filterScale)) / filterScale; |
|
|
|
if (j < 0) |
|
|
|
{ |
|
|
|
n = (int)-j; |
|
|
|
index = (int)-j; |
|
|
|
} |
|
|
|
else if (j >= sourceSize) |
|
|
|
{ |
|
|
|
n = (int)((sourceSize - j) + sourceSize - 1); |
|
|
|
index = (int)((sourceSize - j) + sourceSize - 1); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
n = (int)j; |
|
|
|
index = (int)j; |
|
|
|
} |
|
|
|
|
|
|
|
sum++; |
|
|
|
builder.Add(new Weight(n, (float)weight)); |
|
|
|
sum = (int)result[i].Sum++; |
|
|
|
result[i].Values[sum] = new Weight(index, (float)weight); |
|
|
|
} |
|
|
|
|
|
|
|
result[i].Values = builder.ToArray(); |
|
|
|
result[i].Sum = sum; |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
@ -113,122 +110,46 @@ namespace ImageProcessorCore.Samplers |
|
|
|
// Make the weights slices, one source for each column or row.
|
|
|
|
for (int i = 0; i < destinationSize; i++) |
|
|
|
{ |
|
|
|
float centre = i / xscale; |
|
|
|
left = Math.Ceiling(centre - fwidth); |
|
|
|
right = Math.Floor(centre + fwidth); |
|
|
|
float sum = 0; |
|
|
|
result[i] = new Weights(); |
|
|
|
float centre = i / scale; |
|
|
|
left = Math.Ceiling(centre - radius); |
|
|
|
right = Math.Floor(centre + radius); |
|
|
|
result[i] = new Weights |
|
|
|
{ |
|
|
|
Sum = 0, |
|
|
|
Values = new Weight[(int)(radius * 2 + 1)] |
|
|
|
}; |
|
|
|
|
|
|
|
List<Weight> builder = new List<Weight>(); |
|
|
|
for (double j = left; j <= right; j++) |
|
|
|
{ |
|
|
|
weight = centre - j; |
|
|
|
weight = sampler.GetValue((float)weight); |
|
|
|
if (j < 0) |
|
|
|
{ |
|
|
|
n = (int)-j; |
|
|
|
index = (int)-j; |
|
|
|
} |
|
|
|
else if (j >= sourceSize) |
|
|
|
{ |
|
|
|
n = (int)((sourceSize - j) + sourceSize - 1); |
|
|
|
index = (int)((sourceSize - j) + sourceSize - 1); |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
n = (int)j; |
|
|
|
index = (int)j; |
|
|
|
} |
|
|
|
|
|
|
|
sum++; |
|
|
|
builder.Add(new Weight(n, (float)weight)); |
|
|
|
sum = (int)result[i].Sum++; |
|
|
|
result[i].Values[sum] = new Weight(index, (float)weight); |
|
|
|
} |
|
|
|
|
|
|
|
result[i].Values = builder.ToArray(); |
|
|
|
result[i].Sum = sum; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return result; |
|
|
|
} |
|
|
|
|
|
|
|
//protected Weights[] PrecomputeWeights(int destinationSize, int sourceSize)
|
|
|
|
//{
|
|
|
|
// IResampler sampler = this.Sampler;
|
|
|
|
// float ratio = sourceSize / (float)destinationSize;
|
|
|
|
// float scale = ratio;
|
|
|
|
|
|
|
|
// // When shrinking, broaden the effective kernel support so that we still
|
|
|
|
// // visit every source pixel.
|
|
|
|
// if (scale < 1)
|
|
|
|
// {
|
|
|
|
// scale = 1;
|
|
|
|
// }
|
|
|
|
|
|
|
|
// float scaledRadius = (float)Math.Ceiling(scale * sampler.Radius);
|
|
|
|
// Weights[] result = new Weights[destinationSize];
|
|
|
|
|
|
|
|
// // Make the weights slices, one source for each column or row.
|
|
|
|
// Parallel.For(
|
|
|
|
// 0,
|
|
|
|
// destinationSize,
|
|
|
|
// i =>
|
|
|
|
// {
|
|
|
|
// float center = ((i + .5f) * ratio) - 0.5f;
|
|
|
|
// int start = (int)Math.Ceiling(center - scaledRadius);
|
|
|
|
|
|
|
|
// if (start < 0)
|
|
|
|
// {
|
|
|
|
// start = 0;
|
|
|
|
// }
|
|
|
|
|
|
|
|
// int end = (int)Math.Floor(center + scaledRadius);
|
|
|
|
|
|
|
|
// if (end > sourceSize)
|
|
|
|
// {
|
|
|
|
// end = sourceSize;
|
|
|
|
|
|
|
|
// if (end < start)
|
|
|
|
// {
|
|
|
|
// end = start;
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
|
|
|
|
// float sum = 0;
|
|
|
|
// result[i] = new Weights();
|
|
|
|
|
|
|
|
// List<Weight> builder = new List<Weight>();
|
|
|
|
// for (int a = start; a < end; a++)
|
|
|
|
// {
|
|
|
|
// float w = sampler.GetValue((a - center) / scale);
|
|
|
|
|
|
|
|
// if (w < 0 || w > 0)
|
|
|
|
// {
|
|
|
|
// sum += w;
|
|
|
|
// builder.Add(new Weight(a, w));
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
|
|
|
|
// // Normalise the values
|
|
|
|
// if (sum > 0 || sum < 0)
|
|
|
|
// {
|
|
|
|
// builder.ForEach(w => w.Value /= sum);
|
|
|
|
// }
|
|
|
|
|
|
|
|
// result[i].Values = builder.ToArray();
|
|
|
|
// result[i].Sum = sum;
|
|
|
|
// });
|
|
|
|
|
|
|
|
// return result;
|
|
|
|
//}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Represents the weight to be added to a scaled pixel.
|
|
|
|
/// </summary>
|
|
|
|
protected class Weight |
|
|
|
protected struct Weight |
|
|
|
{ |
|
|
|
/// <summary>
|
|
|
|
/// The pixel index.
|
|
|
|
/// </summary>
|
|
|
|
public readonly int Index; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Initializes a new instance of the <see cref="Weight"/> class.
|
|
|
|
/// </summary>
|
|
|
|
@ -241,9 +162,14 @@ namespace ImageProcessorCore.Samplers |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Gets or sets the result of the interpolation algorithm.
|
|
|
|
/// Gets the pixel index.
|
|
|
|
/// </summary>
|
|
|
|
public int Index { get; } |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Gets the result of the interpolation algorithm.
|
|
|
|
/// </summary>
|
|
|
|
public float Value { get; set; } |
|
|
|
public float Value { get; } |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
@ -262,4 +188,4 @@ namespace ImageProcessorCore.Samplers |
|
|
|
public float Sum { get; set; } |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |