Browse Source

Fix Resizer

Fix #394


Former-commit-id: 490723c7f33cbab80264901ad252541a44b1dc73
Former-commit-id: 60edb602bc6236d29495081697e2f385aaa84320
Former-commit-id: abf91473873cfad473325c0af36a7026f5e40709
af/merge-core
James Jackson-South 10 years ago
parent
commit
2771f593f6
  1. 2
      src/ImageProcessorCore/Samplers/Resampler.cs
  2. 108
      src/ImageProcessorCore/Samplers/Resize.cs
  3. 4
      src/ImageProcessorCore/Samplers/ResizeHelper.cs
  4. 47
      tests/ImageProcessorCore.Tests/Processors/Samplers/SamplerTests.cs

2
src/ImageProcessorCore/Samplers/Resampler.cs

@ -151,7 +151,7 @@ namespace ImageProcessorCore.Samplers
protected struct Weight
{
/// <summary>
/// Initializes a new instance of the <see cref="Weight"/> class.
/// Initializes a new instance of the <see cref="Weight"/> struct.
/// </summary>
/// <param name="index">The index.</param>
/// <param name="value">The value.</param>

108
src/ImageProcessorCore/Samplers/Resize.cs

@ -47,7 +47,6 @@ namespace ImageProcessorCore.Samplers
protected override void Apply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY)
{
// Jump out, we'll deal with that later.
// TODO: Add rectangle comparison.
if (source.Bounds == target.Bounds && sourceRectangle == targetRectangle)
{
return;
@ -104,80 +103,77 @@ namespace ImageProcessorCore.Samplers
// First process the columns. Since we are not using multiple threads startY and endY
// are the upper and lower bounds of the source rectangle.
Parallel.For(
startY,
endY,
0,
sourceHeight,
y =>
{
// Ensure offsets are normalised for cropping and padding.
int offsetY = y - startY;
for (int x = startX; x < endX; x++)
{
int offsetX = x - startX;
float sum = this.HorizontalWeights[offsetX].Sum;
Weight[] horizontalValues = this.HorizontalWeights[offsetX].Values;
for (int x = startX; x < endX; x++)
{
if (x >= 0 && x < width)
{
// Ensure offsets are normalised for cropping and padding.
int offsetX = x - startX;
float sum = this.HorizontalWeights[offsetX].Sum;
Weight[] horizontalValues = this.HorizontalWeights[offsetX].Values;
// Destination color components
Color destination = new Color();
// Destination color components
Color destination = new Color();
for (int i = 0; i < sum; i++)
{
Weight xw = horizontalValues[i];
int originX = xw.Index;
Color sourceColor = compand ? Color.Expand(source[originX, offsetY]) : source[originX, offsetY];
destination += sourceColor * xw.Value;
}
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;
}
if (compand)
{
destination = Color.Compress(destination);
}
if (compand)
{
destination = Color.Compress(destination);
}
if (x >= 0 && x < width && offsetY >= 0 && offsetY < sourceHeight)
{
this.firstPass[x, offsetY] = destination;
this.firstPass[x, y] = destination;
}
}
}
});
});
// Now process the rows.
Parallel.For(
startY,
endY,
y =>
{
// Ensure offsets are normalised for cropping and padding.
int offsetY = y - startY;
float sum = this.VerticalWeights[offsetY].Sum;
Weight[] verticalValues = this.VerticalWeights[offsetY].Values;
for (int x = 0; x < width; x++)
{
// Destination color components
Color destination = new Color();
for (int i = 0; i < sum; i++)
if (y >= 0 && y < height)
{
Weight yw = verticalValues[i];
int originY = yw.Index;
Color sourceColor = compand ? Color.Expand(this.firstPass[x, originY]) : this.firstPass[x, originY];
destination += sourceColor * yw.Value;
}
// Ensure offsets are normalised for cropping and padding.
int offsetY = y - startY;
float sum = this.VerticalWeights[offsetY].Sum;
Weight[] verticalValues = this.VerticalWeights[offsetY].Values;
if (compand)
{
destination = Color.Compress(destination);
}
for (int x = 0; x < width; x++)
{
// Destination color components
Color destination = new Color();
if (y >= 0 && y < height)
{
target[x, y] = destination;
for (int i = 0; i < sum; i++)
{
Weight yw = verticalValues[i];
int originY = yw.Index;
Color sourceColor = compand ? Color.Expand(this.firstPass[x, originY]) : this.firstPass[x, originY];
destination += sourceColor * yw.Value;
}
if (compand)
{
destination = Color.Compress(destination);
}
target[x, y] = destination;
}
}
}
this.OnRowProcessed();
});
this.OnRowProcessed();
});
}
/// <inheritdoc/>

4
src/ImageProcessorCore/Samplers/ResizeHelper.cs

@ -394,12 +394,14 @@ namespace ImageProcessorCore.Samplers
if (widthDiff < heightDiff)
{
destinationHeight = Convert.ToInt32(width * sourceRatio);
height = destinationHeight;
destinationWidth = width;
}
else if (widthDiff > heightDiff)
{
destinationHeight = height;
destinationWidth = Convert.ToInt32(height / sourceRatio);
destinationHeight = height;
width = destinationWidth;
}
else
{

47
tests/ImageProcessorCore.Tests/Processors/Samplers/SamplerTests.cs

@ -182,7 +182,7 @@
{
ResizeOptions options = new ResizeOptions()
{
Size = new Size(image.Width , image.Height / 2)
Size = new Size(image.Width / 2, image.Height)
};
image.Resize(options, this.ProgressUpdate)
@ -214,9 +214,8 @@
{
ResizeOptions options = new ResizeOptions()
{
Size = new Size(image.Width , image.Height + 200),
Mode = ResizeMode.Pad,
Sampler = new NearestNeighborResampler()
Size = new Size(image.Width + 200, image.Height),
Mode = ResizeMode.Pad
};
image.Resize(options, this.ProgressUpdate)
@ -281,8 +280,9 @@
{
ResizeOptions options = new ResizeOptions()
{
Size = new Size(image.Width + 200, image.Height),
Mode = ResizeMode.Max
Size = new Size(300, 300),
Mode = ResizeMode.Max,
//Sampler = new NearestNeighborResampler()
};
image.Resize(options, this.ProgressUpdate)
@ -314,7 +314,7 @@
{
ResizeOptions options = new ResizeOptions()
{
Size = new Size(image.Width + 200, image.Height),
Size = new Size(image.Width - 50, image.Height - 25),
Mode = ResizeMode.Min
};
@ -327,6 +327,39 @@
}
}
[Fact]
public void ImageShouldResizeWithStretchMode()
{
if (!Directory.Exists("TestOutput/ResizeStretch"))
{
Directory.CreateDirectory("TestOutput/ResizeStretch");
}
foreach (string file in Files)
{
using (FileStream stream = File.OpenRead(file))
{
Stopwatch watch = Stopwatch.StartNew();
string filename = Path.GetFileName(file);
using (Image image = new Image(stream))
using (FileStream output = File.OpenWrite($"TestOutput/ResizeStretch/{filename}"))
{
ResizeOptions options = new ResizeOptions()
{
Size = new Size(image.Width - 200, image.Height),
Mode = ResizeMode.Stretch
};
image.Resize(options, this.ProgressUpdate)
.Save(output);
}
Trace.WriteLine($"{filename}: {watch.ElapsedMilliseconds}ms");
}
}
}
[Theory]
[MemberData("RotateFlips")]
public void ImageShouldRotateFlip(RotateType rotateType, FlipType flipType)

Loading…
Cancel
Save