diff --git a/src/ImageProcessor/Filters/Contrast.cs b/src/ImageProcessor/Filters/Contrast.cs
index 291b1c6d2..6c3336fca 100644
--- a/src/ImageProcessor/Filters/Contrast.cs
+++ b/src/ImageProcessor/Filters/Contrast.cs
@@ -30,19 +30,14 @@ namespace ImageProcessor.Filters
///
public int Value { get; }
- protected override void Apply(ImageBase source, ImageBase target, Rectangle sourceRectangle, Rectangle targetRectangle, int startY, int endY)
- {
- throw new NotImplementedException();
- }
-
///
- protected override void Apply(ImageBase target, ImageBase source, Rectangle rectangle, int startY, int endY)
+ protected override void Apply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY)
{
double contrast = (100.0 + this.Value) / 100.0;
for (int y = startY; y < endY; y++)
{
- for (int x = rectangle.X; x < rectangle.Right; x++)
+ for (int x = sourceRectangle.X; x < sourceRectangle.Right; x++)
{
Bgra color = source[x, y];
diff --git a/src/ImageProcessor/IImageProcessor.cs b/src/ImageProcessor/IImageProcessor.cs
index a9eea7dbd..696348989 100644
--- a/src/ImageProcessor/IImageProcessor.cs
+++ b/src/ImageProcessor/IImageProcessor.cs
@@ -11,12 +11,12 @@ namespace ImageProcessor
public interface IImageProcessor
{
///
- /// Apply a process to an image to alter the pixels at the area of the specified rectangle.
+ /// Applies the process to the specified portion of the specified .
///
/// Target image to apply the process to.
/// The source image. Cannot be null.
- ///
- /// The rectangle, which defines the area of the image where the process should be applied to.
+ ///
+ /// The structure that specifies the portion of the image object to draw.
///
///
/// The method keeps the source image unchanged and returns the
@@ -26,10 +26,29 @@ namespace ImageProcessor
/// is null or is null.
///
///
- /// doesnt fit the dimension of the image.
+ /// doesnt fit the dimension of the image.
///
- void Apply(ImageBase target, ImageBase source, Rectangle rectangle);
+ void Apply(ImageBase target, ImageBase source, Rectangle sourceRectangle);
+ ///
+ /// Applies the process to the specified portion of the specified at the specified
+ /// location and with the specified size.
+ ///
+ /// Target image to apply the process to.
+ /// The source image. Cannot be null.
+ /// The target width.
+ /// The target height.
+ ///
+ /// The structure that specifies the location and size of the drawn image.
+ /// The image is scaled to fit the rectangle.
+ ///
+ ///
+ /// The structure that specifies the portion of the image object to draw.
+ ///
+ ///
+ /// The method keeps the source image unchanged and returns the
+ /// the result of image process as new image.
+ ///
void Apply(ImageBase target, ImageBase source, int width, int height, Rectangle targetRectangle, Rectangle sourceRectangle);
}
}
diff --git a/src/ImageProcessor/ImageExtensions.cs b/src/ImageProcessor/ImageExtensions.cs
index 1b5196580..bfdd7ace9 100644
--- a/src/ImageProcessor/ImageExtensions.cs
+++ b/src/ImageProcessor/ImageExtensions.cs
@@ -55,22 +55,26 @@ namespace ImageProcessor
/// The image this method extends.
/// Any processors to apply to the image.
/// The .
- public static Image Process(this Image source, params IImageProcessor[] processors) => Process(source, source.Bounds, processors);
+ public static Image Process(this Image source, params IImageProcessor[] processors)
+ {
+ return Process(source, source.Bounds, processors);
+ }
///
/// Applies the collection of processors to the image.
///
/// The image this method extends.
- ///
- /// The rectangle defining the bounds of the pixels the image filter with adjust.
+ ///
+ /// The structure that specifies the portion of the image object to draw.
+ ///
/// Any processors to apply to the image.
/// The .
- public static Image Process(this Image source, Rectangle rectangle, params IImageProcessor[] processors)
+ public static Image Process(this Image source, Rectangle sourceRectangle, params IImageProcessor[] processors)
{
// ReSharper disable once LoopCanBeConvertedToQuery
foreach (IImageProcessor filter in processors)
{
- source = PerformAction(source, true, (sourceImage, targetImage) => filter.Apply(targetImage, sourceImage, rectangle));
+ source = PerformAction(source, true, (sourceImage, targetImage) => filter.Apply(targetImage, sourceImage, sourceRectangle));
}
return source;
@@ -79,13 +83,29 @@ namespace ImageProcessor
///
/// Applies the collection of processors to the image.
///
- /// The image this method extends.
- ///
- /// The rectangle defining the bounds of the pixels the image filter with adjust.
- ///
- ///
- ///
- ///
+ /// The source image. Cannot be null.
+ /// The target image width.
+ /// The target image width.
+ /// Any processors to apply to the image.
+ /// The .
+ public static Image Process(this Image source, int width, int height, params IImageProcessor[] processors)
+ {
+ return Process(source, width, height, source.Bounds, default(Rectangle), processors);
+ }
+
+ ///
+ /// Applies the collection of processors to the image.
+ ///
+ /// The source image. Cannot be null.
+ /// The target image width.
+ /// The target image width.
+ ///
+ /// The structure that specifies the portion of the image object to draw.
+ ///
+ ///
+ /// The structure that specifies the location and size of the drawn image.
+ /// The image is scaled to fit the rectangle.
+ ///
/// Any processors to apply to the image.
/// The .
public static Image Process(this Image source, int width, int height, Rectangle sourceRectangle, Rectangle targetRectangle, params IImageProcessor[] processors)
diff --git a/src/ImageProcessor/ImageProcessor.csproj b/src/ImageProcessor/ImageProcessor.csproj
index e8731d2fe..1207c97ff 100644
--- a/src/ImageProcessor/ImageProcessor.csproj
+++ b/src/ImageProcessor/ImageProcessor.csproj
@@ -180,7 +180,7 @@
-
+
@@ -196,6 +196,7 @@
+
diff --git a/src/ImageProcessor/ParallelImageProcessor.cs b/src/ImageProcessor/ParallelImageProcessor.cs
index b1533cf65..ea913776c 100644
--- a/src/ImageProcessor/ParallelImageProcessor.cs
+++ b/src/ImageProcessor/ParallelImageProcessor.cs
@@ -19,7 +19,7 @@ namespace ImageProcessor
public int Parallelism { get; set; } = Environment.ProcessorCount;
///
- public void Apply(ImageBase target, ImageBase source, Rectangle rectangle)
+ public void Apply(ImageBase target, ImageBase source, Rectangle sourceRectangle)
{
this.OnApply();
@@ -34,11 +34,11 @@ namespace ImageProcessor
int current = p;
tasks[p] = Task.Run(() =>
{
- int batchSize = rectangle.Height / partitionCount;
- int yStart = rectangle.Y + (current * batchSize);
- int yEnd = current == partitionCount - 1 ? rectangle.Bottom : yStart + batchSize;
+ int batchSize = sourceRectangle.Height / partitionCount;
+ int yStart = sourceRectangle.Y + (current * batchSize);
+ int yEnd = current == partitionCount - 1 ? sourceRectangle.Bottom : yStart + batchSize;
- this.Apply(target, source, rectangle, yStart, yEnd);
+ this.Apply(target, source, target.Bounds, sourceRectangle, yStart, yEnd);
});
}
@@ -46,7 +46,7 @@ namespace ImageProcessor
}
else
{
- this.Apply(target, source, rectangle, rectangle.Y, rectangle.Bottom);
+ this.Apply(target, source, target.Bounds, sourceRectangle, sourceRectangle.Y, sourceRectangle.Bottom);
}
}
@@ -102,22 +102,25 @@ namespace ImageProcessor
{
}
- protected abstract void Apply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY);
-
///
- /// Apply a process to an image to alter the pixels at the area of the specified rectangle.
+ /// Applies the process to the specified portion of the specified at the specified location
+ /// and with the specified size.
///
/// Target image to apply the process to.
/// The source image. Cannot be null.
- ///
- /// The rectangle, which defines the area of the image where the process should be applied to.
+ ///
+ /// The structure that specifies the location and size of the drawn image.
+ /// The image is scaled to fit the rectangle.
///
- /// The index of the row within the image to start processing.
- /// The index of the row within the image to end processing.
+ ///
+ /// The structure that specifies the portion of the image object to draw.
+ ///
+ /// The index of the row within the source image to start processing.
+ /// The index of the row within the source image to end processing.
///
/// The method keeps the source image unchanged and returns the
- /// the result of image processing filter as new image.
+ /// the result of image process as new image.
///
- protected abstract void Apply(ImageBase target, ImageBase source, Rectangle rectangle, int startY, int endY);
+ protected abstract void Apply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY);
}
}
diff --git a/src/ImageProcessor/Samplers/Lanczos3Resampler.cs b/src/ImageProcessor/Samplers/Lanczos5Resampler.cs
similarity index 90%
rename from src/ImageProcessor/Samplers/Lanczos3Resampler.cs
rename to src/ImageProcessor/Samplers/Lanczos5Resampler.cs
index 9593c1aea..1d7008d58 100644
--- a/src/ImageProcessor/Samplers/Lanczos3Resampler.cs
+++ b/src/ImageProcessor/Samplers/Lanczos5Resampler.cs
@@ -9,10 +9,10 @@ namespace ImageProcessor.Samplers
/// The function implements the Lanczos kernel algorithm as described on
/// Wikipedia
///
- public class Lanczos3Resampler : IResampler
+ public class Lanczos5Resampler : IResampler
{
///
- public double Radius => 3;
+ public double Radius => 5;
///
public double GetValue(double x)
diff --git a/src/ImageProcessor/Samplers/Resize.cs b/src/ImageProcessor/Samplers/Resize.cs
index 26dc44d7d..3dc3b166f 100644
--- a/src/ImageProcessor/Samplers/Resize.cs
+++ b/src/ImageProcessor/Samplers/Resize.cs
@@ -1,7 +1,15 @@
-using System;
+//
+// Copyright © James South and contributors.
+// Licensed under the Apache License, Version 2.0.
+//
namespace ImageProcessor.Samplers
{
+ using System;
+
+ ///
+ /// Provides methods that allow the resizing of images using various resampling algorithms.
+ ///
public class Resize : ParallelImageProcessor
{
///
@@ -23,13 +31,7 @@ namespace ImageProcessor.Samplers
public IResampler Sampler { get; }
///
- protected override void Apply(
- ImageBase target,
- ImageBase source,
- Rectangle targetRectangle,
- Rectangle sourceRectangle,
- int startY,
- int endY)
+ protected override void Apply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY)
{
int sourceWidth = source.Width;
int sourceHeight = source.Height;
@@ -126,11 +128,5 @@ namespace ImageProcessor.Samplers
}
}
}
-
- ///
- protected override void Apply(ImageBase target, ImageBase source, Rectangle rectangle, int startY, int endY)
- {
- throw new NotImplementedException();
- }
}
}
diff --git a/tests/ImageProcessor.Tests/Formats/EncoderDecoderTests.cs b/tests/ImageProcessor.Tests/Formats/EncoderDecoderTests.cs
deleted file mode 100644
index 74c8ab304..000000000
--- a/tests/ImageProcessor.Tests/Formats/EncoderDecoderTests.cs
+++ /dev/null
@@ -1,63 +0,0 @@
-namespace ImageProcessor.Tests
-{
- using System.Diagnostics;
- using System.IO;
-
- using Formats;
-
- using Xunit;
-
- public class EncoderDecoderTests
- {
- [Theory]
- [InlineData("../../TestImages/Formats/Jpg/Backdrop.jpg")]
- [InlineData("../../TestImages/Formats/Gif/a.gif")]
- [InlineData("../../TestImages/Formats/Gif/leaf.gif")]
- [InlineData("../../TestImages/Formats/Gif/ani.gif")]
- [InlineData("../../TestImages/Formats/Gif/ani2.gif")]
- [InlineData("../../TestImages/Formats/Gif/giphy.gif")]
- [InlineData("../../TestImages/Formats/Bmp/Car.bmp")]
- [InlineData("../../TestImages/Formats/Png/cmyk.png")]
- public void DecodeThenEncodeImageFromStreamShouldSucceed(string filename)
- {
- if (!Directory.Exists("Encoded"))
- {
- Directory.CreateDirectory("Encoded");
- }
-
- FileStream stream = File.OpenRead(filename);
- Stopwatch watch = Stopwatch.StartNew();
- Image image = new Image(stream);
-
- string encodedFilename = "Encoded/" + Path.GetFileName(filename);
-
- using (FileStream output = File.OpenWrite(encodedFilename))
- {
- image.Save(output);
- }
-
- Trace.WriteLine($"{filename} : {watch.ElapsedMilliseconds}ms");
- }
-
- [Theory]
- [InlineData("../../TestImages/Formats/Jpg/Backdrop.jpg")]
- [InlineData("../../TestImages/Formats/Bmp/Car.bmp")]
- [InlineData("../../TestImages/Formats/Png/cmyk.png")]
- public void QuantizedImageShouldPreserveMaximumColorPrecision(string filename)
- {
- if (!Directory.Exists("Quantized"))
- {
- Directory.CreateDirectory("Quantized");
- }
-
- Image image = new Image(File.OpenRead(filename));
- IQuantizer quantizer = new OctreeQuantizer();
- QuantizedImage quantizedImage = quantizer.Quantize(image);
-
- using (FileStream output = File.OpenWrite($"Quantized/{ Path.GetFileName(filename) }"))
- {
- quantizedImage.ToImage().Save(output);
- }
- }
- }
-}
\ No newline at end of file
diff --git a/tests/ImageProcessor.Tests/ImageProcessor.Tests.csproj b/tests/ImageProcessor.Tests/ImageProcessor.Tests.csproj
index 477b1b909..fd13cac0e 100644
--- a/tests/ImageProcessor.Tests/ImageProcessor.Tests.csproj
+++ b/tests/ImageProcessor.Tests/ImageProcessor.Tests.csproj
@@ -53,14 +53,15 @@
-
-
+
+
+
-
+
diff --git a/tests/ImageProcessor.Tests/ImageProcessor.Tests.csproj.DotSettings b/tests/ImageProcessor.Tests/ImageProcessor.Tests.csproj.DotSettings
index 0b25413f0..cb4957f1e 100644
--- a/tests/ImageProcessor.Tests/ImageProcessor.Tests.csproj.DotSettings
+++ b/tests/ImageProcessor.Tests/ImageProcessor.Tests.csproj.DotSettings
@@ -1,4 +1,9 @@
True
True
- True
\ No newline at end of file
+ True
+ True
+ True
+ True
+ True
+ True
\ No newline at end of file
diff --git a/tests/ImageProcessor.Tests/Filters/FilterTests.cs b/tests/ImageProcessor.Tests/Processors/Filters/FilterTests.cs
similarity index 78%
rename from tests/ImageProcessor.Tests/Filters/FilterTests.cs
rename to tests/ImageProcessor.Tests/Processors/Filters/FilterTests.cs
index 9eed6a977..dac009328 100644
--- a/tests/ImageProcessor.Tests/Filters/FilterTests.cs
+++ b/tests/ImageProcessor.Tests/Processors/Filters/FilterTests.cs
@@ -1,5 +1,5 @@
-namespace ImageProcessor.Tests.Filters
+namespace ImageProcessor.Tests
{
using System.Collections.Generic;
using System.Diagnostics;
@@ -10,20 +10,8 @@ namespace ImageProcessor.Tests.Filters
using Xunit;
- public class FilterTests
+ public class FilterTests : ProcessorTestBase
{
- public static readonly List Files = new List
- {
- //{ "../../TestImages/Formats/Jpg/Backdrop.jpg"},
- //{ "../../TestImages/Formats/Bmp/Car.bmp" },
- //{ "../../TestImages/Formats/Png/cmyk.png" },
- //{ "../../TestImages/Formats/Gif/a.gif" },
- //{ "../../TestImages/Formats/Gif/leaf.gif" },
- { "../../TestImages/Formats/Gif/ani.gif" },
- //{ "../../TestImages/Formats/Gif/ani2.gif" },
- //{ "../../TestImages/Formats/Gif/giphy.gif" },
- };
-
public static readonly TheoryData Filters = new TheoryData
{
{ "Contrast-50", new Contrast(50) },
diff --git a/tests/ImageProcessor.Tests/Processors/Formats/EncoderDecoderTests.cs b/tests/ImageProcessor.Tests/Processors/Formats/EncoderDecoderTests.cs
new file mode 100644
index 000000000..a1af332e8
--- /dev/null
+++ b/tests/ImageProcessor.Tests/Processors/Formats/EncoderDecoderTests.cs
@@ -0,0 +1,63 @@
+namespace ImageProcessor.Tests
+{
+ using System.Diagnostics;
+ using System.IO;
+
+ using Formats;
+
+ using Xunit;
+
+ public class EncoderDecoderTests : ProcessorTestBase
+ {
+ [Fact]
+ public void DecodeThenEncodeImageFromStreamShouldSucceed()
+ {
+ if (!Directory.Exists("Encoded"))
+ {
+ Directory.CreateDirectory("Encoded");
+ }
+
+ foreach (string file in Files)
+ {
+ using (FileStream stream = File.OpenRead(file))
+ {
+ Stopwatch watch = Stopwatch.StartNew();
+ Image image = new Image(stream);
+
+ string encodedFilename = "Encoded/" + Path.GetFileName(file);
+
+ using (FileStream output = File.OpenWrite(encodedFilename))
+ {
+ image.Save(output);
+ }
+
+ Trace.WriteLine($"{file} : {watch.ElapsedMilliseconds}ms");
+ }
+ }
+ }
+
+ [Fact]
+ public void QuantizedImageShouldPreserveMaximumColorPrecision()
+ {
+ if (!Directory.Exists("Quantized"))
+ {
+ Directory.CreateDirectory("Quantized");
+ }
+
+ foreach (string file in Files)
+ {
+ using (FileStream stream = File.OpenRead(file))
+ {
+ Image image = new Image(stream);
+ IQuantizer quantizer = new OctreeQuantizer();
+ QuantizedImage quantizedImage = quantizer.Quantize(image);
+
+ using (FileStream output = File.OpenWrite($"Quantized/{Path.GetFileName(file)}"))
+ {
+ quantizedImage.ToImage().Save(output);
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/tests/ImageProcessor.Tests/Processors/ProcessorTestBase.cs b/tests/ImageProcessor.Tests/Processors/ProcessorTestBase.cs
new file mode 100644
index 000000000..d8399d73f
--- /dev/null
+++ b/tests/ImageProcessor.Tests/Processors/ProcessorTestBase.cs
@@ -0,0 +1,32 @@
+// --------------------------------------------------------------------------------------------------------------------
+//
+// Copyright © James South and contributors.
+// Licensed under the Apache License, Version 2.0.
+//
+// --------------------------------------------------------------------------------------------------------------------
+
+namespace ImageProcessor.Tests
+{
+ using System.Collections.Generic;
+
+ ///
+ /// The processor test base.
+ ///
+ public abstract class ProcessorTestBase
+ {
+ ///
+ /// The collection of image files to test against.
+ ///
+ public static readonly List Files = new List
+ {
+ "../../TestImages/Formats/Jpg/Backdrop.jpg",
+ "../../TestImages/Formats/Bmp/Car.bmp",
+ "../../TestImages/Formats/Png/cmyk.png",
+ "../../TestImages/Formats/Gif/leaf.gif"
+
+ // { "../../TestImages/Formats/Gif/ani.gif" },
+ // { "../../TestImages/Formats/Gif/ani2.gif" },
+ // { "../../TestImages/Formats/Gif/giphy.gif" },
+ };
+ }
+}
diff --git a/tests/ImageProcessor.Tests/Samplers/SamplerTests.cs b/tests/ImageProcessor.Tests/Processors/Samplers/SamplerTests.cs
similarity index 61%
rename from tests/ImageProcessor.Tests/Samplers/SamplerTests.cs
rename to tests/ImageProcessor.Tests/Processors/Samplers/SamplerTests.cs
index a9449fd9f..ab4511ad3 100644
--- a/tests/ImageProcessor.Tests/Samplers/SamplerTests.cs
+++ b/tests/ImageProcessor.Tests/Processors/Samplers/SamplerTests.cs
@@ -1,38 +1,25 @@
-namespace ImageProcessor.Tests.Filters
+namespace ImageProcessor.Tests
{
- using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
- using Samplers;
+ using ImageProcessor.Samplers;
using Xunit;
- public class SamplerTests
+ public class SamplerTests : ProcessorTestBase
{
- public static readonly List Files = new List
- {
- { "../../TestImages/Formats/Jpg/Backdrop.jpg" },
- { "../../TestImages/Formats/Bmp/Car.bmp" },
- { "../../TestImages/Formats/Png/cmyk.png" },
- //{ "../../TestImages/Formats/Gif/a.gif" },
- { "../../TestImages/Formats/Gif/leaf.gif" },
- //{ "../../TestImages/Formats/Gif/ani.gif" },
- //{ "../../TestImages/Formats/Gif/ani2.gif" },
- //{ "../../TestImages/Formats/Gif/giphy.gif" },
- };
-
public static readonly TheoryData Samplers =
new TheoryData
{
{ "Bicubic", new BicubicResampler() },
- { "Lanczos3", new Lanczos3Resampler() }
+ //{ "Lanczos3", new Lanczos5Resampler() }
};
[Theory]
[MemberData("Samplers")]
- public void ResizeImage(string name, IResampler sampler)
+ public void ImageShouldResize(string name, IResampler sampler)
{
if (!Directory.Exists("Resized"))
{
@@ -48,7 +35,7 @@ namespace ImageProcessor.Tests.Filters
string filename = Path.GetFileNameWithoutExtension(file) + "-" + name + Path.GetExtension(file);
using (FileStream output = File.OpenWrite($"Resized/{filename}"))
{
- image.Resize(900, 900, sampler).Save(output);
+ image.Resize(500, 500, sampler).Save(output);
}
Trace.WriteLine($"{name}: {watch.ElapsedMilliseconds}ms");
@@ -65,7 +52,7 @@ namespace ImageProcessor.Tests.Filters
[InlineData(2, 0)]
public static void Lanczos3WindowOscillatesCorrectly(double x, double expected)
{
- Lanczos3Resampler sampler = new Lanczos3Resampler();
+ Lanczos5Resampler sampler = new Lanczos5Resampler();
double result = sampler.GetValue(x);
Assert.Equal(result, expected);
diff --git a/tests/ImageProcessor.Tests/TestImages/Formats/Gif/a.gif b/tests/ImageProcessor.Tests/TestImages/Formats/Gif/a.gif
deleted file mode 100644
index d89e799a6..000000000
Binary files a/tests/ImageProcessor.Tests/TestImages/Formats/Gif/a.gif and /dev/null differ