Browse Source

Resize now 10% faster

Former-commit-id: 8d123c508edef580da7e7226d9dc94b42e0261c2
Former-commit-id: 3fb2cf0b1318711665772efbd37a1e05ea8c39bd
Former-commit-id: 89e4d4123421180721162e5159406483c574bbb2
pull/1/head
James Jackson-South 10 years ago
parent
commit
562bb03b43
  1. 36
      src/ImageProcessorCore/Samplers/Processors/CompandingResizeProcessor.cs
  2. 36
      src/ImageProcessorCore/Samplers/Processors/ResizeProcessor.cs
  3. 37
      tests/ImageProcessorCore.Tests/Processors/Samplers/ResizeTests.cs

36
src/ImageProcessorCore/Samplers/Processors/CompandingResizeProcessor.cs

@ -5,6 +5,7 @@
namespace ImageProcessorCore.Processors namespace ImageProcessorCore.Processors
{ {
using System;
using System.Numerics; using System.Numerics;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -50,7 +51,11 @@ namespace ImageProcessorCore.Processors
int targetBottom = target.Bounds.Bottom; int targetBottom = target.Bounds.Bottom;
int startX = targetRectangle.X; int startX = targetRectangle.X;
int endX = targetRectangle.Right; int endX = targetRectangle.Right;
bool compand = this.Compand;
int minX = Math.Max(targetX, startX);
int maxX = Math.Min(targetRight, endX);
int minY = Math.Max(targetY, startY);
int maxY = Math.Min(targetBottom, endY);
if (this.Sampler is NearestNeighborResampler) if (this.Sampler is NearestNeighborResampler)
{ {
@ -62,27 +67,21 @@ namespace ImageProcessorCore.Processors
using (IPixelAccessor<T, TP> targetPixels = target.Lock()) using (IPixelAccessor<T, TP> targetPixels = target.Lock())
{ {
Parallel.For( Parallel.For(
startY, minY,
endY, maxY,
this.ParallelOptions, this.ParallelOptions,
y => y =>
{
if (targetY <= y && y < targetBottom)
{ {
// Y coordinates of source points // Y coordinates of source points
int originY = (int)((y - startY) * heightFactor); int originY = (int)((y - startY) * heightFactor);
for (int x = startX; x < endX; x++) for (int x = minX; x < maxX; x++)
{
if (targetX <= x && x < targetRight)
{ {
// X coordinates of source points // X coordinates of source points
targetPixels[x, y] = sourcePixels[(int)((x - startX) * widthFactor), originY]; targetPixels[x, y] = sourcePixels[(int)((x - startX) * widthFactor), originY];
} }
}
this.OnRowProcessed(); this.OnRowProcessed();
}
}); });
} }
@ -99,15 +98,18 @@ namespace ImageProcessorCore.Processors
using (IPixelAccessor<T, TP> firstPassPixels = firstPass.Lock()) using (IPixelAccessor<T, TP> firstPassPixels = firstPass.Lock())
using (IPixelAccessor<T, TP> targetPixels = target.Lock()) using (IPixelAccessor<T, TP> targetPixels = target.Lock())
{ {
minX = Math.Max(0, startX);
maxX = Math.Min(width, endX);
minY = Math.Max(0, startY);
maxY = Math.Min(height, endY);
Parallel.For( Parallel.For(
0, 0,
sourceHeight, sourceHeight,
this.ParallelOptions, this.ParallelOptions,
y => y =>
{ {
for (int x = startX; x < endX; x++) for (int x = minX; x < maxX; x++)
{
if (x >= 0 && x < width)
{ {
// Ensure offsets are normalised for cropping and padding. // Ensure offsets are normalised for cropping and padding.
Weight[] horizontalValues = this.HorizontalWeights[x - startX].Values; Weight[] horizontalValues = this.HorizontalWeights[x - startX].Values;
@ -125,17 +127,14 @@ namespace ImageProcessorCore.Processors
d.PackVector(destination.Compress()); d.PackVector(destination.Compress());
firstPassPixels[x, y] = d; firstPassPixels[x, y] = d;
} }
}
}); });
// Now process the rows. // Now process the rows.
Parallel.For( Parallel.For(
startY, minY,
endY, maxY,
this.ParallelOptions, this.ParallelOptions,
y => y =>
{
if (y >= 0 && y < height)
{ {
// Ensure offsets are normalised for cropping and padding. // Ensure offsets are normalised for cropping and padding.
Weight[] verticalValues = this.VerticalWeights[y - startY].Values; Weight[] verticalValues = this.VerticalWeights[y - startY].Values;
@ -155,7 +154,6 @@ namespace ImageProcessorCore.Processors
d.PackVector(destination.Compress()); d.PackVector(destination.Compress());
targetPixels[x, y] = d; targetPixels[x, y] = d;
} }
}
this.OnRowProcessed(); this.OnRowProcessed();
}); });

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

@ -5,6 +5,7 @@
namespace ImageProcessorCore.Processors namespace ImageProcessorCore.Processors
{ {
using System;
using System.Numerics; using System.Numerics;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -50,6 +51,11 @@ namespace ImageProcessorCore.Processors
int startX = targetRectangle.X; int startX = targetRectangle.X;
int endX = targetRectangle.Right; int endX = targetRectangle.Right;
int minX = Math.Max(targetX, startX);
int maxX = Math.Min(targetRight, endX);
int minY = Math.Max(targetY, startY);
int maxY = Math.Min(targetBottom, endY);
if (this.Sampler is NearestNeighborResampler) if (this.Sampler is NearestNeighborResampler)
{ {
// Scaling factors // Scaling factors
@ -60,27 +66,21 @@ namespace ImageProcessorCore.Processors
using (IPixelAccessor<T, TP> targetPixels = target.Lock()) using (IPixelAccessor<T, TP> targetPixels = target.Lock())
{ {
Parallel.For( Parallel.For(
startY, minY,
endY, maxY,
this.ParallelOptions, this.ParallelOptions,
y => y =>
{
if (targetY <= y && y < targetBottom)
{ {
// Y coordinates of source points // Y coordinates of source points
int originY = (int)((y - startY) * heightFactor); int originY = (int)((y - startY) * heightFactor);
for (int x = startX; x < endX; x++) for (int x = minX; x < maxX; x++)
{
if (targetX <= x && x < targetRight)
{ {
// X coordinates of source points // X coordinates of source points
targetPixels[x, y] = sourcePixels[(int)((x - startX) * widthFactor), originY]; targetPixels[x, y] = sourcePixels[(int)((x - startX) * widthFactor), originY];
} }
}
this.OnRowProcessed(); this.OnRowProcessed();
}
}); });
} }
@ -97,15 +97,18 @@ namespace ImageProcessorCore.Processors
using (IPixelAccessor<T, TP> firstPassPixels = firstPass.Lock()) using (IPixelAccessor<T, TP> firstPassPixels = firstPass.Lock())
using (IPixelAccessor<T, TP> targetPixels = target.Lock()) using (IPixelAccessor<T, TP> targetPixels = target.Lock())
{ {
minX = Math.Max(0, startX);
maxX = Math.Min(width, endX);
minY = Math.Max(0, startY);
maxY = Math.Min(height, endY);
Parallel.For( Parallel.For(
0, 0,
sourceHeight, sourceHeight,
this.ParallelOptions, this.ParallelOptions,
y => y =>
{ {
for (int x = startX; x < endX; x++) for (int x = minX; x < maxX; x++)
{
if (x >= 0 && x < width)
{ {
// Ensure offsets are normalised for cropping and padding. // Ensure offsets are normalised for cropping and padding.
Weight[] horizontalValues = this.HorizontalWeights[x - startX].Values; Weight[] horizontalValues = this.HorizontalWeights[x - startX].Values;
@ -123,17 +126,14 @@ namespace ImageProcessorCore.Processors
d.PackVector(destination); d.PackVector(destination);
firstPassPixels[x, y] = d; firstPassPixels[x, y] = d;
} }
}
}); });
// Now process the rows. // Now process the rows.
Parallel.For( Parallel.For(
startY, minY,
endY, maxY,
this.ParallelOptions, this.ParallelOptions,
y => y =>
{
if (y >= 0 && y < height)
{ {
// Ensure offsets are normalised for cropping and padding. // Ensure offsets are normalised for cropping and padding.
Weight[] verticalValues = this.VerticalWeights[y - startY].Values; Weight[] verticalValues = this.VerticalWeights[y - startY].Values;
@ -153,11 +153,9 @@ namespace ImageProcessorCore.Processors
d.PackVector(destination); d.PackVector(destination);
targetPixels[x, y] = d; targetPixels[x, y] = d;
} }
}
this.OnRowProcessed(); this.OnRowProcessed();
}); });
} }
} }
} }

37
tests/ImageProcessorCore.Tests/Processors/Samplers/ResizeTests.cs

@ -115,9 +115,9 @@ namespace ImageProcessorCore.Tests
[Theory] [Theory]
[MemberData("ReSamplers")] [MemberData("ReSamplers")]
public void ImageShouldResizeWithCropMode(string name, IResampler sampler) public void ImageShouldResizeWithCropWidthMode(string name, IResampler sampler)
{ {
name = name + "-Crop"; name = name + "-CropWidth";
if (!Directory.Exists(path)) if (!Directory.Exists(path))
{ {
@ -146,6 +146,39 @@ namespace ImageProcessorCore.Tests
} }
} }
[Theory]
[MemberData("ReSamplers")]
public void ImageShouldResizeWithCropHeightMode(string name, IResampler sampler)
{
name = name + "-CropHeight";
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
foreach (string file in Files)
{
using (FileStream stream = File.OpenRead(file))
{
string filename = Path.GetFileNameWithoutExtension(file) + "-" + name + Path.GetExtension(file);
Image image = new Image(stream);
using (FileStream output = File.OpenWrite($"{path}/{filename}"))
{
ResizeOptions options = new ResizeOptions()
{
Sampler = sampler,
Size = new Size(image.Width, image.Height / 2)
};
image.Resize(options, this.ProgressUpdate)
.Save(output);
}
}
}
}
[Theory] [Theory]
[MemberData("ReSamplers")] [MemberData("ReSamplers")]
public void ImageShouldResizeWithPadMode(string name, IResampler sampler) public void ImageShouldResizeWithPadMode(string name, IResampler sampler)

Loading…
Cancel
Save