Browse Source

pass configuation into processors

af/merge-core
Scott Williams 9 years ago
parent
commit
b289ce752a
  1. 4
      src/ImageSharp.Drawing/Processors/DrawImageProcessor.cs
  2. 4
      src/ImageSharp.Drawing/Processors/FillProcessor.cs
  3. 2
      src/ImageSharp.Drawing/Processors/FillRegionProcessor.cs
  4. 22
      src/ImageSharp/Advanced/IConfigurable.cs
  5. 10
      src/ImageSharp/Advanced/ImageExtensions.cs
  6. 7
      src/ImageSharp/Image/ImageFrame{TPixel}.cs
  7. 17
      src/ImageSharp/Image/Image{TPixel}.cs
  8. 8
      src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor.cs
  9. 6
      src/ImageSharp/Processing/Processors/Binarization/ErrorDiffusionDitherProcessor.cs
  10. 6
      src/ImageSharp/Processing/Processors/Binarization/OrderedDitherProcessor.cs
  11. 33
      src/ImageSharp/Processing/Processors/CloningImageProcessor.cs
  12. 4
      src/ImageSharp/Processing/Processors/ColorMatrix/ColorMatrixProcessor.cs
  13. 4
      src/ImageSharp/Processing/Processors/ColorMatrix/LomographProcessor.cs
  14. 6
      src/ImageSharp/Processing/Processors/ColorMatrix/PolaroidProcessor.cs
  15. 4
      src/ImageSharp/Processing/Processors/Convolution/BoxBlurProcessor.cs
  16. 4
      src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor.cs
  17. 4
      src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor.cs
  18. 4
      src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor.cs
  19. 8
      src/ImageSharp/Processing/Processors/Convolution/EdgeDetection/EdgeDetector2DProcessor.cs
  20. 12
      src/ImageSharp/Processing/Processors/Convolution/EdgeDetection/EdgeDetectorCompassProcessor.cs
  21. 8
      src/ImageSharp/Processing/Processors/Convolution/EdgeDetection/EdgeDetectorProcessor.cs
  22. 4
      src/ImageSharp/Processing/Processors/Convolution/GaussianBlurProcessor.cs
  23. 4
      src/ImageSharp/Processing/Processors/Convolution/GaussianSharpenProcessor.cs
  24. 2
      src/ImageSharp/Processing/Processors/DelegateProcessor.cs
  25. 4
      src/ImageSharp/Processing/Processors/Effects/AlphaProcessor.cs
  26. 4
      src/ImageSharp/Processing/Processors/Effects/BackgroundColorProcessor.cs
  27. 4
      src/ImageSharp/Processing/Processors/Effects/BrightnessProcessor.cs
  28. 4
      src/ImageSharp/Processing/Processors/Effects/ContrastProcessor.cs
  29. 4
      src/ImageSharp/Processing/Processors/Effects/InvertProcessor.cs
  30. 4
      src/ImageSharp/Processing/Processors/Effects/OilPaintingProcessor.cs
  31. 4
      src/ImageSharp/Processing/Processors/Effects/PixelateProcessor.cs
  32. 47
      src/ImageSharp/Processing/Processors/ImageProcessor.cs
  33. 4
      src/ImageSharp/Processing/Processors/Overlays/GlowProcessor.cs
  34. 4
      src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor.cs
  35. 2
      src/ImageSharp/Processing/Processors/Transforms/AutoOrientProcessor.cs
  36. 4
      src/ImageSharp/Processing/Processors/Transforms/CropProcessor.cs
  37. 8
      src/ImageSharp/Processing/Processors/Transforms/EntropyCropProcessor.cs
  38. 16
      src/ImageSharp/Processing/Processors/Transforms/FlipProcessor.cs
  39. 6
      src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.cs
  40. 8
      src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs
  41. 36
      src/ImageSharp/Processing/Processors/Transforms/RotateProcessor.cs
  42. 6
      src/ImageSharp/Processing/Processors/Transforms/SkewProcessor.cs
  43. 4
      tests/ImageSharp.Benchmarks/Samplers/Glow.cs
  44. 4
      tests/ImageSharp.Tests/TestUtilities/ImageComparison/ExactImageComparer.cs
  45. 16
      tests/ImageSharp.Tests/TestUtilities/ImageComparison/ImageComparer.cs
  46. 38
      tests/ImageSharp.Tests/TestUtilities/ImageComparison/ImageSimilarityReport.cs
  47. 6
      tests/ImageSharp.Tests/TestUtilities/ImageComparison/TolerantImageComparer.cs

4
src/ImageSharp.Drawing/Processors/DrawImageProcessor.cs

@ -60,7 +60,7 @@ namespace SixLabors.ImageSharp.Drawing.Processors
public Point Location { get; }
/// <inheritdoc/>
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle)
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)
{
Image<TPixel> disposableImage = null;
Image<TPixel> targetImage = this.Image;
@ -96,7 +96,7 @@ namespace SixLabors.ImageSharp.Drawing.Processors
Parallel.For(
minY,
maxY,
source.Configuration().ParallelOptions,
configuration.ParallelOptions,
y =>
{
Span<TPixel> background = sourcePixels.GetRowSpan(y).Slice(minX, width);

4
src/ImageSharp.Drawing/Processors/FillProcessor.cs

@ -40,7 +40,7 @@ namespace SixLabors.ImageSharp.Drawing.Processors
}
/// <inheritdoc/>
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle)
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)
{
int startX = sourceRectangle.X;
int endX = sourceRectangle.Right;
@ -77,7 +77,7 @@ namespace SixLabors.ImageSharp.Drawing.Processors
Parallel.For(
minY,
maxY,
source.Configuration().ParallelOptions,
configuration.ParallelOptions,
y =>
{
int offsetY = y - startY;

2
src/ImageSharp.Drawing/Processors/FillRegionProcessor.cs

@ -57,7 +57,7 @@ namespace SixLabors.ImageSharp.Drawing.Processors
public GraphicsOptions Options { get; }
/// <inheritdoc/>
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle)
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)
{
Region region = this.Region;
Rectangle rect = region.Bounds;

22
src/ImageSharp/Advanced/IConfigurable.cs

@ -0,0 +1,22 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.MetaData;
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Advanced
{
/// <summary>
/// Encapsulates the properties for configuration
/// </summary>
internal interface IConfigurable
{
/// <summary>
/// Gets the pixel buffer.
/// </summary>
Configuration Configuration { get; }
}
}

10
src/ImageSharp/Advanced/ImageExtensions.cs

@ -80,18 +80,16 @@ namespace SixLabors.ImageSharp.Advanced
/// <typeparam name="TPixel">The Pixel format.</typeparam>
/// <param name="source">The source image</param>
/// <returns>Returns the bounds of the image</returns>
public static Configuration Configuration<TPixel>(this ImageFrame<TPixel> source)
public static Configuration Configuration<TPixel>(this Image<TPixel> source)
where TPixel : struct, IPixel<TPixel>
=> source?.Parent?.ImageConfiguration ?? SixLabors.ImageSharp.Configuration.Default;
=> GetConfiguration(source);
/// <summary>
/// Gets the bounds of the image.
/// </summary>
/// <typeparam name="TPixel">The Pixel format.</typeparam>
/// <param name="source">The source image</param>
/// <returns>Returns the bounds of the image</returns>
public static Configuration Configuration<TPixel>(this Image<TPixel> source)
where TPixel : struct, IPixel<TPixel>
=> source?.ImageConfiguration ?? SixLabors.ImageSharp.Configuration.Default;
private static Configuration GetConfiguration(IConfigurable source)
=> source?.Configuration ?? SixLabors.ImageSharp.Configuration.Default;
}
}

