diff --git a/README.md b/README.md
index 4eeefd54b1..5016825043 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
-**ImageProcessorCore** is a new cross-platform 2D graphics API to allow the processing of images without the use of `System.Drawing`. It's still in early stages but progress has been pretty quick.
+**ImageProcessorCore** is a new cross-platform 2D graphics API designed to allow the processing of images without the use of `System.Drawing`. It's still in early stages but progress has been pretty quick.
[](https://ci.appveyor.com/project/JamesSouth/imageprocessor/branch/Core)
[](https://gitter.im/JimBobSquarePants/ImageProcessor?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
@@ -182,8 +182,11 @@ using (Image image = new Image(stream))
new Sobel { Greyscale = true }
};
- image.Process(processors.ToArray())
- .Save(output);
+ foreach (IImageProcessor processor in processors){
+
+ image.Process(processor)
+ .Save(output);
+ }
}
```
Individual processors can be initialised and apply processing against images. This allows nesting which will allow the powerful combination of processing methods:
diff --git a/src/ImageProcessorCore/Colors/Color.cs b/src/ImageProcessorCore/Colors/Color.cs
index b86a2dfa05..0e47e03e1b 100644
--- a/src/ImageProcessorCore/Colors/Color.cs
+++ b/src/ImageProcessorCore/Colors/Color.cs
@@ -8,6 +8,7 @@ namespace ImageProcessorCore
using System;
using System.ComponentModel;
using System.Numerics;
+ using System.Runtime.CompilerServices;
///
/// Represents a four-component color using red, green, blue, and alpha data.
@@ -316,6 +317,7 @@ namespace ImageProcessorCore
///
/// The
///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Color Average(Color first, Color second)
{
return new Color((first.backingVector + second.backingVector) * .5f);
@@ -361,6 +363,7 @@ namespace ImageProcessorCore
///
/// The to convert.
/// The .
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Color FromNonPremultiplied(Color color)
{
return new Color(FromNonPremultiplied(color.backingVector, color.A));
@@ -383,6 +386,7 @@ namespace ImageProcessorCore
///
/// The to convert.
/// The .
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Color ToNonPremultiplied(Color color)
{
float a = color.A;
@@ -398,6 +402,7 @@ namespace ImageProcessorCore
/// Gets a representation for this .
///
/// A representation for this object.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public Vector4 ToVector4()
{
return new Vector4(this.R, this.G, this.B, this.A);
@@ -430,6 +435,7 @@ namespace ImageProcessorCore
}
///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public override bool Equals(object obj)
{
if (obj is Color)
@@ -447,6 +453,7 @@ namespace ImageProcessorCore
}
///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool AlmostEquals(Color other, float precision)
{
Vector4 result = Vector4.Abs(this.backingVector - other.backingVector);
@@ -466,6 +473,7 @@ namespace ImageProcessorCore
///
/// The .
///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
private static float Compress(float signal)
{
if (signal <= 0.0031308f)
@@ -485,6 +493,7 @@ namespace ImageProcessorCore
///
/// The .
///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
private static float Expand(float signal)
{
if (signal <= 0.04045f)
diff --git a/src/ImageProcessorCore/ImageExtensions.cs b/src/ImageProcessorCore/ImageExtensions.cs
index 0e9603b515..597c681df2 100644
--- a/src/ImageProcessorCore/ImageExtensions.cs
+++ b/src/ImageProcessorCore/ImageExtensions.cs
@@ -56,11 +56,11 @@ namespace ImageProcessorCore
/// This method does not resize the target image.
///
/// The image this method extends.
- /// Any processors to apply to the image.
+ /// The processor to apply to the image.
/// The .
- public static Image Process(this Image source, params IImageProcessor[] processors)
+ public static Image Process(this Image source, IImageProcessor processor)
{
- return Process(source, source.Bounds, processors);
+ return Process(source, source.Bounds, processor);
}
///
@@ -71,15 +71,11 @@ namespace ImageProcessorCore
///
/// The structure that specifies the portion of the image object to draw.
///
- /// Any processors to apply to the image.
+ /// The processors to apply to the image.
/// The .
- public static Image Process(this Image source, Rectangle sourceRectangle, params IImageProcessor[] processors)
+ public static Image Process(this Image source, Rectangle sourceRectangle, IImageProcessor processor)
{
- // ReSharper disable once LoopCanBeConvertedToQuery
- foreach (IImageProcessor filter in processors)
- {
- source = PerformAction(source, true, (sourceImage, targetImage) => filter.Apply(targetImage, sourceImage, sourceRectangle));
- }
+ source = PerformAction(source, true, (sourceImage, targetImage) => processor.Apply(targetImage, sourceImage, sourceRectangle));
return source;
}
@@ -93,11 +89,11 @@ namespace ImageProcessorCore
/// The source image. Cannot be null.
/// The target image width.
/// The target image height.
- /// Any processors to apply to the image.
+ /// The processor to apply to the image.
/// The .
- public static Image Process(this Image source, int width, int height, params IImageSampler[] processors)
+ internal static Image Process(this Image source, int width, int height, IImageSampler sampler)
{
- return Process(source, width, height, source.Bounds, default(Rectangle), processors);
+ return Process(source, width, height, source.Bounds, default(Rectangle), sampler);
}
///
@@ -117,15 +113,11 @@ namespace ImageProcessorCore
/// 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 processor to apply to the image.
/// The .
- public static Image Process(this Image source, int width, int height, Rectangle sourceRectangle, Rectangle targetRectangle, params IImageSampler[] processors)
+ public static Image Process(this Image source, int width, int height, Rectangle sourceRectangle, Rectangle targetRectangle, IImageSampler sampler)
{
- // ReSharper disable once LoopCanBeConvertedToQuery
- foreach (IImageSampler sampler in processors)
- {
- source = PerformAction(source, false, (sourceImage, targetImage) => sampler.Apply(targetImage, sourceImage, width, height, targetRectangle, sourceRectangle));
- }
+ source = PerformAction(source, false, (sourceImage, targetImage) => sampler.Apply(targetImage, sourceImage, width, height, targetRectangle, sourceRectangle));
return source;
}
diff --git a/src/ImageProcessorCore/Samplers/Crop.cs b/src/ImageProcessorCore/Samplers/Crop.cs
index 3c315c574d..3ee47149bb 100644
--- a/src/ImageProcessorCore/Samplers/Crop.cs
+++ b/src/ImageProcessorCore/Samplers/Crop.cs
@@ -19,6 +19,8 @@ namespace ImageProcessorCore.Samplers
int targetBottom = targetRectangle.Bottom;
int startX = targetRectangle.X;
int endX = targetRectangle.Right;
+ int sourceX = sourceRectangle.X;
+ int sourceY = sourceRectangle.Y;
Parallel.For(
startY,
@@ -29,7 +31,7 @@ namespace ImageProcessorCore.Samplers
{
for (int x = startX; x < endX; x++)
{
- target[x, y] = source[x + sourceRectangle.X, y + sourceRectangle.Y];
+ target[x, y] = source[x + sourceX, y + sourceY];
}
this.OnRowProcessed();
diff --git a/tests/ImageProcessorCore.Benchmarks/Color/ColorEquality.cs b/tests/ImageProcessorCore.Benchmarks/Color/ColorEquality.cs
new file mode 100644
index 0000000000..e9ef2c1835
--- /dev/null
+++ b/tests/ImageProcessorCore.Benchmarks/Color/ColorEquality.cs
@@ -0,0 +1,22 @@
+namespace ImageProcessorCore.Benchmarks
+{
+ using BenchmarkDotNet.Attributes;
+
+ using CoreColor = ImageProcessorCore.Color;
+ using SystemColor = System.Drawing.Color;
+
+ public class ColorEquality
+ {
+ [Benchmark(Baseline = true, Description = "System.Drawing Color Equals")]
+ public bool SystemDrawingColorEqual()
+ {
+ return SystemColor.FromArgb(128, 128, 128, 128).Equals(SystemColor.FromArgb(128, 128, 128, 128));
+ }
+
+ [Benchmark(Description = "ImageProcessorCore Color Equals")]
+ public bool ColorEqual()
+ {
+ return new CoreColor(.5f, .5f, .5f, .5f).Equals(new CoreColor(.5f, .5f, .5f, .5f));
+ }
+ }
+}
diff --git a/tests/ImageProcessorCore.Benchmarks/Colors.cs b/tests/ImageProcessorCore.Benchmarks/Colors.cs
deleted file mode 100644
index 0a7d54c994..0000000000
--- a/tests/ImageProcessorCore.Benchmarks/Colors.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-using BenchmarkDotNet.Attributes;
-
-namespace ImageProcessorCore.Benchmarks
-{
- using System.Drawing;
-
- using CoreColor = ImageProcessorCore.Color;
-
- public class Colors
- {
- [Benchmark(Baseline = true, Description = "System.Drawing Color")]
- public bool SystemDrawingColorEqual()
- {
- return Color.FromArgb(128, 128, 128, 128).Equals(Color.FromArgb(128, 128, 128, 128));
- }
-
- [Benchmark(Description = "ImageProcessorCore Color")]
- public bool ColorEqual()
- {
- return new CoreColor(.5f, .5f, .5f, .5f).Equals(new CoreColor(.5f, .5f, .5f, .5f));
- }
- }
-}
diff --git a/tests/ImageProcessorCore.Benchmarks/Image/GetSetPixel.cs b/tests/ImageProcessorCore.Benchmarks/Image/GetSetPixel.cs
new file mode 100644
index 0000000000..fce14beb7f
--- /dev/null
+++ b/tests/ImageProcessorCore.Benchmarks/Image/GetSetPixel.cs
@@ -0,0 +1,33 @@
+namespace ImageProcessorCore.Benchmarks.Image
+{
+ using System.Drawing;
+
+ using BenchmarkDotNet.Attributes;
+
+ using CoreColor = ImageProcessorCore.Color;
+ using CoreImage = ImageProcessorCore.Image;
+ using SystemColor = System.Drawing.Color;
+
+ public class GetSetPixel
+ {
+ [Benchmark(Baseline = true, Description = "System.Drawing GetSet Pixel")]
+ public SystemColor ResizeSystemDrawing()
+ {
+ using (Bitmap source = new Bitmap(400, 400))
+ {
+ source.SetPixel(200, 200, SystemColor.White);
+ return source.GetPixel(200, 200);
+ }
+ }
+
+ [Benchmark(Description = "ImageProcessorCore GetSet Pixel")]
+ public CoreColor ResizeCore()
+ {
+ using (CoreImage image = new CoreImage(400, 400))
+ {
+ image[200, 200] = CoreColor.White;
+ return image[200, 200];
+ }
+ }
+ }
+}
diff --git a/tests/ImageProcessorCore.Benchmarks/Samplers/Crop.cs b/tests/ImageProcessorCore.Benchmarks/Samplers/Crop.cs
new file mode 100644
index 0000000000..85bc4190a2
--- /dev/null
+++ b/tests/ImageProcessorCore.Benchmarks/Samplers/Crop.cs
@@ -0,0 +1,44 @@
+namespace ImageProcessorCore.Benchmarks
+{
+ using System.Drawing;
+ using System.Drawing.Drawing2D;
+
+ using BenchmarkDotNet.Attributes;
+
+ using ImageProcessorCore.Samplers;
+ using CoreImage = ImageProcessorCore.Image;
+ using CoreSize = ImageProcessorCore.Size;
+
+ public class Crop
+ {
+ [Benchmark(Baseline = true, Description = "System.Drawing Crop")]
+ public Size CropSystemDrawing()
+ {
+ using (Bitmap source = new Bitmap(400, 400))
+ {
+ using (Bitmap destination = new Bitmap(100, 100))
+ {
+ using (Graphics graphics = Graphics.FromImage(destination))
+ {
+ graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
+ graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
+ graphics.CompositingQuality = CompositingQuality.HighQuality;
+ graphics.DrawImage(source, new Rectangle(0, 0, 100, 100), 0, 0, 100, 100, GraphicsUnit.Pixel);
+ }
+
+ return destination.Size;
+ }
+ }
+ }
+
+ [Benchmark(Description = "ImageProcessorCore Crop")]
+ public CoreSize CropResizeCore()
+ {
+ using (CoreImage image = new CoreImage(400, 400))
+ {
+ image.Crop(100, 100);
+ return new CoreSize(image.Width, image.Height);
+ }
+ }
+ }
+}
diff --git a/tests/ImageProcessorCore.Benchmarks/Resize.cs b/tests/ImageProcessorCore.Benchmarks/Samplers/Resize.cs
similarity index 100%
rename from tests/ImageProcessorCore.Benchmarks/Resize.cs
rename to tests/ImageProcessorCore.Benchmarks/Samplers/Resize.cs