diff --git a/src/ImageSharp/Advanced/AotCompilerTools.cs b/src/ImageSharp/Advanced/AotCompilerTools.cs index 8d3a074b5..1ceba5f90 100644 --- a/src/ImageSharp/Advanced/AotCompilerTools.cs +++ b/src/ImageSharp/Advanced/AotCompilerTools.cs @@ -2,13 +2,12 @@ // Licensed under the Apache License, Version 2.0. using System.Numerics; +using System.Runtime.CompilerServices; using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.Formats.Jpeg.Components; using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Processing.Processors.Dithering; using SixLabors.ImageSharp.Processing.Processors.Quantization; -using SixLabors.ImageSharp.Processing.Processors.Transforms; namespace SixLabors.ImageSharp.Advanced { @@ -81,9 +80,8 @@ namespace SixLabors.ImageSharp.Advanced AotCompileWuQuantizer(); AotCompileDithering(); AotCompilePixelOperations(); - AotCompileResizeOperations(); - System.Runtime.CompilerServices.Unsafe.SizeOf(); + Unsafe.SizeOf(); AotCodec(new Formats.Png.PngDecoder(), new Formats.Png.PngEncoder()); AotCodec(new Formats.Bmp.BmpDecoder(), new Formats.Bmp.BmpEncoder()); @@ -107,8 +105,10 @@ namespace SixLabors.ImageSharp.Advanced private static void AotCompileOctreeQuantizer() where TPixel : struct, IPixel { - var test = new OctreeFrameQuantizer(new OctreeQuantizer(false)); - test.AotGetPalette(); + using (var test = new OctreeFrameQuantizer(new OctreeQuantizer(false))) + { + test.AotGetPalette(); + } } /// @@ -118,9 +118,11 @@ namespace SixLabors.ImageSharp.Advanced private static void AotCompileWuQuantizer() where TPixel : struct, IPixel { - var test = new WuFrameQuantizer(Configuration.Default.MemoryAllocator, new WuQuantizer(false)); - test.QuantizeFrame(new ImageFrame(Configuration.Default, 1, 1)); - test.AotGetPalette(); + using (var test = new WuFrameQuantizer(Configuration.Default.MemoryAllocator, new WuQuantizer(false))) + { + test.QuantizeFrame(new ImageFrame(Configuration.Default, 1, 1)); + test.AotGetPalette(); + } } /// @@ -132,7 +134,10 @@ namespace SixLabors.ImageSharp.Advanced { var test = new FloydSteinbergDiffuser(); TPixel pixel = default; - test.Dither(new ImageFrame(Configuration.Default, 1, 1), pixel, pixel, 0, 0, 0, 0, 0, 0); + using (var image = new ImageFrame(Configuration.Default, 1, 1)) + { + test.Dither(image, pixel, pixel, 0, 0, 0, 0, 0, 0); + } } /// @@ -171,16 +176,5 @@ namespace SixLabors.ImageSharp.Advanced var pixelOp = new PixelOperations(); pixelOp.GetPixelBlender(PixelColorBlendingMode.Normal, PixelAlphaCompositionMode.Clear); } - - /// - /// This method pre-seeds the ResizeProcessor for the AoT compiler on iOS. - /// - /// The pixel format. - private static void AotCompileResizeOperations() - where TPixel : struct, IPixel - { - var genericResizeProcessor = (ResizeProcessor)new ResizeProcessor(new ResizeOptions(), default).CreatePixelSpecificProcessor(new Image(0, 0), default); - genericResizeProcessor.AotCreateDestination(); - } } } diff --git a/src/ImageSharp/Processing/DefaultImageProcessorContext{TPixel}.cs b/src/ImageSharp/Processing/DefaultImageProcessorContext{TPixel}.cs index 7f7316694..328ccdf94 100644 --- a/src/ImageSharp/Processing/DefaultImageProcessorContext{TPixel}.cs +++ b/src/ImageSharp/Processing/DefaultImageProcessorContext{TPixel}.cs @@ -69,9 +69,9 @@ namespace SixLabors.ImageSharp.Processing { // When cloning an image we can optimize the processing pipeline by avoiding an unnecessary // interim clone if the first processor in the pipeline is a cloning processor. - if (processor is CloningImageProcessor cloningImageProcessor) + if (processor is ICloningImageProcessor cloningImageProcessor) { - using (ICloningImageProcessor pixelProcessor = cloningImageProcessor.CreatePixelSpecificProcessor(this.source, rectangle)) + using (ICloningImageProcessor pixelProcessor = cloningImageProcessor.CreatePixelSpecificCloningProcessor(this.source, rectangle)) { this.destination = pixelProcessor.CloneAndExecute(); return this; diff --git a/src/ImageSharp/Processing/Processors/CloningImageProcessor.cs b/src/ImageSharp/Processing/Processors/CloningImageProcessor.cs index 6ab0fcb13..5e9ca2e54 100644 --- a/src/ImageSharp/Processing/Processors/CloningImageProcessor.cs +++ b/src/ImageSharp/Processing/Processors/CloningImageProcessor.cs @@ -9,23 +9,14 @@ namespace SixLabors.ImageSharp.Processing.Processors /// /// The base class for all cloning image processors. /// - public abstract class CloningImageProcessor : IImageProcessor + public abstract class CloningImageProcessor : ICloningImageProcessor { - /// - /// Creates a pixel specific that is capable of executing - /// the processing algorithm on an . - /// - /// The pixel type. - /// The source image. Cannot be null. - /// - /// The structure that specifies the portion of the image object to draw. - /// - /// The - public abstract ICloningImageProcessor CreatePixelSpecificProcessor(Image source, Rectangle sourceRectangle) + /// + public abstract ICloningImageProcessor CreatePixelSpecificCloningProcessor(Image source, Rectangle sourceRectangle) where TPixel : struct, IPixel; /// IImageProcessor IImageProcessor.CreatePixelSpecificProcessor(Image source, Rectangle sourceRectangle) - => this.CreatePixelSpecificProcessor(source, sourceRectangle); + => this.CreatePixelSpecificCloningProcessor(source, sourceRectangle); } } diff --git a/src/ImageSharp/Processing/Processors/CloningImageProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/CloningImageProcessor{TPixel}.cs index 1290a1032..42d2f0e1d 100644 --- a/src/ImageSharp/Processing/Processors/CloningImageProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/CloningImageProcessor{TPixel}.cs @@ -2,6 +2,8 @@ // Licensed under the Apache License, Version 2.0. using System; +using System.Collections.Generic; +using System.Linq; using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.PixelFormats; using SixLabors.Primitives; @@ -40,16 +42,16 @@ namespace SixLabors.ImageSharp.Processing.Processors protected Rectangle SourceRectangle { get; } /// - /// Gets the instance to use when performing operations. + /// Gets the instance to use when performing operations. /// protected Configuration Configuration { get; } /// - public Image CloneAndExecute() + Image ICloningImageProcessor.CloneAndExecute() { try { - Image clone = this.CreateDestination(); + Image clone = this.CreateTarget(); this.CheckFrameCount(this.Source, clone); Configuration configuration = this.Source.GetConfiguration(); @@ -82,7 +84,7 @@ namespace SixLabors.ImageSharp.Processing.Processors } /// - public void Execute() + void IImageProcessor.Execute() { // Create an interim clone of the source image to operate on. // Doing this allows for the application of transforms that will alter @@ -90,7 +92,7 @@ namespace SixLabors.ImageSharp.Processing.Processors Image clone = default; try { - clone = this.CloneAndExecute(); + clone = ((ICloningImageProcessor)this).CloneAndExecute(); // We now need to move the pixel data/size data from the clone to the source. this.CheckFrameCount(this.Source, clone); @@ -111,10 +113,10 @@ namespace SixLabors.ImageSharp.Processing.Processors } /// - /// Generates a deep clone of the source image that operations should be applied to. + /// Gets the size of the target image. /// - /// The cloned image. - protected virtual Image CreateDestination() => this.Source.Clone(); + /// The . + protected abstract Size GetTargetSize(); /// /// This method is called before the process is applied to prepare the processor. @@ -166,6 +168,23 @@ namespace SixLabors.ImageSharp.Processing.Processors { } + private Image CreateTarget() + { + Image source = this.Source; + Size targetSize = this.GetTargetSize(); + + // We will always be creating the clone even for mutate because we may need to resize the canvas + IEnumerable> frames = source.Frames.Select, ImageFrame>( + x => new ImageFrame( + source.GetConfiguration(), + targetSize.Width, + targetSize.Height, + x.Metadata.DeepClone())); + + // Use the overload to prevent an extra frame being added + return new Image(this.Configuration, source.Metadata.DeepClone(), frames); + } + private void CheckFrameCount(Image a, Image b) { if (a.Frames.Count != b.Frames.Count) diff --git a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetector2DProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetector2DProcessor{TPixel}.cs index 7b070f99a..8358abe7d 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetector2DProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetector2DProcessor{TPixel}.cs @@ -54,7 +54,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution { if (this.Grayscale) { - new GrayscaleBt709Processor(1F).Apply(this.Source, this.SourceRectangle); + new GrayscaleBt709Processor(1F).Execute(this.Source, this.SourceRectangle); } base.BeforeImageApply(); diff --git a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorCompassProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorCompassProcessor{TPixel}.cs index b7119ef44..dc9974c61 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorCompassProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorCompassProcessor{TPixel}.cs @@ -45,7 +45,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution { if (this.Grayscale) { - new GrayscaleBt709Processor(1F).Apply(this.Source, this.SourceRectangle); + new GrayscaleBt709Processor(1F).Execute(this.Source, this.SourceRectangle); } base.BeforeImageApply(); diff --git a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorProcessor{TPixel}.cs index fc762cf1b..5246dc3b7 100644 --- a/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Convolution/EdgeDetectorProcessor{TPixel}.cs @@ -41,7 +41,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution { if (this.Grayscale) { - new GrayscaleBt709Processor(1F).Apply(this.Source, this.SourceRectangle); + new GrayscaleBt709Processor(1F).Execute(this.Source, this.SourceRectangle); } base.BeforeImageApply(); diff --git a/src/ImageSharp/Processing/Processors/Filters/LomographProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Filters/LomographProcessor{TPixel}.cs index ab832a275..7d3a5bbc0 100644 --- a/src/ImageSharp/Processing/Processors/Filters/LomographProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Filters/LomographProcessor{TPixel}.cs @@ -29,7 +29,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters /// protected override void AfterImageApply() { - new VignetteProcessor(VeryDarkGreen).Apply(this.Source, this.SourceRectangle); + new VignetteProcessor(VeryDarkGreen).Execute(this.Source, this.SourceRectangle); base.AfterImageApply(); } } diff --git a/src/ImageSharp/Processing/Processors/Filters/PolaroidProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Filters/PolaroidProcessor{TPixel}.cs index 0be5bbb0d..f7ab1a1ec 100644 --- a/src/ImageSharp/Processing/Processors/Filters/PolaroidProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Filters/PolaroidProcessor{TPixel}.cs @@ -31,8 +31,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters /// protected override void AfterImageApply() { - new VignetteProcessor(VeryDarkOrange).Apply(this.Source, this.SourceRectangle); - new GlowProcessor(LightOrange, this.Source.Width / 4F).Apply(this.Source, this.SourceRectangle); + new VignetteProcessor(VeryDarkOrange).Execute(this.Source, this.SourceRectangle); + new GlowProcessor(LightOrange, this.Source.Width / 4F).Execute(this.Source, this.SourceRectangle); base.AfterImageApply(); } } diff --git a/src/ImageSharp/Processing/Processors/ICloningImageProcessor.cs b/src/ImageSharp/Processing/Processors/ICloningImageProcessor.cs new file mode 100644 index 000000000..554a4b886 --- /dev/null +++ b/src/ImageSharp/Processing/Processors/ICloningImageProcessor.cs @@ -0,0 +1,27 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.Primitives; + +namespace SixLabors.ImageSharp.Processing.Processors +{ + /// + /// Defines an algorithm to alter the pixels of a cloned image. + /// + public interface ICloningImageProcessor : IImageProcessor + { + /// + /// Creates a pixel specific that is capable of executing + /// the processing algorithm on an . + /// + /// The pixel type. + /// The source image. Cannot be null. + /// + /// The structure that specifies the portion of the image object to draw. + /// + /// The + ICloningImageProcessor CreatePixelSpecificCloningProcessor(Image source, Rectangle sourceRectangle) + where TPixel : struct, IPixel; + } +} diff --git a/src/ImageSharp/Processing/Processors/ICloningImageProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/ICloningImageProcessor{TPixel}.cs index c34bf60ae..84b126229 100644 --- a/src/ImageSharp/Processing/Processors/ICloningImageProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/ICloningImageProcessor{TPixel}.cs @@ -6,7 +6,7 @@ using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp.Processing.Processors { /// - /// Encapsulates methods to alter the pixels of a new image, cloned from the original image. + /// Implements an algorithm to alter the pixels of a cloned image. /// /// The pixel format. public interface ICloningImageProcessor : IImageProcessor diff --git a/src/ImageSharp/Processing/Processors/ImageProcessorExtensions.cs b/src/ImageSharp/Processing/Processors/ImageProcessorExtensions.cs index 19e594a32..ce8ed813b 100644 --- a/src/ImageSharp/Processing/Processors/ImageProcessorExtensions.cs +++ b/src/ImageSharp/Processing/Processors/ImageProcessorExtensions.cs @@ -9,18 +9,21 @@ namespace SixLabors.ImageSharp.Processing.Processors { internal static class ImageProcessorExtensions { - public static void Apply(this IImageProcessor processor, Image source, Rectangle sourceRectangle) - { - source.AcceptVisitor(new ApplyVisitor(processor, sourceRectangle)); - } + /// + /// Executes the processor against the given source image and rectangle bounds. + /// + /// The processor. + /// The source image. + /// The source bounds. + public static void Execute(this IImageProcessor processor, Image source, Rectangle sourceRectangle) + => source.AcceptVisitor(new ExecuteVisitor(processor, sourceRectangle)); - private class ApplyVisitor : IImageVisitor + private class ExecuteVisitor : IImageVisitor { private readonly IImageProcessor processor; - private readonly Rectangle sourceRectangle; - public ApplyVisitor(IImageProcessor processor, Rectangle sourceRectangle) + public ExecuteVisitor(IImageProcessor processor, Rectangle sourceRectangle) { this.processor = processor; this.sourceRectangle = sourceRectangle; diff --git a/src/ImageSharp/Processing/Processors/ImageProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/ImageProcessor{TPixel}.cs index eb1dc4ba0..3e46e3c08 100644 --- a/src/ImageSharp/Processing/Processors/ImageProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/ImageProcessor{TPixel}.cs @@ -44,7 +44,7 @@ namespace SixLabors.ImageSharp.Processing.Processors protected Configuration Configuration { get; } /// - public void Execute() + void IImageProcessor.Execute() { try { diff --git a/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor.cs index be5675578..6ca844fae 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor.cs @@ -41,7 +41,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms public Size TargetDimensions { get; } /// - public override ICloningImageProcessor CreatePixelSpecificProcessor(Image source, Rectangle sourceRectangle) + public override ICloningImageProcessor CreatePixelSpecificCloningProcessor(Image source, Rectangle sourceRectangle) => new AffineTransformProcessor(this, source, sourceRectangle); } } diff --git a/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor{TPixel}.cs index 7c50c04f3..97b8b009b 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor{TPixel}.cs @@ -2,10 +2,7 @@ // Licensed under the Apache License, Version 2.0. using System; -using System.Collections.Generic; -using System.Linq; using System.Numerics; - using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.ParallelUtils; using SixLabors.ImageSharp.PixelFormats; @@ -20,6 +17,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms internal class AffineTransformProcessor : TransformProcessor where TPixel : struct, IPixel { + private Size targetSize; + private Matrix3x2 transformMatrix; + private readonly IResampler resampler; + /// /// Initializes a new instance of the class. /// @@ -29,50 +30,37 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms public AffineTransformProcessor(AffineTransformProcessor definition, Image source, Rectangle sourceRectangle) : base(source, sourceRectangle) { - this.Definition = definition; + this.targetSize = definition.TargetDimensions; + this.transformMatrix = definition.TransformMatrix; + this.resampler = definition.Sampler; } - protected AffineTransformProcessor Definition { get; } - - private Size TargetDimensions => this.Definition.TargetDimensions; - - private Matrix3x2 TransformMatrix => this.Definition.TransformMatrix; - - /// - protected override Image CreateDestination() - { - // We will always be creating the clone even for mutate because we may need to resize the canvas - IEnumerable> frames = this.Source.Frames.Select, ImageFrame>( - x => new ImageFrame(this.Configuration, this.TargetDimensions, x.Metadata.DeepClone())); - - // Use the overload to prevent an extra frame being added - return new Image(this.Configuration, this.Source.Metadata.DeepClone(), frames); - } + protected override Size GetTargetSize() => this.targetSize; /// protected override void OnFrameApply(ImageFrame source, ImageFrame destination) { // Handle transforms that result in output identical to the original. - if (this.TransformMatrix.Equals(default) || this.TransformMatrix.Equals(Matrix3x2.Identity)) + if (this.transformMatrix.Equals(default) || this.transformMatrix.Equals(Matrix3x2.Identity)) { // The clone will be blank here copy all the pixel data over source.GetPixelSpan().CopyTo(destination.GetPixelSpan()); return; } - int width = this.TargetDimensions.Width; - var targetBounds = new Rectangle(Point.Empty, this.TargetDimensions); + int width = this.targetSize.Width; + Rectangle sourceBounds = this.SourceRectangle; + var targetBounds = new Rectangle(Point.Empty, this.targetSize); + Configuration configuration = this.Configuration; // Convert from screen to world space. - Matrix3x2.Invert(this.TransformMatrix, out Matrix3x2 matrix); + Matrix3x2.Invert(this.transformMatrix, out Matrix3x2 matrix); - IResampler sampler = this.Definition.Sampler; - - if (sampler is NearestNeighborResampler) + if (this.resampler is NearestNeighborResampler) { ParallelHelper.IterateRows( targetBounds, - this.Configuration, + configuration, rows => { for (int y = rows.Min; y < rows.Max; y++) @@ -82,7 +70,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms for (int x = 0; x < width; x++) { var point = Point.Transform(new Point(x, y), matrix); - if (this.SourceRectangle.Contains(point.X, point.Y)) + if (sourceBounds.Contains(point.X, point.Y)) { destRow[x] = source[point.X, point.Y]; } @@ -93,19 +81,20 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms return; } - var kernel = new TransformKernelMap(this.Configuration, source.Size(), destination.Size(), sampler); + var kernel = new TransformKernelMap(configuration, source.Size(), destination.Size(), this.resampler); + try { ParallelHelper.IterateRowsWithTempBuffer( targetBounds, - this.Configuration, + configuration, (rows, vectorBuffer) => { Span vectorSpan = vectorBuffer.Span; for (int y = rows.Min; y < rows.Max; y++) { Span targetRowSpan = destination.GetPixelRowSpan(y); - PixelOperations.Instance.ToVector4(this.Configuration, targetRowSpan, vectorSpan); + PixelOperations.Instance.ToVector4(configuration, targetRowSpan, vectorSpan); ref float ySpanRef = ref kernel.GetYStartReference(y); ref float xSpanRef = ref kernel.GetXStartReference(y); @@ -124,7 +113,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms } PixelOperations.Instance.FromVector4Destructive( - this.Configuration, + configuration, vectorSpan, targetRowSpan); } diff --git a/src/ImageSharp/Processing/Processors/Transforms/AutoOrientProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/AutoOrientProcessor{TPixel}.cs index a5170c96a..b9952ac8f 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/AutoOrientProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/AutoOrientProcessor{TPixel}.cs @@ -34,33 +34,33 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms switch (orientation) { case OrientationMode.TopRight: - new FlipProcessor(FlipMode.Horizontal).Apply(this.Source, this.SourceRectangle); + new FlipProcessor(FlipMode.Horizontal).Execute(this.Source, this.SourceRectangle); break; case OrientationMode.BottomRight: - new RotateProcessor((int)RotateMode.Rotate180, size).Apply(this.Source, this.SourceRectangle); + new RotateProcessor((int)RotateMode.Rotate180, size).Execute(this.Source, this.SourceRectangle); break; case OrientationMode.BottomLeft: - new FlipProcessor(FlipMode.Vertical).Apply(this.Source, this.SourceRectangle); + new FlipProcessor(FlipMode.Vertical).Execute(this.Source, this.SourceRectangle); break; case OrientationMode.LeftTop: - new RotateProcessor((int)RotateMode.Rotate90, size).Apply(this.Source, this.SourceRectangle); - new FlipProcessor(FlipMode.Horizontal).Apply(this.Source, this.SourceRectangle); + new RotateProcessor((int)RotateMode.Rotate90, size).Execute(this.Source, this.SourceRectangle); + new FlipProcessor(FlipMode.Horizontal).Execute(this.Source, this.SourceRectangle); break; case OrientationMode.RightTop: - new RotateProcessor((int)RotateMode.Rotate90, size).Apply(this.Source, this.SourceRectangle); + new RotateProcessor((int)RotateMode.Rotate90, size).Execute(this.Source, this.SourceRectangle); break; case OrientationMode.RightBottom: - new FlipProcessor(FlipMode.Vertical).Apply(this.Source, this.SourceRectangle); - new RotateProcessor((int)RotateMode.Rotate270, size).Apply(this.Source, this.SourceRectangle); + new FlipProcessor(FlipMode.Vertical).Execute(this.Source, this.SourceRectangle); + new RotateProcessor((int)RotateMode.Rotate270, size).Execute(this.Source, this.SourceRectangle); break; case OrientationMode.LeftBottom: - new RotateProcessor((int)RotateMode.Rotate270, size).Apply(this.Source, this.SourceRectangle); + new RotateProcessor((int)RotateMode.Rotate270, size).Execute(this.Source, this.SourceRectangle); break; case OrientationMode.Unknown: diff --git a/src/ImageSharp/Processing/Processors/Transforms/CropProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/CropProcessor.cs index 025592a36..245a54208 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/CropProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/CropProcessor.cs @@ -32,7 +32,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms public Rectangle CropRectangle { get; } /// - public override ICloningImageProcessor CreatePixelSpecificProcessor(Image source, Rectangle sourceRectangle) + public override ICloningImageProcessor CreatePixelSpecificCloningProcessor(Image source, Rectangle sourceRectangle) => new CropProcessor(this, source, sourceRectangle); } } diff --git a/src/ImageSharp/Processing/Processors/Transforms/CropProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/CropProcessor{TPixel}.cs index 539a11f02..1bbdd0a16 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/CropProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/CropProcessor{TPixel}.cs @@ -2,9 +2,6 @@ // Licensed under the Apache License, Version 2.0. using System; -using System.Collections.Generic; -using System.Linq; - using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.ParallelUtils; using SixLabors.ImageSharp.PixelFormats; @@ -19,7 +16,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms internal class CropProcessor : TransformProcessor where TPixel : struct, IPixel { - private readonly CropProcessor definition; + private Rectangle cropRectangle; /// /// Initializes a new instance of the class. @@ -29,53 +26,42 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms /// The source area to process for the current processor instance. public CropProcessor(CropProcessor definition, Image source, Rectangle sourceRectangle) : base(source, sourceRectangle) - { - this.definition = definition; - } - - private Rectangle CropRectangle => this.definition.CropRectangle; + => this.cropRectangle = definition.CropRectangle; /// - protected override Image CreateDestination() - { - // We will always be creating the clone even for mutate because we may need to resize the canvas - IEnumerable> frames = this.Source.Frames.Select, ImageFrame>( - x => new ImageFrame( - this.Source.GetConfiguration(), - this.CropRectangle.Width, - this.CropRectangle.Height, - x.Metadata.DeepClone())); - - // Use the overload to prevent an extra frame being added - return new Image(this.Source.GetConfiguration(), this.Source.Metadata.DeepClone(), frames); - } + protected override Size GetTargetSize() => new Size(this.cropRectangle.Width, this.cropRectangle.Height); /// protected override void OnFrameApply(ImageFrame source, ImageFrame destination) { - // Handle resize dimensions identical to the original - if (source.Width == destination.Width && source.Height == destination.Height && this.SourceRectangle == this.CropRectangle) + // Handle crop dimensions identical to the original + if (source.Width == destination.Width + && source.Height == destination.Height + && this.SourceRectangle == this.cropRectangle) { // the cloned will be blank here copy all the pixel data over source.GetPixelSpan().CopyTo(destination.GetPixelSpan()); return; } - Rectangle rect = this.CropRectangle; + Rectangle bounds = this.cropRectangle; // Copying is cheap, we should process more pixels per task: - ParallelExecutionSettings parallelSettings = this.Configuration.GetParallelSettings().MultiplyMinimumPixelsPerTask(4); + ParallelExecutionSettings parallelSettings + = this.Configuration + .GetParallelSettings() + .MultiplyMinimumPixelsPerTask(4); ParallelHelper.IterateRows( - rect, + bounds, parallelSettings, rows => { for (int y = rows.Min; y < rows.Max; y++) { - Span sourceRow = source.GetPixelRowSpan(y).Slice(rect.Left); - Span targetRow = destination.GetPixelRowSpan(y - rect.Top); - sourceRow.Slice(0, rect.Width).CopyTo(targetRow); + Span sourceRow = source.GetPixelRowSpan(y).Slice(bounds.Left); + Span targetRow = destination.GetPixelRowSpan(y - bounds.Top); + sourceRow.Slice(0, bounds.Width).CopyTo(targetRow); } }); } diff --git a/src/ImageSharp/Processing/Processors/Transforms/EntropyCropProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/EntropyCropProcessor{TPixel}.cs index b74fbb0ab..2b900ee36 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/EntropyCropProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/EntropyCropProcessor{TPixel}.cs @@ -42,16 +42,16 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms Configuration configuration = this.Source.GetConfiguration(); // Detect the edges. - new SobelProcessor(false).Apply(temp, this.SourceRectangle); + new SobelProcessor(false).Execute(temp, this.SourceRectangle); // Apply threshold binarization filter. - new BinaryThresholdProcessor(this.definition.Threshold).Apply(temp, this.SourceRectangle); + new BinaryThresholdProcessor(this.definition.Threshold).Execute(temp, this.SourceRectangle); // Search for the first white pixels rectangle = ImageMaths.GetFilteredBoundingRectangle(temp.Frames.RootFrame, 0); } - new CropProcessor(rectangle, this.Source.Size()).Apply(this.Source, this.SourceRectangle); + new CropProcessor(rectangle, this.Source.Size()).Execute(this.Source, this.SourceRectangle); base.BeforeImageApply(); } diff --git a/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor.cs index babdee593..d91db9a72 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor.cs @@ -41,7 +41,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms public Size TargetDimensions { get; } /// - public override ICloningImageProcessor CreatePixelSpecificProcessor(Image source, Rectangle sourceRectangle) + public override ICloningImageProcessor CreatePixelSpecificCloningProcessor(Image source, Rectangle sourceRectangle) => new ProjectiveTransformProcessor(this, source, sourceRectangle); } } diff --git a/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor{TPixel}.cs index 29dc8a070..68bfd817e 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor{TPixel}.cs @@ -2,8 +2,6 @@ // Licensed under the Apache License, Version 2.0. using System; -using System.Collections.Generic; -using System.Linq; using System.Numerics; using SixLabors.ImageSharp.Advanced; @@ -20,7 +18,9 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms internal class ProjectiveTransformProcessor : TransformProcessor where TPixel : struct, IPixel { - private readonly ProjectiveTransformProcessor definition; + private Size targetSize; + private readonly IResampler resampler; + private Matrix4x4 transformMatrix; /// /// Initializes a new instance of the class. @@ -31,52 +31,37 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms public ProjectiveTransformProcessor(ProjectiveTransformProcessor definition, Image source, Rectangle sourceRectangle) : base(source, sourceRectangle) { - this.definition = definition; + this.targetSize = definition.TargetDimensions; + this.transformMatrix = definition.TransformMatrix; + this.resampler = definition.Sampler; } - private Size TargetDimensions => this.definition.TargetDimensions; - - /// - protected override Image CreateDestination() - { - // We will always be creating the clone even for mutate because we may need to resize the canvas - IEnumerable> frames = this.Source.Frames.Select, ImageFrame>( - x => new ImageFrame( - this.Source.GetConfiguration(), - this.TargetDimensions.Width, - this.TargetDimensions.Height, - x.Metadata.DeepClone())); - - // Use the overload to prevent an extra frame being added - return new Image(this.Source.GetConfiguration(), this.Source.Metadata.DeepClone(), frames); - } + protected override Size GetTargetSize() => this.targetSize; /// protected override void OnFrameApply(ImageFrame source, ImageFrame destination) { - Matrix4x4 transformMatrix = this.definition.TransformMatrix; - // Handle transforms that result in output identical to the original. - if (transformMatrix.Equals(default) || transformMatrix.Equals(Matrix4x4.Identity)) + if (this.transformMatrix.Equals(default) || this.transformMatrix.Equals(Matrix4x4.Identity)) { // The clone will be blank here copy all the pixel data over source.GetPixelSpan().CopyTo(destination.GetPixelSpan()); return; } - int width = this.TargetDimensions.Width; - var targetBounds = new Rectangle(Point.Empty, this.TargetDimensions); + int width = this.targetSize.Width; + Rectangle sourceBounds = this.SourceRectangle; + var targetBounds = new Rectangle(Point.Empty, this.targetSize); + Configuration configuration = this.Configuration; // Convert from screen to world space. - Matrix4x4.Invert(transformMatrix, out Matrix4x4 matrix); - - IResampler sampler = this.definition.Sampler; + Matrix4x4.Invert(this.transformMatrix, out Matrix4x4 matrix); - if (sampler is NearestNeighborResampler) + if (this.resampler is NearestNeighborResampler) { ParallelHelper.IterateRows( targetBounds, - this.Configuration, + configuration, rows => { for (int y = rows.Min; y < rows.Max; y++) @@ -89,7 +74,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms int px = (int)MathF.Round(point.X); int py = (int)MathF.Round(point.Y); - if (this.SourceRectangle.Contains(px, py)) + if (sourceBounds.Contains(px, py)) { destRow[x] = source[px, py]; } @@ -100,19 +85,20 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms return; } - var kernel = new TransformKernelMap(this.Configuration, source.Size(), destination.Size(), sampler); + var kernel = new TransformKernelMap(configuration, source.Size(), destination.Size(), this.resampler); + try { ParallelHelper.IterateRowsWithTempBuffer( targetBounds, - this.Configuration, + configuration, (rows, vectorBuffer) => { Span vectorSpan = vectorBuffer.Span; for (int y = rows.Min; y < rows.Max; y++) { Span targetRowSpan = destination.GetPixelRowSpan(y); - PixelOperations.Instance.ToVector4(this.Configuration, targetRowSpan, vectorSpan); + PixelOperations.Instance.ToVector4(configuration, targetRowSpan, vectorSpan); ref float ySpanRef = ref kernel.GetYStartReference(y); ref float xSpanRef = ref kernel.GetXStartReference(y); @@ -131,7 +117,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms } PixelOperations.Instance.FromVector4Destructive( - this.Configuration, + configuration, vectorSpan, targetRowSpan); } diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs index 5390fa4a4..ccaa1ef9e 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs @@ -55,7 +55,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms public bool Compand { get; } /// - public override ICloningImageProcessor CreatePixelSpecificProcessor(Image source, Rectangle sourceRectangle) + public override ICloningImageProcessor CreatePixelSpecificCloningProcessor(Image source, Rectangle sourceRectangle) => new ResizeProcessor(this, source, sourceRectangle); } } diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor{TPixel}.cs index b85983a48..78e471ad6 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor{TPixel}.cs @@ -2,8 +2,6 @@ // Licensed under the Apache License, Version 2.0. using System; -using System.Collections.Generic; -using System.Linq; using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Memory; @@ -24,74 +22,34 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms internal class ResizeProcessor : TransformProcessor where TPixel : struct, IPixel { - private readonly ResizeProcessor parameterSource; private bool isDisposed; + private readonly int targetWidth; + private readonly int targetHeight; + private readonly IResampler resampler; + private Rectangle targetRectangle; + private readonly bool compand; // The following fields are not immutable but are optionally created on demand. private ResizeKernelMap horizontalKernelMap; private ResizeKernelMap verticalKernelMap; - public ResizeProcessor(ResizeProcessor parameterSource, Image source, Rectangle sourceRectangle) + public ResizeProcessor(ResizeProcessor definition, Image source, Rectangle sourceRectangle) : base(source, sourceRectangle) { - this.parameterSource = parameterSource; + this.targetWidth = definition.TargetWidth; + this.targetHeight = definition.TargetHeight; + this.targetRectangle = definition.TargetRectangle; + this.resampler = definition.Sampler; + this.compand = definition.Compand; } - /// - /// Gets the sampler to perform the resize operation. - /// - public IResampler Sampler => this.parameterSource.Sampler; - - /// - /// Gets the target width. - /// - public int TargetWidth => this.parameterSource.TargetWidth; - - /// - /// Gets the target height. - /// - public int TargetHeight => this.parameterSource.TargetHeight; - - /// - /// Gets the target resize rectangle. - /// - public Rectangle TargetRectangle => this.parameterSource.TargetRectangle; - - /// - /// Gets a value indicating whether to compress or expand individual pixel color values on processing. - /// - public bool Compand => this.parameterSource.Compand; - - /// - /// This is a shim for tagging the CreateDestination virtual generic method for the AoT iOS compiler. - /// This method should never be referenced outside of the AotCompiler code. - /// - /// The result returned from . - internal Image AotCreateDestination() - => this.CreateDestination(); - /// - protected override Image CreateDestination() - { - Image source = this.Source; - Configuration configuration = this.Configuration; - - // We will always be creating the clone even for mutate because we may need to resize the canvas - IEnumerable> frames = source.Frames.Select, ImageFrame>( - x => new ImageFrame( - configuration, - this.TargetWidth, - this.TargetHeight, - x.Metadata.DeepClone())); - - // Use the overload to prevent an extra frame being added - return new Image(configuration, source.Metadata.DeepClone(), frames); - } + protected override Size GetTargetSize() => new Size(this.targetWidth, this.targetHeight); /// protected override void BeforeImageApply(Image destination) { - if (!(this.Sampler is NearestNeighborResampler)) + if (!(this.resampler is NearestNeighborResampler)) { Image source = this.Source; Rectangle sourceRectangle = this.SourceRectangle; @@ -99,14 +57,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms // Since all image frame dimensions have to be the same we can calculate this for all frames. MemoryAllocator memoryAllocator = source.GetMemoryAllocator(); this.horizontalKernelMap = ResizeKernelMap.Calculate( - this.Sampler, - this.TargetRectangle.Width, + this.resampler, + this.targetRectangle.Width, sourceRectangle.Width, memoryAllocator); this.verticalKernelMap = ResizeKernelMap.Calculate( - this.Sampler, - this.TargetRectangle.Height, + this.resampler, + this.targetRectangle.Height, sourceRectangle.Height, memoryAllocator); } @@ -121,29 +79,29 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms Configuration configuration = this.Configuration; // Handle resize dimensions identical to the original - if (source.Width == destination.Width && source.Height == destination.Height && sourceRectangle == this.TargetRectangle) + if (source.Width == destination.Width && source.Height == destination.Height && sourceRectangle == this.targetRectangle) { // The cloned will be blank here copy all the pixel data over source.GetPixelSpan().CopyTo(destination.GetPixelSpan()); return; } - int width = this.TargetWidth; - int height = this.TargetHeight; + int width = this.targetWidth; + int height = this.targetHeight; int sourceX = sourceRectangle.X; int sourceY = sourceRectangle.Y; - int startY = this.TargetRectangle.Y; - int startX = this.TargetRectangle.X; + int startY = this.targetRectangle.Y; + int startX = this.targetRectangle.X; var targetWorkingRect = Rectangle.Intersect( - this.TargetRectangle, + this.targetRectangle, new Rectangle(0, 0, width, height)); - if (this.Sampler is NearestNeighborResampler) + if (this.resampler is NearestNeighborResampler) { // Scaling factors - float widthFactor = sourceRectangle.Width / (float)this.TargetRectangle.Width; - float heightFactor = sourceRectangle.Height / (float)this.TargetRectangle.Height; + float widthFactor = sourceRectangle.Width / (float)this.targetRectangle.Width; + float heightFactor = sourceRectangle.Height / (float)this.targetRectangle.Height; ParallelHelper.IterateRows( targetWorkingRect, @@ -153,8 +111,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms for (int y = rows.Min; y < rows.Max; y++) { // Y coordinates of source points - Span sourceRow = - source.GetPixelRowSpan((int)(((y - startY) * heightFactor) + sourceY)); + Span sourceRow = source.GetPixelRowSpan((int)(((y - startY) * heightFactor) + sourceY)); Span targetRow = destination.GetPixelRowSpan(y); for (int x = targetWorkingRect.Left; x < targetWorkingRect.Right; x++) @@ -169,7 +126,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms } PixelConversionModifiers conversionModifiers = - PixelConversionModifiers.Premultiply.ApplyCompanding(this.Compand); + PixelConversionModifiers.Premultiply.ApplyCompanding(this.compand); BufferArea sourceArea = source.PixelBuffer.GetArea(sourceRectangle); @@ -183,7 +140,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms this.verticalKernelMap, width, targetWorkingRect, - this.TargetRectangle.Location)) + this.targetRectangle.Location)) { worker.Initialize(); diff --git a/src/ImageSharp/Processing/Processors/Transforms/RotateProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/RotateProcessor.cs index 277cc05b2..7d6ec0e08 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/RotateProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/RotateProcessor.cs @@ -46,7 +46,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms public float Degrees { get; } /// - public override ICloningImageProcessor CreatePixelSpecificProcessor(Image source, Rectangle sourceRectangle) + public override ICloningImageProcessor CreatePixelSpecificCloningProcessor(Image source, Rectangle sourceRectangle) => new RotateProcessor(this, source, sourceRectangle); } } diff --git a/tests/ImageSharp.Tests/Drawing/FillRegionProcessorTests.cs b/tests/ImageSharp.Tests/Drawing/FillRegionProcessorTests.cs index 972f5cf4a..c0388ea2d 100644 --- a/tests/ImageSharp.Tests/Drawing/FillRegionProcessorTests.cs +++ b/tests/ImageSharp.Tests/Drawing/FillRegionProcessorTests.cs @@ -41,7 +41,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing }; var processor = new FillRegionProcessor(brush.Object, region, options); var img = new Image(1, 1); - processor.Apply(img, bounds); + processor.Execute(img, bounds); Assert.Equal(4, region.ScanInvocationCounter); } @@ -54,7 +54,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing var options = new GraphicsOptions(true); var processor = new FillRegionProcessor(brush.Object, new MockRegion1(), options); var img = new Image(10, 10); - processor.Apply(img, bounds); + processor.Execute(img, bounds); } [Fact] diff --git a/tests/ImageSharp.Tests/Processing/ImageProcessingContextTests.cs b/tests/ImageSharp.Tests/Processing/ImageProcessingContextTests.cs index afb2cbecd..9d16583cd 100644 --- a/tests/ImageSharp.Tests/Processing/ImageProcessingContextTests.cs +++ b/tests/ImageSharp.Tests/Processing/ImageProcessingContextTests.cs @@ -2,12 +2,10 @@ // Licensed under the Apache License, Version 2.0. using Moq; - using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Processing.Processors; using SixLabors.Primitives; - using Xunit; namespace SixLabors.ImageSharp.Tests.Processing @@ -21,7 +19,7 @@ namespace SixLabors.ImageSharp.Tests.Processing private readonly Mock processorDefinition; - private readonly Mock cloningProcessorDefinition; + private readonly Mock cloningProcessorDefinition; private readonly Mock> regularProcessorImpl; @@ -32,7 +30,7 @@ namespace SixLabors.ImageSharp.Tests.Processing public ImageProcessingContextTests() { this.processorDefinition = new Mock(); - this.cloningProcessorDefinition = new Mock(); + this.cloningProcessorDefinition = new Mock(); this.regularProcessorImpl = new Mock>(); this.cloningProcessorImpl = new Mock>(); } @@ -54,11 +52,11 @@ namespace SixLabors.ImageSharp.Tests.Processing if (throwException) { - Assert.Throws(() => this.MutateApply(useBounds)); + Assert.Throws(() => this.MutateRegularApply(useBounds)); } else { - this.MutateApply(useBounds); + this.MutateRegularApply(useBounds); } this.regularProcessorImpl.Verify(p => p.Execute(), Times.Once()); @@ -92,11 +90,11 @@ namespace SixLabors.ImageSharp.Tests.Processing if (throwException) { - Assert.Throws(() => this.MutateApply(useBounds)); + Assert.Throws(() => this.MutateCloneApply(useBounds)); } else { - this.MutateApply(useBounds); + this.MutateCloneApply(useBounds); } this.cloningProcessorImpl.Verify(p => p.Execute(), Times.Once()); @@ -122,7 +120,7 @@ namespace SixLabors.ImageSharp.Tests.Processing this.cloningProcessorImpl.Verify(p => p.Dispose(), Times.Once()); } - private void MutateApply(bool useBounds) + private void MutateRegularApply(bool useBounds) { if (useBounds) { @@ -134,6 +132,18 @@ namespace SixLabors.ImageSharp.Tests.Processing } } + private void MutateCloneApply(bool useBounds) + { + if (useBounds) + { + this.image.Mutate(c => c.ApplyProcessor(this.cloningProcessorDefinition.Object, Bounds)); + } + else + { + this.image.Mutate(c => c.ApplyProcessor(this.cloningProcessorDefinition.Object)); + } + } + private void CloneRegularApply(bool useBounds) { if (useBounds) @@ -178,8 +188,8 @@ namespace SixLabors.ImageSharp.Tests.Processing this.cloningProcessorImpl.Setup(p => p.CloneAndExecute()).Throws(new ImageProcessingException("Test")); } - this.processorDefinition - .Setup(p => p.CreatePixelSpecificProcessor(It.IsAny>(), It.IsAny())) + this.cloningProcessorDefinition + .Setup(p => p.CreatePixelSpecificCloningProcessor(It.IsAny>(), It.IsAny())) .Returns(this.cloningProcessorImpl.Object); this.cloningProcessorDefinition