7
src/ImageSharp/Image/ImageFrame{TPixel}.cs

@ -73,11 +73,6 @@ namespace SixLabors.ImageSharp
/// <inheritdoc/>
public int Height => this.pixelBuffer.Height;
/// <summary>
/// Gets the configuration providing initialization code which allows extending the library.
/// </summary>
public Image<TPixel> Parent { get; private set; }
/// <summary>
/// Gets the meta data of the frame.
/// </summary>
@ -222,7 +217,7 @@ namespace SixLabors.ImageSharp
Parallel.For(
0,
target.Height,
this.Configuration().ParallelOptions,
Configuration.Default.ParallelOptions,
y =>
{
for (int x = 0; x < target.Width; x++)

17
src/ImageSharp/Image/Image{TPixel}.cs

@ -17,9 +17,11 @@ namespace SixLabors.ImageSharp
/// Encapsulates an image, which consists of the pixel data for a graphics image and its attributes.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
public sealed partial class Image<TPixel> : IDisposable
public sealed partial class Image<TPixel> : IDisposable, IConfigurable
where TPixel : struct, IPixel<TPixel>
{
private Configuration configuration;
/// <summary>
/// Initializes a new instance of the <see cref="Image{TPixel}"/> class
/// with the height and the width of the image.
@ -71,7 +73,7 @@ namespace SixLabors.ImageSharp
/// <param name="frames">The frames that will be owned by this image instance.</param>
internal Image(Configuration configuration, int width, int height, ImageMetaData metadata, IEnumerable<ImageFrame<TPixel>> frames)
{
this.ImageConfiguration = configuration ?? Configuration.Default;
this.configuration = configuration ?? Configuration.Default;
this.MetaData = metadata ?? new ImageMetaData();
this.Frames = new ImageFrameCollection<TPixel>();
@ -91,12 +93,9 @@ namespace SixLabors.ImageSharp
}
/// <summary>
/// Gets the configuration.
/// Gets the pixel buffer.
/// </summary>
/// <value>
/// The configuration.
/// </value>
internal Configuration ImageConfiguration { get; }
Configuration IConfigurable.Configuration => this.configuration;
/// <summary>
/// Gets the width.
@ -158,7 +157,7 @@ namespace SixLabors.ImageSharp
{
IEnumerable<ImageFrame<TPixel>> frames = this.Frames.Select(x => x.Clone()).ToArray();
return new Image<TPixel>(this.ImageConfiguration, this.Width, this.Height, this.MetaData.Clone(), frames);
return new Image<TPixel>(this.configuration, this.Width, this.Height, this.MetaData.Clone(), frames);
}
/// <inheritdoc/>
@ -176,7 +175,7 @@ namespace SixLabors.ImageSharp
where TPixel2 : struct, IPixel<TPixel2>
{
IEnumerable<ImageFrame<TPixel2>> frames = this.Frames.Select(x => x.CloneAs<TPixel2>()).ToArray();
var target = new Image<TPixel2>(this.ImageConfiguration, this.Width, this.Height, this.MetaData, frames);
var target = new Image<TPixel2>(this.configuration, this.Width, this.Height, this.MetaData, frames);
return target;
}

8
src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor.cs

@ -48,13 +48,13 @@ namespace SixLabors.ImageSharp.Processing.Processors
public TPixel LowerColor { get; set; }
/// <inheritdoc/>
protected override void BeforeApply(ImageFrame<TPixel> source, Rectangle sourceRectangle)
protected override void BeforeApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)
{
new GrayscaleBt709Processor<TPixel>().Apply(source, sourceRectangle);
new GrayscaleBt709Processor<TPixel>().Apply(source, sourceRectangle, configuration);
}
/// <inheritdoc/>
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle)
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)
{
float threshold = this.Threshold;
TPixel upper = this.UpperColor;
@ -85,7 +85,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
Parallel.For(
minY,
maxY,
source.Configuration().ParallelOptions,
configuration.ParallelOptions,
y =>
{
Span<TPixel> row = source.GetPixelRowSpan(y - startY);

6
src/ImageSharp/Processing/Processors/Binarization/ErrorDiffusionDitherProcessor.cs

@ -55,13 +55,13 @@ namespace SixLabors.ImageSharp.Processing.Processors
public TPixel LowerColor { get; set; }
/// <inheritdoc/>
protected override void BeforeApply(ImageFrame<TPixel> source, Rectangle sourceRectangle)
protected override void BeforeApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)
{
new GrayscaleBt709Processor<TPixel>().Apply(source, sourceRectangle);
new GrayscaleBt709Processor<TPixel>().Apply(source, sourceRectangle, configuration);
}
/// <inheritdoc/>
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle)
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)
{
var interest = Rectangle.Intersect(sourceRectangle, source.Bounds());
int startY = interest.Y;

6
src/ImageSharp/Processing/Processors/Binarization/OrderedDitherProcessor.cs

@ -63,13 +63,13 @@ namespace SixLabors.ImageSharp.Processing.Processors
public TPixel LowerColor { get; set; }
/// <inheritdoc/>
protected override void BeforeApply(ImageFrame<TPixel> source, Rectangle sourceRectangle)
protected override void BeforeApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)
{
new GrayscaleBt709Processor<TPixel>().Apply(source, sourceRectangle);
new GrayscaleBt709Processor<TPixel>().Apply(source, sourceRectangle, configuration);
}
/// <inheritdoc/>
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle)
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)
{
var interest = Rectangle.Intersect(sourceRectangle, source.Bounds());
int startY = interest.Y;

33
src/ImageSharp/Processing/Processors/CloningImageProcessor.cs

@ -2,7 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Primitives;
@ -27,6 +27,7 @@ namespace SixLabors.ImageSharp.Processing
throw new ImageProcessingException($"An error occured when processing the image using {this.GetType().Name}. The processor changed the number of frames.");
}
var configuration = source.Configuration();
this.BeforeImageApply(source, clone, sourceRectangle);
for (int i = 0; i < source.Frames.Count; i++)
@ -34,10 +35,9 @@ namespace SixLabors.ImageSharp.Processing
ImageFrame<TPixel> sourceFrame = source.Frames[i];
ImageFrame<TPixel> clonedFrame = clone.Frames[i];
this.BeforeApply(sourceFrame, clonedFrame, sourceRectangle);
this.OnApply(sourceFrame, clonedFrame, sourceRectangle);
this.AfterApply(sourceFrame, clonedFrame, sourceRectangle);
this.BeforeApply(sourceFrame, clonedFrame, sourceRectangle, configuration);
this.OnApply(sourceFrame, clonedFrame, sourceRectangle, configuration);
this.AfterApply(sourceFrame, clonedFrame, sourceRectangle, configuration);
}
this.AfterImageApply(source, clone, sourceRectangle);
@ -99,33 +99,30 @@ namespace SixLabors.ImageSharp.Processing
/// </summary>
/// <param name="source">The source image. Cannot be null.</param>
/// <param name="destination">The cloned/destination image. Cannot be null.</param>
/// <param name="sourceRectangle">
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to draw.
/// </param>
protected virtual void BeforeApply(ImageFrame<TPixel> source, ImageFrame<TPixel> destination, Rectangle sourceRectangle)
/// <param name="sourceRectangle">The <see cref="Rectangle" /> structure that specifies the portion of the image object to draw.</param>
/// <param name="configuration">The configuration.</param>
protected virtual void BeforeApply(ImageFrame<TPixel> source, ImageFrame<TPixel> destination, Rectangle sourceRectangle, Configuration configuration)
{
}
/// <summary>
/// Applies the process to the specified portion of the specified <see cref="ImageFrame{TPixel}"/> at the specified location
/// Applies the process to the specified portion of the specified <see cref="ImageFrame{TPixel}" /> at the specified location
/// and with the specified size.
/// </summary>
/// <param name="source">The source image. Cannot be null.</param>
/// <param name="destination">The cloned/destination image. Cannot be null.</param>
/// <param name="sourceRectangle">
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to draw.
/// </param>
protected abstract void OnApply(ImageFrame<TPixel> source, ImageFrame<TPixel> destination, Rectangle sourceRectangle);
/// <param name="sourceRectangle">The <see cref="Rectangle" /> structure that specifies the portion of the image object to draw.</param>
/// <param name="configuration">The configuration.</param>
protected abstract void OnApply(ImageFrame<TPixel> source, ImageFrame<TPixel> destination, Rectangle sourceRectangle, Configuration configuration);
/// <summary>
/// This method is called after the process is applied to prepare the processor.
/// </summary>
/// <param name="source">The source image. Cannot be null.</param>
/// <param name="destination">The cloned/destination image. Cannot be null.</param>
/// <param name="sourceRectangle">
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to draw.
/// </param>
protected virtual void AfterApply(ImageFrame<TPixel> source, ImageFrame<TPixel> destination, Rectangle sourceRectangle)
/// <param name="sourceRectangle">The <see cref="Rectangle" /> structure that specifies the portion of the image object to draw.</param>
/// <param name="configuration">The configuration.</param>
protected virtual void AfterApply(ImageFrame<TPixel> source, ImageFrame<TPixel> destination, Rectangle sourceRectangle, Configuration configuration)
{
}

