diff --git a/src/ImageProcessorCore/Samplers/Resampler.cs b/src/ImageProcessorCore/Samplers/Resampler.cs
index 4b7239af4..0554b18e0 100644
--- a/src/ImageProcessorCore/Samplers/Resampler.cs
+++ b/src/ImageProcessorCore/Samplers/Resampler.cs
@@ -11,6 +11,8 @@ namespace ImageProcessorCore.Samplers
///
/// Provides methods that allow the resampling of images using various algorithms.
+ ///
+ ///
///
public abstract class Resampler : ImageSampler
{
@@ -52,74 +54,171 @@ namespace ImageProcessorCore.Samplers
///
protected Weights[] PrecomputeWeights(int destinationSize, int sourceSize)
{
+ float xscale = destinationSize / (float)sourceSize;
+ float width;
IResampler sampler = this.Sampler;
- float ratio = sourceSize / (float)destinationSize;
- float scale = ratio;
+ float fwidth = sampler.Radius;
+ float fscale;
+ double left;
+ double right;
+ double weight = 0;
+ int n = 0;
+ int k;
- // When shrinking, broaden the effective kernel support so that we still
+ Weights[] result = new Weights[destinationSize];
+
+ // When expanding, broaden the effective kernel support so that we still
// visit every source pixel.
- if (scale < 1)
+ if (xscale < 0)
{
- scale = 1;
- }
+ width = sampler.Radius / xscale;
+ fscale = 1 / xscale;
- 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 =>
+ // Make the weights slices, one source for each column or row.
+ for (int i = 0; i < 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)
+ float centre = i / xscale;
+ left = Math.Ceiling(centre - width);
+ right = Math.Floor(centre + width);
+ float sum = 0;
+ result[i] = new Weights();
+ List builder = new List();
+ for (double j = left; j <= right; j++)
{
- end = sourceSize;
-
- if (end < start)
+ weight = centre - j;
+ weight = sampler.GetValue((float)weight / fscale) / fscale;
+ if (j < 0)
+ {
+ n = (int)-j;
+ }
+ else if (j >= sourceSize)
+ {
+ n = (int)((sourceSize - j) + sourceSize - 1);
+ }
+ else
{
- end = start;
+ n = (int)j;
}
+
+ sum++;
+ builder.Add(new Weight(n, (float)weight));
}
+ result[i].Values = builder.ToArray();
+ result[i].Sum = sum;
+ }
+ }
+ else
+ {
+ // 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();
List builder = new List();
- for (int a = start; a < end; a++)
+ for (double j = left; j <= right; j++)
{
- float w = sampler.GetValue((a - center) / scale);
-
- if (w < 0 || w > 0)
+ weight = centre - j;
+ weight = sampler.GetValue((float)weight);
+ if (j < 0)
{
- sum += w;
- builder.Add(new Weight(a, w));
+ n = (int)-j;
+ }
+ else if (j >= sourceSize)
+ {
+ n = (int)((sourceSize - j) + sourceSize - 1);
+ }
+ else
+ {
+ n = (int)j;
}
- }
- // Normalise the values
- if (sum > 0 || sum < 0)
- {
- builder.ForEach(w => w.Value /= sum);
+ sum++;
+ builder.Add(new Weight(n, (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 builder = new List();
+ // 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;
+ //}
+
///
/// Represents the weight to be added to a scaled pixel.
///
diff --git a/src/ImageProcessorCore/Samplers/Resize.cs b/src/ImageProcessorCore/Samplers/Resize.cs
index ce4d513ac..dc6a92f5e 100644
--- a/src/ImageProcessorCore/Samplers/Resize.cs
+++ b/src/ImageProcessorCore/Samplers/Resize.cs
@@ -100,18 +100,27 @@ namespace ImageProcessorCore.Samplers
{
for (int x = startX; x < endX; x++)
{
+ float sum = this.HorizontalWeights[x].Sum;
Weight[] horizontalValues = this.HorizontalWeights[x].Values;
// Destination color components
Color destination = new Color();
- foreach (Weight xw in horizontalValues)
+ for (int i = 0; i < sum; i++)
{
+ Weight xw = horizontalValues[i];
int originX = xw.Index;
Color sourceColor = compand ? Color.Expand(source[originX, y]) : source[originX, y];
destination += sourceColor * xw.Value;
}
+ //foreach (Weight xw in horizontalValues)
+ //{
+ // int originX = xw.Index;
+ // Color sourceColor = compand ? Color.Expand(source[originX, y]) : source[originX, y];
+ // destination += sourceColor * xw.Value;
+ //}
+
if (compand)
{
destination = Color.Compress(destination);
@@ -129,6 +138,7 @@ namespace ImageProcessorCore.Samplers
{
if (y >= targetY && y < targetBottom)
{
+ float sum = this.VerticalWeights[y].Sum;
Weight[] verticalValues = this.VerticalWeights[y].Values;
for (int x = startX; x < endX; x++)
@@ -136,14 +146,23 @@ namespace ImageProcessorCore.Samplers
// Destination color components
Color destination = new Color();
- foreach (Weight yw in verticalValues)
+ for (int i = 0; i < sum; i++)
{
+ Weight yw = verticalValues[i];
int originY = yw.Index;
int originX = x;
Color sourceColor = compand ? Color.Expand(this.firstPass[originX, originY]) : this.firstPass[originX, originY];
destination += sourceColor * yw.Value;
}
+ //foreach (Weight yw in verticalValues)
+ //{
+ // int originY = yw.Index;
+ // int originX = x;
+ // Color sourceColor = compand ? Color.Expand(this.firstPass[originX, originY]) : this.firstPass[originX, originY];
+ // destination += sourceColor * yw.Value;
+ //}
+
if (compand)
{
destination = Color.Compress(destination);
diff --git a/tests/ImageProcessorCore.Tests/Processors/Samplers/SamplerTests.cs b/tests/ImageProcessorCore.Tests/Processors/Samplers/SamplerTests.cs
index 925d1340b..c419ae560 100644
--- a/tests/ImageProcessorCore.Tests/Processors/Samplers/SamplerTests.cs
+++ b/tests/ImageProcessorCore.Tests/Processors/Samplers/SamplerTests.cs
@@ -92,7 +92,7 @@
string filename = Path.GetFileNameWithoutExtension(file) + "-" + name + Path.GetExtension(file);
using (FileStream output = File.OpenWrite($"TestOutput/Resize/{filename}"))
{
- image.Resize(image.Width / 2, image.Height / 2, sampler, false, this.ProgressUpdate)
+ image.Resize(image.Width * 2, image.Height * 2, sampler, false, this.ProgressUpdate)
.Save(output);
}