diff --git a/src/ImageProcessorCore/Filters/Binarization/Threshold.cs b/src/ImageProcessorCore/Filters/Binarization/Threshold.cs index 250cdc140..6c71834d5 100644 --- a/src/ImageProcessorCore/Filters/Binarization/Threshold.cs +++ b/src/ImageProcessorCore/Filters/Binarization/Threshold.cs @@ -6,7 +6,6 @@ namespace ImageProcessorCore.Filters { using System; - using System.Numerics; using System.Threading.Tasks; /// diff --git a/src/ImageProcessorCore/ImageExtensions.cs b/src/ImageProcessorCore/ImageExtensions.cs index f194b54c3..7379f20c8 100644 --- a/src/ImageProcessorCore/ImageExtensions.cs +++ b/src/ImageProcessorCore/ImageExtensions.cs @@ -9,7 +9,6 @@ namespace ImageProcessorCore using System.IO; using Formats; - using Processors; /// /// Extension methods for the type. diff --git a/src/ImageProcessorCore/Samplers/Crop.cs b/src/ImageProcessorCore/Samplers/Crop.cs index 6347d8e98..23f4d18f5 100644 --- a/src/ImageProcessorCore/Samplers/Crop.cs +++ b/src/ImageProcessorCore/Samplers/Crop.cs @@ -5,8 +5,6 @@ namespace ImageProcessorCore { - using Processors; - /// /// Extension methods for the type. /// @@ -52,7 +50,7 @@ namespace ImageProcessorCore source = source.Resize(sourceRectangle.Width, sourceRectangle.Height); } - Crop processor = new Crop(); + CropProcessor processor = new CropProcessor(); processor.OnProgress += progressHandler; try diff --git a/src/ImageProcessorCore/Samplers/EntropyCrop.cs b/src/ImageProcessorCore/Samplers/EntropyCrop.cs index 9e96d5b3e..8a6cafc75 100644 --- a/src/ImageProcessorCore/Samplers/EntropyCrop.cs +++ b/src/ImageProcessorCore/Samplers/EntropyCrop.cs @@ -5,8 +5,6 @@ namespace ImageProcessorCore { - using Processors; - /// /// Extension methods for the type. /// @@ -21,7 +19,7 @@ namespace ImageProcessorCore /// The public static Image EntropyCrop(this Image source, float threshold = .5f, ProgressEventHandler progressHandler = null) { - EntropyCrop processor = new EntropyCrop(threshold); + EntropyCropProcessor processor = new EntropyCropProcessor(threshold); processor.OnProgress += progressHandler; try diff --git a/src/ImageProcessorCore/Samplers/Pad.cs b/src/ImageProcessorCore/Samplers/Pad.cs index de973d345..fcdac9200 100644 --- a/src/ImageProcessorCore/Samplers/Pad.cs +++ b/src/ImageProcessorCore/Samplers/Pad.cs @@ -5,8 +5,6 @@ namespace ImageProcessorCore { - using Processors; - /// /// Extension methods for the type. /// diff --git a/src/ImageProcessorCore/Samplers/Processors/Crop.cs b/src/ImageProcessorCore/Samplers/Processors/CropProcessor.cs similarity index 88% rename from src/ImageProcessorCore/Samplers/Processors/Crop.cs rename to src/ImageProcessorCore/Samplers/Processors/CropProcessor.cs index 0fdef35fc..d6347ea8a 100644 --- a/src/ImageProcessorCore/Samplers/Processors/Crop.cs +++ b/src/ImageProcessorCore/Samplers/Processors/CropProcessor.cs @@ -1,16 +1,16 @@ -// +// // Copyright (c) James Jackson-South and contributors. // Licensed under the Apache License, Version 2.0. // -namespace ImageProcessorCore.Processors +namespace ImageProcessorCore { using System.Threading.Tasks; /// /// Provides methods to allow the cropping of an image. /// - public class Crop : ImageSampler + public class CropProcessor : ImageSampler { /// protected override void Apply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY) diff --git a/src/ImageProcessorCore/Samplers/Processors/EntropyCrop.cs b/src/ImageProcessorCore/Samplers/Processors/EntropyCropProcessor.cs similarity index 93% rename from src/ImageProcessorCore/Samplers/Processors/EntropyCrop.cs rename to src/ImageProcessorCore/Samplers/Processors/EntropyCropProcessor.cs index ef9bd5b23..697148f09 100644 --- a/src/ImageProcessorCore/Samplers/Processors/EntropyCrop.cs +++ b/src/ImageProcessorCore/Samplers/Processors/EntropyCropProcessor.cs @@ -1,9 +1,9 @@ -// +// // Copyright (c) James Jackson-South and contributors. // Licensed under the Apache License, Version 2.0. // -namespace ImageProcessorCore.Processors +namespace ImageProcessorCore { using System; using System.Threading.Tasks; @@ -14,7 +14,7 @@ namespace ImageProcessorCore.Processors /// Provides methods to allow the cropping of an image to preserve areas of highest /// entropy. /// - public class EntropyCrop : ImageSampler + public class EntropyCropProcessor : ImageSampler { /// /// The rectangle for cropping @@ -22,13 +22,13 @@ namespace ImageProcessorCore.Processors private Rectangle cropRectangle; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The threshold to split the image. Must be between 0 and 1. /// /// is less than 0 or is greater than 1. /// - public EntropyCrop(float threshold) + public EntropyCropProcessor(float threshold) { Guard.MustBeBetweenOrEqualTo(threshold, 0, 1, nameof(threshold)); this.Value = threshold; diff --git a/src/ImageProcessorCore/Samplers/Processors/IImageSampler.cs b/src/ImageProcessorCore/Samplers/Processors/IImageSampler.cs index 76a2c5a4d..69e017c52 100644 --- a/src/ImageProcessorCore/Samplers/Processors/IImageSampler.cs +++ b/src/ImageProcessorCore/Samplers/Processors/IImageSampler.cs @@ -3,7 +3,7 @@ // Licensed under the Apache License, Version 2.0. // -namespace ImageProcessorCore.Processors +namespace ImageProcessorCore { /// /// Acts as a marker for generic parameters that require an image sampler. diff --git a/src/ImageProcessorCore/Samplers/Processors/ImageSampler.cs b/src/ImageProcessorCore/Samplers/Processors/ImageSampler.cs index cc8bfe4cc..ee1a7dd7e 100644 --- a/src/ImageProcessorCore/Samplers/Processors/ImageSampler.cs +++ b/src/ImageProcessorCore/Samplers/Processors/ImageSampler.cs @@ -3,7 +3,7 @@ // Licensed under the Apache License, Version 2.0. // -namespace ImageProcessorCore.Processors +namespace ImageProcessorCore { /// /// Applies sampling methods to an image. diff --git a/src/ImageProcessorCore/Samplers/Processors/Resampler.cs b/src/ImageProcessorCore/Samplers/Processors/Resampler.cs deleted file mode 100644 index 283d64cfa..000000000 --- a/src/ImageProcessorCore/Samplers/Processors/Resampler.cs +++ /dev/null @@ -1,186 +0,0 @@ -// -// Copyright (c) James Jackson-South and contributors. -// Licensed under the Apache License, Version 2.0. -// -namespace ImageProcessorCore.Processors -{ - using System; - - /// - /// Provides methods that allow the resampling of images using various algorithms. - /// - /// - /// - public abstract class Resampler : ImageSampler - { - /// - /// Initializes a new instance of the class. - /// - /// - /// The sampler to perform the resize operation. - /// - protected Resampler(IResampler sampler) - { - Guard.NotNull(sampler, nameof(sampler)); - - this.Sampler = sampler; - } - - /// - /// Gets the sampler to perform the resize operation. - /// - public IResampler Sampler { get; } - - /// - /// Gets or sets the horizontal weights. - /// - protected Weights[] HorizontalWeights { get; set; } - - /// - /// Gets or sets the vertical weights. - /// - protected Weights[] VerticalWeights { get; set; } - - /// - /// Computes the weights to apply at each pixel when resizing. - /// - /// The destination section size. - /// The source section size. - /// - /// The . - /// - protected Weights[] PrecomputeWeights(int destinationSize, int sourceSize) - { - float scale = (float)destinationSize / sourceSize; - IResampler sampler = this.Sampler; - float radius = sampler.Radius; - double left; - double right; - float weight; - int index; - int sum; - - Weights[] result = new Weights[destinationSize]; - - // When shrinking, broaden the effective kernel support so that we still - // visit every source pixel. - if (scale < 1) - { - float width = radius / scale; - float filterScale = 1 / scale; - - // Make the weights slices, one source for each column or row. - for (int i = 0; i < destinationSize; i++) - { - float centre = i / scale; - left = Math.Ceiling(centre - width); - right = Math.Floor(centre + width); - - result[i] = new Weights - { - Values = new Weight[(int)(right - left + 1)] - }; - - for (double j = left; j <= right; j++) - { - weight = sampler.GetValue((float)((centre - j) / filterScale)) / filterScale; - if (j < 0) - { - index = (int)-j; - } - else if (j >= sourceSize) - { - index = (int)((sourceSize - j) + sourceSize - 1); - } - else - { - index = (int)j; - } - - sum = (int)result[i].Sum++; - result[i].Values[sum] = new Weight(index, weight); - } - } - } - else - { - // Make the weights slices, one source for each column or row. - for (int i = 0; i < destinationSize; i++) - { - float centre = i / scale; - left = Math.Ceiling(centre - radius); - right = Math.Floor(centre + radius); - result[i] = new Weights - { - Values = new Weight[(int)(right - left + 1)] - }; - - for (double j = left; j <= right; j++) - { - weight = sampler.GetValue((float)(centre - j)); - if (j < 0) - { - index = (int)-j; - } - else if (j >= sourceSize) - { - index = (int)((sourceSize - j) + sourceSize - 1); - } - else - { - index = (int)j; - } - - sum = (int)result[i].Sum++; - result[i].Values[sum] = new Weight(index, weight); - } - } - } - - return result; - } - - /// - /// Represents the weight to be added to a scaled pixel. - /// - protected struct Weight - { - /// - /// Initializes a new instance of the struct. - /// - /// The index. - /// The value. - public Weight(int index, float value) - { - this.Index = index; - this.Value = value; - } - - /// - /// Gets the pixel index. - /// - public int Index { get; } - - /// - /// Gets the result of the interpolation algorithm. - /// - public float Value { get; } - } - - /// - /// Represents a collection of weights and their sum. - /// - protected class Weights - { - /// - /// Gets or sets the values. - /// - public Weight[] Values { get; set; } - - /// - /// Gets or sets the sum. - /// - public float Sum { get; set; } - } - } -} \ No newline at end of file diff --git a/src/ImageProcessorCore/Samplers/Processors/Resize.cs b/src/ImageProcessorCore/Samplers/Processors/ResizeProcessor.cs similarity index 56% rename from src/ImageProcessorCore/Samplers/Processors/Resize.cs rename to src/ImageProcessorCore/Samplers/Processors/ResizeProcessor.cs index 3ca754ee6..e72e303e6 100644 --- a/src/ImageProcessorCore/Samplers/Processors/Resize.cs +++ b/src/ImageProcessorCore/Samplers/Processors/ResizeProcessor.cs @@ -1,16 +1,17 @@ -// +// // Copyright (c) James Jackson-South and contributors. // Licensed under the Apache License, Version 2.0. // -namespace ImageProcessorCore.Processors +namespace ImageProcessorCore { + using System; using System.Threading.Tasks; /// /// Provides methods that allow the resizing of images using various algorithms. /// - public class Resize : Resampler + public class ResizeProcessor : ImageSampler { /// /// The image used for storing the first pass pixels. @@ -18,19 +19,36 @@ namespace ImageProcessorCore.Processors private Image firstPass; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// /// The sampler to perform the resize operation. /// - public Resize(IResampler sampler) - : base(sampler) + public ResizeProcessor(IResampler sampler) { + Guard.NotNull(sampler, nameof(sampler)); + + this.Sampler = sampler; } /// public override int Parallelism { get; set; } = 1; + /// + /// Gets the sampler to perform the resize operation. + /// + public IResampler Sampler { get; } + + /// + /// Gets or sets the horizontal weights. + /// + protected Weights[] HorizontalWeights { get; set; } + + /// + /// Gets or sets the vertical weights. + /// + protected Weights[] VerticalWeights { get; set; } + /// protected override void OnApply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle) { @@ -188,5 +206,147 @@ namespace ImageProcessorCore.Processors // Clean up this.firstPass?.Dispose(); } + + /// + /// Computes the weights to apply at each pixel when resizing. + /// + /// The destination section size. + /// The source section size. + /// + /// The . + /// + protected Weights[] PrecomputeWeights(int destinationSize, int sourceSize) + { + float scale = (float)destinationSize / sourceSize; + IResampler sampler = this.Sampler; + float radius = sampler.Radius; + double left; + double right; + float weight; + int index; + int sum; + + Weights[] result = new Weights[destinationSize]; + + // When shrinking, broaden the effective kernel support so that we still + // visit every source pixel. + if (scale < 1) + { + float width = radius / scale; + float filterScale = 1 / scale; + + // Make the weights slices, one source for each column or row. + for (int i = 0; i < destinationSize; i++) + { + float centre = i / scale; + left = Math.Ceiling(centre - width); + right = Math.Floor(centre + width); + + result[i] = new Weights + { + Values = new Weight[(int)(right - left + 1)] + }; + + for (double j = left; j <= right; j++) + { + weight = sampler.GetValue((float)((centre - j) / filterScale)) / filterScale; + if (j < 0) + { + index = (int)-j; + } + else if (j >= sourceSize) + { + index = (int)((sourceSize - j) + sourceSize - 1); + } + else + { + index = (int)j; + } + + sum = (int)result[i].Sum++; + result[i].Values[sum] = new Weight(index, weight); + } + } + } + else + { + // Make the weights slices, one source for each column or row. + for (int i = 0; i < destinationSize; i++) + { + float centre = i / scale; + left = Math.Ceiling(centre - radius); + right = Math.Floor(centre + radius); + result[i] = new Weights + { + Values = new Weight[(int)(right - left + 1)] + }; + + for (double j = left; j <= right; j++) + { + weight = sampler.GetValue((float)(centre - j)); + if (j < 0) + { + index = (int)-j; + } + else if (j >= sourceSize) + { + index = (int)((sourceSize - j) + sourceSize - 1); + } + else + { + index = (int)j; + } + + sum = (int)result[i].Sum++; + result[i].Values[sum] = new Weight(index, weight); + } + } + } + + return result; + } + + /// + /// Represents the weight to be added to a scaled pixel. + /// + protected struct Weight + { + /// + /// Initializes a new instance of the struct. + /// + /// The index. + /// The value. + public Weight(int index, float value) + { + this.Index = index; + this.Value = value; + } + + /// + /// Gets the pixel index. + /// + public int Index { get; } + + /// + /// Gets the result of the interpolation algorithm. + /// + public float Value { get; } + } + + /// + /// Represents a collection of weights and their sum. + /// + protected class Weights + { + /// + /// Gets or sets the values. + /// + public Weight[] Values { get; set; } + + /// + /// Gets or sets the sum. + /// + public float Sum { get; set; } + } } } \ No newline at end of file diff --git a/src/ImageProcessorCore/Samplers/Processors/RotateFlip.cs b/src/ImageProcessorCore/Samplers/Processors/RotateFlip.cs index dfcc3e69e..d732a8bb1 100644 --- a/src/ImageProcessorCore/Samplers/Processors/RotateFlip.cs +++ b/src/ImageProcessorCore/Samplers/Processors/RotateFlip.cs @@ -1,8 +1,8 @@ -// +// // Copyright (c) James Jackson-South and contributors. // Licensed under the Apache License, Version 2.0. // -namespace ImageProcessorCore.Processors +namespace ImageProcessorCore { using System; using System.Threading.Tasks; @@ -10,14 +10,14 @@ namespace ImageProcessorCore.Processors /// /// Provides methods that allow the rotation and flipping of an image around its center point. /// - public class RotateFlip : ImageSampler + public class RotateFlipProcessor : ImageSampler { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The used to perform rotation. /// The used to perform flipping. - public RotateFlip(RotateType rotateType, FlipType flipType) + public RotateFlipProcessor(RotateType rotateType, FlipType flipType) { this.RotateType = rotateType; this.FlipType = flipType; diff --git a/src/ImageProcessorCore/Samplers/Processors/Rotate.cs b/src/ImageProcessorCore/Samplers/Processors/RotateProcessor.cs similarity index 93% rename from src/ImageProcessorCore/Samplers/Processors/Rotate.cs rename to src/ImageProcessorCore/Samplers/Processors/RotateProcessor.cs index 2d46dee06..33c31bf9c 100644 --- a/src/ImageProcessorCore/Samplers/Processors/Rotate.cs +++ b/src/ImageProcessorCore/Samplers/Processors/RotateProcessor.cs @@ -1,9 +1,9 @@ -// +// // Copyright (c) James Jackson-South and contributors. // Licensed under the Apache License, Version 2.0. // -namespace ImageProcessorCore.Processors +namespace ImageProcessorCore { using System.Numerics; using System.Threading.Tasks; @@ -11,7 +11,7 @@ namespace ImageProcessorCore.Processors /// /// Provides methods that allow the rotating of images. /// - public class Rotate : ImageSampler + public class RotateProcessor : ImageSampler { /// /// The image used for storing the first pass pixels. @@ -83,7 +83,7 @@ namespace ImageProcessorCore.Processors Rectangle bounds = ResizeHelper.CalculateTargetLocationAndBounds(source, options); this.firstPass = new Image(rectangle.Width, rectangle.Height); target.SetPixels(rectangle.Width, rectangle.Height, new float[rectangle.Width * rectangle.Height * 4]); - new Resize(new NearestNeighborResampler()).Apply(this.firstPass, source, rectangle.Width, rectangle.Height, bounds, sourceRectangle); + new ResizeProcessor(new NearestNeighborResampler()).Apply(this.firstPass, source, rectangle.Width, rectangle.Height, bounds, sourceRectangle); } else { diff --git a/src/ImageProcessorCore/Samplers/Processors/Skew.cs b/src/ImageProcessorCore/Samplers/Processors/SkewProcessor.cs similarity index 94% rename from src/ImageProcessorCore/Samplers/Processors/Skew.cs rename to src/ImageProcessorCore/Samplers/Processors/SkewProcessor.cs index 89f050630..1bfcfb7e2 100644 --- a/src/ImageProcessorCore/Samplers/Processors/Skew.cs +++ b/src/ImageProcessorCore/Samplers/Processors/SkewProcessor.cs @@ -1,9 +1,9 @@ -// +// // Copyright (c) James Jackson-South and contributors. // Licensed under the Apache License, Version 2.0. // -namespace ImageProcessorCore.Processors +namespace ImageProcessorCore { using System.Numerics; using System.Threading.Tasks; @@ -11,7 +11,7 @@ namespace ImageProcessorCore.Processors /// /// Provides methods that allow the skewing of images. /// - public class Skew : ImageSampler + public class SkewProcessor : ImageSampler { /// /// The image used for storing the first pass pixels. @@ -114,7 +114,7 @@ namespace ImageProcessorCore.Processors Rectangle bounds = ResizeHelper.CalculateTargetLocationAndBounds(source, options); this.firstPass = new Image(rectangle.Width, rectangle.Height); target.SetPixels(rectangle.Width, rectangle.Height, new float[rectangle.Width * rectangle.Height * 4]); - new Resize(new NearestNeighborResampler()).Apply(this.firstPass, source, rectangle.Width, rectangle.Height, bounds, sourceRectangle); + new ResizeProcessor(new NearestNeighborResampler()).Apply(this.firstPass, source, rectangle.Width, rectangle.Height, bounds, sourceRectangle); } else { diff --git a/src/ImageProcessorCore/Samplers/Resize.cs b/src/ImageProcessorCore/Samplers/Resize.cs index fbf86081a..a90c4c105 100644 --- a/src/ImageProcessorCore/Samplers/Resize.cs +++ b/src/ImageProcessorCore/Samplers/Resize.cs @@ -5,8 +5,6 @@ namespace ImageProcessorCore { - using Processors; - /// /// Extension methods for the type. /// @@ -118,7 +116,7 @@ namespace ImageProcessorCore Guard.MustBeGreaterThan(width, 0, nameof(width)); Guard.MustBeGreaterThan(height, 0, nameof(height)); - Resize processor = new Resize(sampler) { Compand = compand }; + ResizeProcessor processor = new ResizeProcessor(sampler) { Compand = compand }; processor.OnProgress += progressHandler; try diff --git a/src/ImageProcessorCore/Samplers/Rotate.cs b/src/ImageProcessorCore/Samplers/Rotate.cs index 3d338230f..49441fbb5 100644 --- a/src/ImageProcessorCore/Samplers/Rotate.cs +++ b/src/ImageProcessorCore/Samplers/Rotate.cs @@ -5,8 +5,6 @@ namespace ImageProcessorCore { - using Processors; - /// /// Extension methods for the type. /// @@ -35,7 +33,7 @@ namespace ImageProcessorCore /// The public static Image Rotate(this Image source, float degrees, Point center, bool expand, ProgressEventHandler progressHandler = null) { - Rotate processor = new Rotate { Angle = degrees, Center = center, Expand = expand }; + RotateProcessor processor = new RotateProcessor { Angle = degrees, Center = center, Expand = expand }; processor.OnProgress += progressHandler; try diff --git a/src/ImageProcessorCore/Samplers/RotateFlip.cs b/src/ImageProcessorCore/Samplers/RotateFlip.cs index a7051fec5..279bd274b 100644 --- a/src/ImageProcessorCore/Samplers/RotateFlip.cs +++ b/src/ImageProcessorCore/Samplers/RotateFlip.cs @@ -5,8 +5,6 @@ namespace ImageProcessorCore { - using Processors; - /// /// Extension methods for the type. /// @@ -22,7 +20,7 @@ namespace ImageProcessorCore /// The public static Image RotateFlip(this Image source, RotateType rotateType, FlipType flipType, ProgressEventHandler progressHandler = null) { - RotateFlip processor = new RotateFlip(rotateType, flipType); + RotateFlipProcessor processor = new RotateFlipProcessor(rotateType, flipType); processor.OnProgress += progressHandler; try diff --git a/src/ImageProcessorCore/Samplers/Skew.cs b/src/ImageProcessorCore/Samplers/Skew.cs index 5150bea89..7e9088ab9 100644 --- a/src/ImageProcessorCore/Samplers/Skew.cs +++ b/src/ImageProcessorCore/Samplers/Skew.cs @@ -5,8 +5,6 @@ namespace ImageProcessorCore { - using Processors; - /// /// Extension methods for the type. /// @@ -37,7 +35,7 @@ namespace ImageProcessorCore /// The public static Image Skew(this Image source, float degreesX, float degreesY, Point center, bool expand, ProgressEventHandler progressHandler = null) { - Skew processor = new Skew { AngleX = degreesX, AngleY = degreesY, Center = center, Expand = expand }; + SkewProcessor processor = new SkewProcessor { AngleX = degreesX, AngleY = degreesY, Center = center, Expand = expand }; processor.OnProgress += progressHandler; try diff --git a/tests/ImageProcessorCore.Tests/Processors/Samplers/SamplerTests.cs b/tests/ImageProcessorCore.Tests/Processors/Samplers/SamplerTests.cs index 33b006ebf..ac610746e 100644 --- a/tests/ImageProcessorCore.Tests/Processors/Samplers/SamplerTests.cs +++ b/tests/ImageProcessorCore.Tests/Processors/Samplers/SamplerTests.cs @@ -32,8 +32,8 @@ public static readonly TheoryData Samplers = new TheoryData { - { "Resize", new Resize(new BicubicResampler()) }, - { "Crop", new Crop() } + { "Resize", new ResizeProcessor(new BicubicResampler()) }, + { "Crop", new CropProcessor() } }; public static readonly TheoryData RotateFlips = new TheoryData