4
src/ImageSharp/Processing/Processors/ColorMatrix/ColorMatrixProcessor.cs

@ -24,7 +24,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
public virtual bool Compand { get; set; } = true;
/// <inheritdoc/>
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle)
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)
{
int startY = sourceRectangle.Y;
int endY = sourceRectangle.Bottom;
@ -54,7 +54,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
Parallel.For(
minY,
maxY,
source.Configuration().ParallelOptions,
configuration.ParallelOptions,
y =>
{
Span<TPixel> row = source.GetPixelRowSpan(y - startY);

4
src/ImageSharp/Processing/Processors/ColorMatrix/LomographProcessor.cs

@ -39,9 +39,9 @@ namespace SixLabors.ImageSharp.Processing.Processors
};
/// <inheritdoc/>
protected override void AfterApply(ImageFrame<TPixel> source, Rectangle sourceRectangle)
protected override void AfterApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)
{
new VignetteProcessor<TPixel>(VeryDarkGreen, this.options).Apply(source, sourceRectangle);
new VignetteProcessor<TPixel>(VeryDarkGreen, this.options).Apply(source, sourceRectangle, configuration);
}
}
}

6
src/ImageSharp/Processing/Processors/ColorMatrix/PolaroidProcessor.cs

@ -46,10 +46,10 @@ namespace SixLabors.ImageSharp.Processing.Processors
};
/// <inheritdoc/>
protected override void AfterApply(ImageFrame<TPixel> source, Rectangle sourceRectangle)
protected override void AfterApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)
{
new VignetteProcessor<TPixel>(VeryDarkOrange, this.options).Apply(source, sourceRectangle);
new GlowProcessor<TPixel>(LightOrange, source.Width / 4F, this.options).Apply(source, sourceRectangle);
new VignetteProcessor<TPixel>(VeryDarkOrange, this.options).Apply(source, sourceRectangle, configuration);
new GlowProcessor<TPixel>(LightOrange, source.Width / 4F, this.options).Apply(source, sourceRectangle, configuration);
}
}
}

4
src/ImageSharp/Processing/Processors/Convolution/BoxBlurProcessor.cs

@ -50,9 +50,9 @@ namespace SixLabors.ImageSharp.Processing.Processors
public Fast2DArray<float> KernelY { get; }
/// <inheritdoc/>
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle)
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)
{
new Convolution2PassProcessor<TPixel>(this.KernelX, this.KernelY).Apply(source, sourceRectangle);
new Convolution2PassProcessor<TPixel>(this.KernelX, this.KernelY).Apply(source, sourceRectangle, configuration);
}
/// <summary>

4
src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor.cs

@ -40,7 +40,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
public Fast2DArray<float> KernelY { get; }
/// <inheritdoc/>
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle)
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)
{
int kernelYHeight = this.KernelY.Height;
int kernelYWidth = this.KernelY.Width;
@ -63,7 +63,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
Parallel.For(
startY,
endY,
source.Configuration().ParallelOptions,
configuration.ParallelOptions,
y =>
{
Span<TPixel> sourceRow = source.GetPixelRowSpan(y);

4
src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor.cs

@ -41,11 +41,11 @@ namespace SixLabors.ImageSharp.Processing.Processors
public Fast2DArray<float> KernelY { get; }
/// <inheritdoc/>
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle)
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)
{
int width = source.Width;
int height = source.Height;
ParallelOptions parallelOptions = source.Configuration().ParallelOptions;
ParallelOptions parallelOptions = configuration.ParallelOptions;
using (var firstPassPixels = new PixelAccessor<TPixel>(width, height))
using (PixelAccessor<TPixel> sourcePixels = source.Lock())

4
src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor.cs

@ -33,7 +33,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
public Fast2DArray<float> KernelXY { get; }
/// <inheritdoc/>
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle)
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)
{
int kernelLength = this.KernelXY.Height;
int radius = kernelLength >> 1;
@ -52,7 +52,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
Parallel.For(
startY,
endY,
source.Configuration().ParallelOptions,
configuration.ParallelOptions,
y =>
{
Span<TPixel> sourceRow = source.GetPixelRowSpan(y);

8
src/ImageSharp/Processing/Processors/Convolution/EdgeDetection/EdgeDetector2DProcessor.cs

@ -40,17 +40,17 @@ namespace SixLabors.ImageSharp.Processing.Processors
public bool Grayscale { get; set; }
/// <inheritdoc />
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle)
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)
{
new Convolution2DProcessor<TPixel>(this.KernelX, this.KernelY).Apply(source, sourceRectangle);
new Convolution2DProcessor<TPixel>(this.KernelX, this.KernelY).Apply(source, sourceRectangle, configuration);
}
/// <inheritdoc/>
protected override void BeforeApply(ImageFrame<TPixel> source, Rectangle sourceRectangle)
protected override void BeforeApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)
{
if (this.Grayscale)
{
new GrayscaleBt709Processor<TPixel>().Apply(source, sourceRectangle);
new GrayscaleBt709Processor<TPixel>().Apply(source, sourceRectangle, configuration);
}
}
}

12
src/ImageSharp/Processing/Processors/Convolution/EdgeDetection/EdgeDetectorCompassProcessor.cs

@ -62,16 +62,16 @@ namespace SixLabors.ImageSharp.Processing.Processors
public bool Grayscale { get; set; }
/// <inheritdoc/>
protected override void BeforeApply(ImageFrame<TPixel> source, Rectangle sourceRectangle)
protected override void BeforeApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)
{
if (this.Grayscale)
{
new GrayscaleBt709Processor<TPixel>().Apply(source, sourceRectangle);
new GrayscaleBt709Processor<TPixel>().Apply(source, sourceRectangle, configuration);
}
}
/// <inheritdoc />
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle)
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)
{
Fast2DArray<float>[] kernels = { this.North, this.NorthWest, this.West, this.SouthWest, this.South, this.SouthEast, this.East, this.NorthEast };
@ -89,7 +89,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
// we need a clean copy for each pass to start from
using (ImageFrame<TPixel> cleanCopy = source.Clone())
{
new ConvolutionProcessor<TPixel>(kernels[0]).Apply(source, sourceRectangle);
new ConvolutionProcessor<TPixel>(kernels[0]).Apply(source, sourceRectangle, configuration);
if (kernels.Length == 1)
{
@ -116,7 +116,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
{
using (ImageFrame<TPixel> pass = cleanCopy.Clone())
{
new ConvolutionProcessor<TPixel>(kernels[i]).Apply(pass, sourceRectangle);
new ConvolutionProcessor<TPixel>(kernels[i]).Apply(pass, sourceRectangle, configuration);
using (PixelAccessor<TPixel> passPixels = pass.Lock())
using (PixelAccessor<TPixel> targetPixels = source.Lock())
@ -124,7 +124,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
Parallel.For(
minY,
maxY,
source.Configuration().ParallelOptions,
configuration.ParallelOptions,
y =>
{
int offsetY = y - shiftY;

8
src/ImageSharp/Processing/Processors/Convolution/EdgeDetection/EdgeDetectorProcessor.cs

@ -33,18 +33,18 @@ namespace SixLabors.ImageSharp.Processing.Processors
public Fast2DArray<float> KernelXY { get; }
/// <inheritdoc/>
protected override void BeforeApply(ImageFrame<TPixel> source, Rectangle sourceRectangle)
protected override void BeforeApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)
{
if (this.Grayscale)
{
new GrayscaleBt709Processor<TPixel>().Apply(source, sourceRectangle);
new GrayscaleBt709Processor<TPixel>().Apply(source, sourceRectangle, configuration);
}
}
/// <inheritdoc/>
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle)
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)
{
new ConvolutionProcessor<TPixel>(this.KernelXY).Apply(source, sourceRectangle);
new ConvolutionProcessor<TPixel>(this.KernelXY).Apply(source, sourceRectangle, configuration);
}
}
}

4
src/ImageSharp/Processing/Processors/Convolution/GaussianBlurProcessor.cs

@ -85,9 +85,9 @@ namespace SixLabors.ImageSharp.Processing.Processors
public Fast2DArray<float> KernelY { get; }
/// <inheritdoc/>
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle)
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)
{
new Convolution2PassProcessor<TPixel>(this.KernelX, this.KernelY).Apply(source, sourceRectangle);
new Convolution2PassProcessor<TPixel>(this.KernelX, this.KernelY).Apply(source, sourceRectangle, configuration);
}
/// <summary>

4
src/ImageSharp/Processing/Processors/Convolution/GaussianSharpenProcessor.cs

@ -87,9 +87,9 @@ namespace SixLabors.ImageSharp.Processing.Processors
public Fast2DArray<float> KernelY { get; }
/// <inheritdoc/>
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle)
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)
{
new Convolution2PassProcessor<TPixel>(this.KernelX, this.KernelY).Apply(source, sourceRectangle);
new Convolution2PassProcessor<TPixel>(this.KernelX, this.KernelY).Apply(source, sourceRectangle, configuration);
}
/// <summary>

2
src/ImageSharp/Processing/Processors/DelegateProcessor.cs

@ -37,7 +37,7 @@ namespace SixLabors.ImageSharp.Processing
}
/// <inheritdoc/>
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle)
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)
{
// NOP, we did all we wanted to do inside BeforeImageApply
}

4
src/ImageSharp/Processing/Processors/Effects/AlphaProcessor.cs

@ -36,7 +36,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
public float Value { get; }
/// <inheritdoc/>
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle)
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)
{
int startY = sourceRectangle.Y;
int endY = sourceRectangle.Bottom;
@ -65,7 +65,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
Parallel.For(
minY,
maxY,
source.Configuration().ParallelOptions,
configuration.ParallelOptions,
y =>
{
Span<TPixel> row = source.GetPixelRowSpan(y - startY);

4
src/ImageSharp/Processing/Processors/Effects/BackgroundColorProcessor.cs

@ -41,7 +41,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
public TPixel Value { get; }
/// <inheritdoc/>
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle)
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)
{
int startY = sourceRectangle.Y;
int endY = sourceRectangle.Bottom;
@ -80,7 +80,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
Parallel.For(
minY,
maxY,
source.Configuration().ParallelOptions,
configuration.ParallelOptions,
y =>
{
Span<TPixel> destination = source.GetPixelRowSpan(y - startY).Slice(minX - startX, width);

4
src/ImageSharp/Processing/Processors/Effects/BrightnessProcessor.cs

@ -36,7 +36,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
public int Value { get; }
/// <inheritdoc/>
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle)
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)
{
float brightness = this.Value / 100F;
@ -65,7 +65,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
Parallel.For(
minY,
maxY,
source.Configuration().ParallelOptions,
configuration.ParallelOptions,
y =>
{
Span<TPixel> row = source.GetPixelRowSpan(y - startY);

4
src/ImageSharp/Processing/Processors/Effects/ContrastProcessor.cs

@ -36,7 +36,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
public int Value { get; }
/// <inheritdoc/>
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle)
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)
{
float contrast = (100F + this.Value) / 100F;
@ -67,7 +67,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
Parallel.For(
minY,
maxY,
source.Configuration().ParallelOptions,
configuration.ParallelOptions,
y =>
{
Span<TPixel> row = source.GetPixelRowSpan(y - startY);

4
src/ImageSharp/Processing/Processors/Effects/InvertProcessor.cs

@ -18,7 +18,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
where TPixel : struct, IPixel<TPixel>
{
/// <inheritdoc/>
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle)
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)
{
int startY = sourceRectangle.Y;
int endY = sourceRectangle.Bottom;
@ -46,7 +46,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
Parallel.For(
minY,
maxY,
source.Configuration().ParallelOptions,
configuration.ParallelOptions,
y =>
{
Span<TPixel> row = source.GetPixelRowSpan(y - startY);

4
src/ImageSharp/Processing/Processors/Effects/OilPaintingProcessor.cs

@ -48,7 +48,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
public int BrushSize { get; }
/// <inheritdoc/>
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle)
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)
{
if (this.BrushSize <= 0 || this.BrushSize > source.Height || this.BrushSize > source.Width)
{
@ -72,7 +72,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
Parallel.For(
startY,
maxY,
source.Configuration().ParallelOptions,
configuration.ParallelOptions,
y =>
{
Span<TPixel> sourceRow = source.GetPixelRowSpan(y);

4
src/ImageSharp/Processing/Processors/Effects/PixelateProcessor.cs

@ -37,7 +37,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
public int Size { get; }
/// <inheritdoc/>
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle)
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)
{
if (this.Size <= 0 || this.Size > source.Height || this.Size > source.Width)
{
@ -73,7 +73,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
Parallel.ForEach(
range,
source.Configuration().ParallelOptions,
configuration.ParallelOptions,
y =>
{
int offsetY = y - startY;

47
src/ImageSharp/Processing/Processors/ImageProcessor.cs

@ -2,7 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Primitives;
@ -20,13 +20,12 @@ namespace SixLabors.ImageSharp.Processing
{
try
{
var config = source.Configuration();
this.BeforeImageApply(source, sourceRectangle);
foreach (ImageFrame<TPixel> sourceFrame in source.Frames)
{
this.BeforeApply(sourceFrame, sourceRectangle);
this.OnApply(sourceFrame, sourceRectangle);
this.AfterApply(sourceFrame, sourceRectangle);
this.Apply(sourceFrame, sourceRectangle, config);
}
this.AfterImageApply(source, sourceRectangle);
@ -48,13 +47,14 @@ namespace SixLabors.ImageSharp.Processing
/// </summary>
/// <param name="source">the source image</param>
/// <param name="sourceRectangle">the target</param>
public void Apply(ImageFrame<TPixel> source, Rectangle sourceRectangle)
/// <param name="configuration">The configuration.</param>
public void Apply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)
{
try
{
this.BeforeApply(source, sourceRectangle);
this.OnApply(source, sourceRectangle);
this.AfterApply(source, sourceRectangle);
this.BeforeApply(source, sourceRectangle, configuration);
this.OnApply(source, sourceRectangle, configuration);
this.AfterApply(source, sourceRectangle, configuration);
}
#if DEBUG
catch (Exception)
@ -72,9 +72,7 @@ namespace SixLabors.ImageSharp.Processing
/// This method is called before the process is applied to prepare the processor.
/// </summary>
/// <param name="source">The source image. Cannot be null.</param>
/// <param name="sourceRectangle">
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to draw.
/// </param>
/// <param name="sourceRectangle">The <see cref="Rectangle" /> structure that specifies the portion of the image object to draw.</param>
protected virtual void BeforeImageApply(Image<TPixel> source, Rectangle sourceRectangle)
{
}
@ -83,31 +81,28 @@ namespace SixLabors.ImageSharp.Processing
/// This method is called before the process is applied to prepare the processor.
/// </summary>
/// <param name="source">The source image. Cannot be null.</param>
/// <param name="sourceRectangle">
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to draw.
/// </param>
protected virtual void BeforeApply(ImageFrame<TPixel> source, Rectangle sourceRectangle)
/// <param name="sourceRectangle">The <see cref="Rectangle" /> structure that specifies the portion of the image object to draw.</param>
/// <param name="configuration">The configuration.</param>
protected virtual void BeforeApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)
{
}
/// <summary>
/// Applies the process to the specified portion of the specified <see cref="ImageFrame{TPixel}"/> at the specified location
/// Applies the process to the specified portion of the specified <see cref="ImageFrame{TPixel}" /> at the specified location
/// and with the specified size.
/// </summary>
/// <param name="source">The source image. Cannot be null.</param>
/// <param name="sourceRectangle">
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to draw.
/// </param>
protected abstract void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle);
/// <param name="sourceRectangle">The <see cref="Rectangle" /> structure that specifies the portion of the image object to draw.</param>
/// <param name="configuration">The configuration.</param>
protected abstract void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration);
/// <summary>
/// This method is called after the process is applied to prepare the processor.
/// </summary>
/// <param name="source">The source image. Cannot be null.</param>
/// <param name="sourceRectangle">
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to draw.
/// </param>
protected virtual void AfterApply(ImageFrame<TPixel> source, Rectangle sourceRectangle)
/// <param name="sourceRectangle">The <see cref="Rectangle" /> structure that specifies the portion of the image object to draw.</param>
/// <param name="configuration">The configuration.</param>
protected virtual void AfterApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)
{
}
@ -115,9 +110,7 @@ namespace SixLabors.ImageSharp.Processing
/// This method is called after the process is applied to prepare the processor.
/// </summary>
/// <param name="source">The source image. Cannot be null.</param>
/// <param name="sourceRectangle">
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to draw.
/// </param>
/// <param name="sourceRectangle">The <see cref="Rectangle" /> structure that specifies the portion of the image object to draw.</param>
protected virtual void AfterImageApply(Image<TPixel> source, Rectangle sourceRectangle)
{
}

4
src/ImageSharp/Processing/Processors/Overlays/GlowProcessor.cs

@ -52,7 +52,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
public ValueSize Radius { get; set; }
/// <inheritdoc/>
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle)
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)
{
int startY = sourceRectangle.Y;
int endY = sourceRectangle.Bottom;
@ -93,7 +93,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
Parallel.For(
minY,
maxY,
source.Configuration().ParallelOptions,
configuration.ParallelOptions,
y =>
{
using (var amounts = new Buffer<float>(width))

4
src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor.cs

@ -71,7 +71,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
public ValueSize RadiusY { get; set; }
/// <inheritdoc/>
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle)
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)
{
int startY = sourceRectangle.Y;
int endY = sourceRectangle.Bottom;
@ -114,7 +114,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
Parallel.For(
minY,
maxY,
source.Configuration().ParallelOptions,
configuration.ParallelOptions,
y =>
{
using (var amounts = new Buffer<float>(width))

2
src/ImageSharp/Processing/Processors/Transforms/AutoOrientProcessor.cs

@ -61,7 +61,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
}
/// <inheritdoc />
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle)
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)
{
// Nothing required here
}

4
src/ImageSharp/Processing/Processors/Transforms/CropProcessor.cs

@ -32,7 +32,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
public Rectangle CropRectangle { get; }
/// <inheritdoc/>
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle)
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)
{
if (this.CropRectangle == sourceRectangle)
{
@ -49,7 +49,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
Parallel.For(
minY,
maxY,
source.Configuration().ParallelOptions,
configuration.ParallelOptions,
y =>
{
Span<TPixel> sourceRow = source.GetPixelRowSpan(y).Slice(minX);

8
src/ImageSharp/Processing/Processors/Transforms/EntropyCropProcessor.cs

@ -34,15 +34,15 @@ namespace SixLabors.ImageSharp.Processing.Processors
public float Threshold { get; }
/// <inheritdoc/>
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle)
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)
{
using (ImageFrame<TPixel> temp = source.Clone())
{
// Detect the edges.
new SobelProcessor<TPixel>().Apply(temp, sourceRectangle);
new SobelProcessor<TPixel>().Apply(temp, sourceRectangle, configuration);
// Apply threshold binarization filter.
new BinaryThresholdProcessor<TPixel>(this.Threshold).Apply(temp, sourceRectangle);
new BinaryThresholdProcessor<TPixel>(this.Threshold).Apply(temp, sourceRectangle, configuration);
// Search for the first white pixels
Rectangle rectangle = ImageMaths.GetFilteredBoundingRectangle(temp, 0);
@ -52,7 +52,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
return;
}
new CropProcessor<TPixel>(rectangle).Apply(source, sourceRectangle);
new CropProcessor<TPixel>(rectangle).Apply(source, sourceRectangle, configuration);
}
}
}

16
src/ImageSharp/Processing/Processors/Transforms/FlipProcessor.cs

@ -32,16 +32,16 @@ namespace SixLabors.ImageSharp.Processing.Processors
public FlipType FlipType { get; }
/// <inheritdoc/>
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle)
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)
{
switch (this.FlipType)
{
// No default needed as we have already set the pixels.
case FlipType.Vertical:
this.FlipX(source);
this.FlipX(source, configuration);
break;
case FlipType.Horizontal:
this.FlipY(source);
this.FlipY(source, configuration);
break;
}
}
@ -51,7 +51,8 @@ namespace SixLabors.ImageSharp.Processing.Processors
/// at half the height of the image.
/// </summary>
/// <param name="source">The source image to apply the process to.</param>
private void FlipX(ImageFrame<TPixel> source)
/// <param name="configuration">The configuration.</param>
private void FlipX(ImageFrame<TPixel> source, Configuration configuration)
{
int width = source.Width;
int height = source.Height;
@ -62,7 +63,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
Parallel.For(
0,
halfHeight,
source.Configuration().ParallelOptions,
configuration.ParallelOptions,
y =>
{
int newY = height - y - 1;
@ -84,7 +85,8 @@ namespace SixLabors.ImageSharp.Processing.Processors
/// at half of the width of the image.
/// </summary>
/// <param name="source">The source image to apply the process to.</param>
private void FlipY(ImageFrame<TPixel> source)
/// <param name="configuration">The configuration.</param>
private void FlipY(ImageFrame<TPixel> source, Configuration configuration)
{
int width = source.Width;
int height = source.Height;
@ -95,7 +97,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
Parallel.For(
0,
height,
source.Configuration().ParallelOptions,
configuration.ParallelOptions,
y =>
{
Span<TPixel> sourceRow = source.GetPixelRowSpan(y);

6
src/ImageSharp/Processing/Processors/Transforms/ResamplingWeightedProcessor.cs

@ -137,7 +137,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
}
/// <inheritdoc/>
protected override void BeforeApply(ImageFrame<TPixel> source, ImageFrame<TPixel> destination, Rectangle sourceRectangle)
protected override void BeforeApply(ImageFrame<TPixel> source, ImageFrame<TPixel> destination, Rectangle sourceRectangle, Configuration configuration)
{
if (!(this.Sampler is NearestNeighborResampler))
{
@ -152,9 +152,9 @@ namespace SixLabors.ImageSharp.Processing.Processors
}
/// <inheritdoc />
protected override void AfterApply(ImageFrame<TPixel> source, ImageFrame<TPixel> destination, Rectangle sourceRectangle)
protected override void AfterApply(ImageFrame<TPixel> source, ImageFrame<TPixel> destination, Rectangle sourceRectangle, Configuration configuration)
{
base.AfterApply(source, destination, sourceRectangle);
base.AfterApply(source, destination, sourceRectangle, configuration);
this.HorizontalWeights?.Dispose();
this.HorizontalWeights = null;
this.VerticalWeights?.Dispose();

8
src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs

@ -66,7 +66,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
}
/// <inheritdoc/>
protected override unsafe void OnApply(ImageFrame<TPixel> source, ImageFrame<TPixel> cloned, Rectangle sourceRectangle)
protected override unsafe void OnApply(ImageFrame<TPixel> source, ImageFrame<TPixel> cloned, Rectangle sourceRectangle, Configuration configuration)
{
// Jump out, we'll deal with that later.
if (source.Width == cloned.Width && source.Height == cloned.Height && sourceRectangle == this.ResizeRectangle)
@ -99,7 +99,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
Parallel.For(
minY,
maxY,
source.Configuration().ParallelOptions,
configuration.ParallelOptions,
y =>
{
// Y coordinates of source points
@ -128,7 +128,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
Parallel.For(
0,
sourceRectangle.Bottom,
source.Configuration().ParallelOptions,
configuration.ParallelOptions,
y =>
{
// TODO: Without Parallel.For() this buffer object could be reused:
@ -161,7 +161,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
Parallel.For(
minY,
maxY,
source.Configuration().ParallelOptions,
configuration.ParallelOptions,
y =>
{
// Ensure offsets are normalised for cropping and padding.

36
src/ImageSharp/Processing/Processors/Transforms/RotateProcessor.cs

@ -35,9 +35,9 @@ namespace SixLabors.ImageSharp.Processing.Processors
public bool Expand { get; set; } = true;
/// <inheritdoc/>
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle)
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)
{
if (this.OptimizedApply(source))
if (this.OptimizedApply(source, configuration))
{
return;
}
@ -52,7 +52,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
Parallel.For(
0,
height,
source.Configuration().ParallelOptions,
configuration.ParallelOptions,
y =>
{
Span<TPixel> targetRow = targetPixels.GetRowSpan(y);
@ -73,7 +73,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
}
/// <inheritdoc/>
protected override void BeforeApply(ImageFrame<TPixel> source, Rectangle sourceRectangle)
protected override void BeforeApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)
{
if (MathF.Abs(this.Angle) < Constants.Epsilon || MathF.Abs(this.Angle - 90) < Constants.Epsilon || MathF.Abs(this.Angle - 180) < Constants.Epsilon || MathF.Abs(this.Angle - 270) < Constants.Epsilon)
{
@ -91,8 +91,11 @@ namespace SixLabors.ImageSharp.Processing.Processors
/// Rotates the images with an optimized method when the angle is 90, 180 or 270 degrees.
/// </summary>
/// <param name="source">The source image.</param>
/// <returns>The <see cref="bool"/></returns>
private bool OptimizedApply(ImageFrame<TPixel> source)
/// <param name="configuration">The configuration.</param>
/// <returns>
/// The <see cref="bool" />
/// </returns>
private bool OptimizedApply(ImageFrame<TPixel> source, Configuration configuration)
{
if (MathF.Abs(this.Angle) < Constants.Epsilon)
{
@ -102,19 +105,19 @@ namespace SixLabors.ImageSharp.Processing.Processors
if (MathF.Abs(this.Angle - 90) < Constants.Epsilon)
{
this.Rotate90(source);
this.Rotate90(source, configuration);
return true;
}
if (MathF.Abs(this.Angle - 180) < Constants.Epsilon)
{
this.Rotate180(source);
this.Rotate180(source, configuration);
return true;
}
if (MathF.Abs(this.Angle - 270) < Constants.Epsilon)
{
this.Rotate270(source);
this.Rotate270(source, configuration);
return true;
}
@ -125,7 +128,8 @@ namespace SixLabors.ImageSharp.Processing.Processors
/// Rotates the image 270 degrees clockwise at the centre point.
/// </summary>
/// <param name="source">The source image.</param>
private void Rotate270(ImageFrame<TPixel> source)
/// <param name="configuration">The configuration.</param>
private void Rotate270(ImageFrame<TPixel> source, Configuration configuration)
{
int width = source.Width;
int height = source.Height;
@ -137,7 +141,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
Parallel.For(
0,
height,
source.Configuration().ParallelOptions,
configuration.ParallelOptions,
y =>
{
for (int x = 0; x < width; x++)
@ -158,7 +162,8 @@ namespace SixLabors.ImageSharp.Processing.Processors
/// Rotates the image 180 degrees clockwise at the centre point.
/// </summary>
/// <param name="source">The source image.</param>
private void Rotate180(ImageFrame<TPixel> source)
/// <param name="configuration">The configuration.</param>
private void Rotate180(ImageFrame<TPixel> source, Configuration configuration)
{
int width = source.Width;
int height = source.Height;
@ -168,7 +173,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
Parallel.For(
0,
height,
source.Configuration().ParallelOptions,
configuration.ParallelOptions,
y =>
{
Span<TPixel> sourceRow = source.GetPixelRowSpan(y);
@ -188,7 +193,8 @@ namespace SixLabors.ImageSharp.Processing.Processors
/// Rotates the image 90 degrees clockwise at the centre point.
/// </summary>
/// <param name="source">The source image.</param>
private void Rotate90(ImageFrame<TPixel> source)
/// <param name="configuration">The configuration.</param>
private void Rotate90(ImageFrame<TPixel> source, Configuration configuration)
{
int width = source.Width;
int height = source.Height;
@ -198,7 +204,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
Parallel.For(
0,
height,
source.Configuration().ParallelOptions,
configuration.ParallelOptions,
y =>
{
Span<TPixel> sourceRow = source.GetPixelRowSpan(y);

6
src/ImageSharp/Processing/Processors/Transforms/SkewProcessor.cs

@ -40,7 +40,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
public bool Expand { get; set; } = true;
/// <inheritdoc/>
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle)
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)
{
int height = this.CanvasRectangle.Height;
int width = this.CanvasRectangle.Width;
@ -52,7 +52,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
Parallel.For(
0,
height,
source.Configuration().ParallelOptions,
configuration.ParallelOptions,
y =>
{
Span<TPixel> targetRow = targetPixels.GetRowSpan(y);
@ -73,7 +73,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
}
/// <inheritdoc/>
protected override void BeforeApply(ImageFrame<TPixel> source, Rectangle sourceRectangle)
protected override void BeforeApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)
{
this.processMatrix = Matrix3x2Extensions.CreateSkewDegrees(-this.AngleX, -this.AngleY, new Point(0, 0));
if (this.Expand)

4
tests/ImageSharp.Benchmarks/Samplers/Glow.cs

@ -75,7 +75,7 @@ namespace SixLabors.ImageSharp.Benchmarks
public float Radius { get; set; }
/// <inheritdoc/>
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle)
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)
{
int startY = sourceRectangle.Y;
int endY = sourceRectangle.Bottom;
@ -114,7 +114,7 @@ namespace SixLabors.ImageSharp.Benchmarks
Parallel.For(
minY,
maxY,
source.Configuration().ParallelOptions,
configuration.ParallelOptions,
y =>
{
int offsetY = y - startY;

4
tests/ImageSharp.Tests/TestUtilities/ImageComparison/ExactImageComparer.cs

@ -12,7 +12,7 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison
{
public static ExactImageComparer Instance { get; } = new ExactImageComparer();
public override ImageSimilarityReport CompareImagesOrFrames<TPixelA, TPixelB>(
public override ImageSimilarityReport<TPixelA, TPixelB> CompareImagesOrFrames<TPixelA, TPixelB>(
ImageFrame<TPixelA> expected,
ImageFrame<TPixelB> actual)
{
@ -51,7 +51,7 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison
}
}
return new ImageSimilarityReport(expected, actual, differences);
return new ImageSimilarityReport<TPixelA, TPixelB>(expected, actual, differences);
}
}
}

16
tests/ImageSharp.Tests/TestUtilities/ImageComparison/ImageComparer.cs

@ -22,7 +22,7 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison
return new TolerantImageComparer(imageThreshold, perPixelManhattanThreshold);
}
public abstract ImageSimilarityReport CompareImagesOrFrames<TPixelA, TPixelB>(
public abstract ImageSimilarityReport<TPixelA, TPixelB> CompareImagesOrFrames<TPixelA, TPixelB>(
ImageFrame<TPixelA> expected,
ImageFrame<TPixelB> actual)
where TPixelA : struct, IPixel<TPixelA> where TPixelB : struct, IPixel<TPixelB>;
@ -30,7 +30,7 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison
public static class ImageComparerExtensions
{
public static ImageSimilarityReport CompareImagesOrFrames<TPixelA, TPixelB>(
public static ImageSimilarityReport<TPixelA, TPixelB> CompareImagesOrFrames<TPixelA, TPixelB>(
this ImageComparer comparer,
Image<TPixelA> expected,
Image<TPixelB> actual)
@ -39,13 +39,13 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison
return comparer.CompareImagesOrFrames((ImageFrame<TPixelA>)expected, (ImageFrame<TPixelB>)actual);
}
public static IEnumerable<ImageSimilarityReport> CompareImages<TPixelA, TPixelB>(
public static IEnumerable<ImageSimilarityReport<TPixelA, TPixelB>> CompareImages<TPixelA, TPixelB>(
this ImageComparer comparer,
Image<TPixelA> expected,
Image<TPixelB> actual)
where TPixelA : struct, IPixel<TPixelA> where TPixelB : struct, IPixel<TPixelB>
{
var result = new List<ImageSimilarityReport>();
var result = new List<ImageSimilarityReport<TPixelA, TPixelB>>();
if (expected.Frames.Count != actual.Frames.Count)
{
@ -53,7 +53,7 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison
}
for (int i = 0; i < expected.Frames.Count; i++)
{
ImageSimilarityReport report = comparer.CompareImagesOrFrames(expected.Frames[i], actual.Frames[i]);
ImageSimilarityReport<TPixelA, TPixelB> report = comparer.CompareImagesOrFrames(expected.Frames[i], actual.Frames[i]);
if (!report.IsEmpty)
{
result.Add(report);
@ -104,10 +104,10 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison
throw new ImagesSimilarityException("Image frame count does not match!");
}
IEnumerable<ImageSimilarityReport> reports = comparer.CompareImages(expected, actual);
IEnumerable<ImageSimilarityReport<TPixelA, TPixelB>> reports = comparer.CompareImages(expected, actual);
if (reports.Any())
{
List<ImageSimilarityReport> cleanedReports = new List<ImageSimilarityReport>(reports.Count());
List<ImageSimilarityReport<TPixelA, TPixelB>> cleanedReports = new List<ImageSimilarityReport<TPixelA, TPixelB>>(reports.Count());
foreach (var r in reports)
{
var outsideChanges = r.Differences.Where(x => !(
@ -117,7 +117,7 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison
x.Position.Y <= ignoredRegion.Bottom));
if (outsideChanges.Any())
{
cleanedReports.Add(new ImageSimilarityReport(r.ExpectedImage, r.ActualImage, outsideChanges, null));
cleanedReports.Add(new ImageSimilarityReport<TPixelA, TPixelB>(r.ExpectedImage, r.ActualImage, outsideChanges, null));
}
}

38
tests/ImageSharp.Tests/TestUtilities/ImageComparison/ImageSimilarityReport.cs

@ -4,12 +4,13 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SixLabors.ImageSharp.PixelFormats;
public class ImageSimilarityReport
{
public ImageSimilarityReport(
IImageFrame expectedImage,
IImageFrame actualImage,
protected ImageSimilarityReport(
object expectedImage,
object actualImage,
IEnumerable<PixelDifference> differences,
float? totalNormalizedDifference = null)
{
@ -18,9 +19,9 @@
this.TotalNormalizedDifference = totalNormalizedDifference;
this.Differences = differences.ToArray();
}
public object ExpectedImage { get; }
public static ImageSimilarityReport Empty =>
new ImageSimilarityReport(null, null, Enumerable.Empty<PixelDifference>(), 0f);
public object ActualImage { get; }
// TODO: This should not be a nullable value!
public float? TotalNormalizedDifference { get; }
@ -29,10 +30,6 @@
? $"{this.TotalNormalizedDifference.Value * 100:0.0000}%"
: "?";
public IImageFrame ExpectedImage { get; }
public IImageFrame ActualImage { get; }
public PixelDifference[] Differences { get; }
public bool IsEmpty => this.Differences.Length == 0;
@ -41,7 +38,7 @@
{
return this.IsEmpty ? "[SimilarImages]" : this.PrintDifference();
}
private string PrintDifference()
{
var sb = new StringBuilder();
@ -66,4 +63,25 @@
return sb.ToString();
}
}
public class ImageSimilarityReport<TPixelA, TPixelB> : ImageSimilarityReport
where TPixelA : struct, IPixel<TPixelA>
where TPixelB : struct, IPixel<TPixelB>
{
public ImageSimilarityReport(
ImageFrame<TPixelA> expectedImage,
ImageFrame<TPixelB> actualImage,
IEnumerable<PixelDifference> differences,
float? totalNormalizedDifference = null)
: base(expectedImage, actualImage, differences, totalNormalizedDifference)
{
}
public static ImageSimilarityReport<TPixelA, TPixelB> Empty =>
new ImageSimilarityReport<TPixelA, TPixelB>(null, null, Enumerable.Empty<PixelDifference>(), 0f);
public new ImageFrame<TPixelA> ExpectedImage => (ImageFrame<TPixelA>)base.ExpectedImage;
public new ImageFrame<TPixelB> ActualImage => (ImageFrame<TPixelB>)base.ActualImage;
}
}

6
tests/ImageSharp.Tests/TestUtilities/ImageComparison/TolerantImageComparer.cs

@ -46,7 +46,7 @@
/// </summary>
public int PerPixelManhattanThreshold { get; }
public override ImageSimilarityReport CompareImagesOrFrames<TPixelA, TPixelB>(ImageFrame<TPixelA> expected, ImageFrame<TPixelB> actual)
public override ImageSimilarityReport<TPixelA, TPixelB> CompareImagesOrFrames<TPixelA, TPixelB>(ImageFrame<TPixelA> expected, ImageFrame<TPixelB> actual)
{
if (expected.Size() != actual.Size())
{
@ -91,11 +91,11 @@
if (normalizedDifference > this.ImageThreshold)
{
return new ImageSimilarityReport(expected, actual, differences, normalizedDifference);
return new ImageSimilarityReport<TPixelA, TPixelB>(expected, actual, differences, normalizedDifference);
}
else
{
return ImageSimilarityReport.Empty;
return ImageSimilarityReport<TPixelA, TPixelB>.Empty;
}
}

Loading…
Cancel
Save