diff --git a/src/ImageSharp/Common/Helpers/ImageMaths.cs b/src/ImageSharp/Common/Helpers/ImageMaths.cs index fa60f855ee..74d705d53a 100644 --- a/src/ImageSharp/Common/Helpers/ImageMaths.cs +++ b/src/ImageSharp/Common/Helpers/ImageMaths.cs @@ -147,17 +147,26 @@ namespace SixLabors.ImageSharp /// /// The . /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Rectangle GetBoundingRectangle(Rectangle rectangle, Matrix3x2 matrix) { - var leftTop = Vector2.Transform(new Vector2(rectangle.Left, rectangle.Top), matrix); - var rightTop = Vector2.Transform(new Vector2(rectangle.Right, rectangle.Top), matrix); - var leftBottom = Vector2.Transform(new Vector2(rectangle.Left, rectangle.Bottom), matrix); - var rightBottom = Vector2.Transform(new Vector2(rectangle.Right, rectangle.Bottom), matrix); - - Vector2[] allCorners = { leftTop, rightTop, leftBottom, rightBottom }; - float extentX = allCorners.Select(v => v.X).Max() - allCorners.Select(v => v.X).Min(); - float extentY = allCorners.Select(v => v.Y).Max() - allCorners.Select(v => v.Y).Min(); - return new Rectangle(0, 0, (int)MathF.Ceiling(extentX), (int)MathF.Ceiling(extentY)); + // Calculate the position of the four corners in world space by applying + // The world matrix to the four corners in object space (0, 0, width, height) + var tl = Vector2.Transform(Vector2.Zero, matrix); + var tr = Vector2.Transform(new Vector2(rectangle.Width, 0), matrix); + var bl = Vector2.Transform(new Vector2(0, rectangle.Height), matrix); + var br = Vector2.Transform(new Vector2(rectangle.Width, rectangle.Height), matrix); + + // Find the minimum and maximum "corners" based on the ones above + float minX = MathF.Min(tl.X, MathF.Min(tr.X, MathF.Min(bl.X, br.X))); + float maxX = MathF.Max(tl.X, MathF.Max(tr.X, MathF.Max(bl.X, br.X))); + float minY = MathF.Min(tl.Y, MathF.Min(tr.Y, MathF.Min(bl.Y, br.Y))); + float maxY = MathF.Max(tl.Y, MathF.Max(tr.Y, MathF.Max(bl.Y, br.Y))); + var min = new Vector2(minX, minY); + var max = new Vector2(maxX, maxY); + Vector2 size = max - min; + + return new Rectangle((int)MathF.Floor(minX), (int)MathF.Floor(minY), (int)MathF.Ceiling(size.X), (int)MathF.Ceiling(size.Y)); } /// diff --git a/src/ImageSharp/Processing/Processors/Transforms/AffineProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/AffineProcessor.cs index 3dbcf796fc..843d07f4b5 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/AffineProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/AffineProcessor.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Numerics; using System.Threading.Tasks; @@ -18,52 +17,40 @@ namespace SixLabors.ImageSharp.Processing.Processors /// Provides the base methods to perform affine transforms on an image. /// /// The pixel format. - internal abstract class AffineProcessor : ResamplingWeightedProcessor + internal abstract class AffineProcessor : CloningImageProcessor where TPixel : struct, IPixel { + private Rectangle targetRectangle; + private Matrix3x2 transformMatrix; + /// /// Initializes a new instance of the class. /// /// The sampler to perform the resize operation. protected AffineProcessor(IResampler sampler) - : base(sampler, 1, 1, Rectangles.DefaultRectangle) // Hack to prevent Guard throwing in base, we always set the canvas { + this.Sampler = sampler; } /// - /// Gets or sets a value indicating whether to expand the canvas to fit the transformed image. + /// Gets the sampler to perform interpolation of the transform operation. /// - public bool Expand { get; set; } = true; + public IResampler Sampler { get; } /// /// Returns the processing matrix used for transforming the image. /// - /// The rectangle bounds /// The - protected abstract Matrix3x2 CreateProcessingMatrix(Rectangle rectangle); - - /// - /// Creates a new target canvas to contain the results of the matrix transform. - /// - /// The source rectangle. - protected virtual void CreateNewCanvas(Rectangle sourceRectangle) - { - this.ResizeRectangle = Matrix3x2.Invert(this.CreateProcessingMatrix(sourceRectangle), out Matrix3x2 sizeMatrix) - ? ImageMaths.GetBoundingRectangle(sourceRectangle, sizeMatrix) - : sourceRectangle; - - this.Width = this.ResizeRectangle.Width; - this.Height = this.ResizeRectangle.Height; - } + protected abstract Matrix3x2 GetTransformMatrix(); /// protected override Image CreateDestination(Image source, Rectangle sourceRectangle) { - this.CreateNewCanvas(sourceRectangle); + this.ResizeCanvas(sourceRectangle); // We will always be creating the clone even for mutate because we may need to resize the canvas IEnumerable> frames = - source.Frames.Select(x => new ImageFrame(this.ResizeRectangle.Width, this.ResizeRectangle.Height, x.MetaData.Clone())); + source.Frames.Select(x => new ImageFrame(this.targetRectangle.Width, this.targetRectangle.Height, x.MetaData.Clone())); // Use the overload to prevent an extra frame being added return new Image(source.GetConfiguration(), source.MetaData.Clone(), frames); @@ -72,9 +59,11 @@ namespace SixLabors.ImageSharp.Processing.Processors /// protected override void OnApply(ImageFrame source, ImageFrame destination, Rectangle sourceRectangle, Configuration configuration) { - int height = this.ResizeRectangle.Height; - int width = this.ResizeRectangle.Width; + int height = this.targetRectangle.Height; + int width = this.targetRectangle.Width; Rectangle sourceBounds = source.Bounds(); + + // Since could potentially be resizing the canvas we need to recenter the matrix Matrix3x2 matrix = this.GetCenteredMatrix(source); if (this.Sampler is NearestNeighborResampler) @@ -106,8 +95,7 @@ namespace SixLabors.ImageSharp.Processing.Processors (float radius, float scale) yRadiusScale = this.GetSamplingRadius(source.Height, destination.Height); float xScale = xRadiusScale.scale; float yScale = yRadiusScale.scale; - float xRadius = xRadiusScale.radius; - float yRadius = yRadiusScale.radius; + var radius = new Vector2(xRadiusScale.radius, yRadiusScale.radius); IResampler sampler = this.Sampler; var maxSource = new Vector4(maxSourceX, maxSourceY, maxSourceX, maxSourceY); @@ -125,11 +113,14 @@ namespace SixLabors.ImageSharp.Processing.Processors var point = Vector2.Transform(new Vector2(x, y), matrix); // Clamp sampling pixel radial extents to the source image edges + Vector2 maxXY = point + radius; + Vector2 minXY = point - radius; + var extents = new Vector4( - MathF.Ceiling(point.X + xRadius), - MathF.Ceiling(point.Y + yRadius), - MathF.Floor(point.X - xRadius), - MathF.Floor(point.Y - yRadius)); + MathF.Ceiling(maxXY.X), + MathF.Ceiling(maxXY.Y), + MathF.Floor(minXY.X), + MathF.Floor(minXY.Y)); extents = Vector4.Clamp(extents, Vector4.Zero, maxSource); @@ -172,9 +163,21 @@ namespace SixLabors.ImageSharp.Processing.Processors /// protected Matrix3x2 GetCenteredMatrix(ImageFrame source) { - var translationToTargetCenter = Matrix3x2.CreateTranslation(-this.ResizeRectangle.Width * .5F, -this.ResizeRectangle.Height * .5F); + var translationToTargetCenter = Matrix3x2.CreateTranslation(-this.targetRectangle.Width * .5F, -this.targetRectangle.Height * .5F); var translateToSourceCenter = Matrix3x2.CreateTranslation(source.Width * .5F, source.Height * .5F); - return (translationToTargetCenter * this.CreateProcessingMatrix(this.ResizeRectangle)) * translateToSourceCenter; + return translationToTargetCenter * this.transformMatrix * translateToSourceCenter; + } + + /// + /// Creates a new target canvas to contain the results of the matrix transform. + /// + /// The source rectangle. + private void ResizeCanvas(Rectangle sourceRectangle) + { + this.transformMatrix = this.GetTransformMatrix(); + this.targetRectangle = Matrix3x2.Invert(this.transformMatrix, out Matrix3x2 sizeMatrix) + ? ImageMaths.GetBoundingRectangle(sourceRectangle, sizeMatrix) + : sourceRectangle; } /// @@ -196,14 +199,4 @@ namespace SixLabors.ImageSharp.Processing.Processors return (MathF.Ceiling(scale * this.Sampler.Radius), scale); } } - - /// - /// Contains a static rectangle used for comparison when creating a new canvas. - /// We do this so we can inherit from the resampling weights class and pass the guard in the constructor and also avoid creating a new rectangle each time. - /// - [SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:FileMayOnlyContainASingleType", Justification = "I'm using this only here to prevent duplication in generic types.")] - internal static class Rectangles - { - public static Rectangle DefaultRectangle { get; } = new Rectangle(0, 0, 1, 1); - } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Transforms/AutoOrientProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/AutoOrientProcessor.cs index ab93e0e384..c39311bc33 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/AutoOrientProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/AutoOrientProcessor.cs @@ -15,13 +15,7 @@ namespace SixLabors.ImageSharp.Processing.Processors internal class AutoOrientProcessor : ImageProcessor where TPixel : struct, IPixel { - /// - /// Initializes a new instance of the class. - /// - public AutoOrientProcessor() - { - } - + /// protected override void BeforeImageApply(Image source, Rectangle sourceRectangle) { Orientation orientation = GetExifOrientation(source); @@ -33,7 +27,7 @@ namespace SixLabors.ImageSharp.Processing.Processors break; case Orientation.BottomRight: - new RotateProcessor() { Angle = (int)RotateType.Rotate180, Expand = false }.Apply(source, sourceRectangle); + new RotateProcessor((int)RotateType.Rotate180).Apply(source, sourceRectangle); break; case Orientation.BottomLeft: @@ -41,21 +35,21 @@ namespace SixLabors.ImageSharp.Processing.Processors break; case Orientation.LeftTop: - new RotateProcessor() { Angle = (int)RotateType.Rotate90, Expand = false }.Apply(source, sourceRectangle); + new RotateProcessor((int)RotateType.Rotate90).Apply(source, sourceRectangle); new FlipProcessor(FlipType.Horizontal).Apply(source, sourceRectangle); break; case Orientation.RightTop: - new RotateProcessor() { Angle = (int)RotateType.Rotate90, Expand = false }.Apply(source, sourceRectangle); + new RotateProcessor((int)RotateType.Rotate90).Apply(source, sourceRectangle); break; case Orientation.RightBottom: new FlipProcessor(FlipType.Vertical).Apply(source, sourceRectangle); - new RotateProcessor() { Angle = (int)RotateType.Rotate270, Expand = false }.Apply(source, sourceRectangle); + new RotateProcessor((int)RotateType.Rotate270).Apply(source, sourceRectangle); break; case Orientation.LeftBottom: - new RotateProcessor() { Angle = (int)RotateType.Rotate270, Expand = false }.Apply(source, sourceRectangle); + new RotateProcessor((int)RotateType.Rotate270).Apply(source, sourceRectangle); break; case Orientation.Unknown: diff --git a/src/ImageSharp/Processing/Processors/Transforms/RotateProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/RotateProcessor.cs index 1ad7263929..be49ec321b 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/RotateProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/RotateProcessor.cs @@ -19,39 +19,35 @@ namespace SixLabors.ImageSharp.Processing.Processors internal class RotateProcessor : AffineProcessor where TPixel : struct, IPixel { - private Matrix3x2 transformMatrix; - /// /// Initializes a new instance of the class. /// - public RotateProcessor() - : base(KnownResamplers.NearestNeighbor) + /// The angle of rotation in degrees. + public RotateProcessor(float angle) + : this(angle, KnownResamplers.NearestNeighbor) { } /// /// Initializes a new instance of the class. /// + /// The angle of rotation in degrees. /// The sampler to perform the rotating operation. - public RotateProcessor(IResampler sampler) + public RotateProcessor(float degrees, IResampler sampler) : base(sampler) { + this.Degrees = degrees; } /// - /// Gets or sets the angle of processMatrix in degrees. + /// Gets the angle of rotation in degrees. /// - public float Angle { get; set; } + public float Degrees { get; } /// - protected override Matrix3x2 CreateProcessingMatrix(Rectangle rectangle) + protected override Matrix3x2 GetTransformMatrix() { - if (this.transformMatrix == default(Matrix3x2)) - { - this.transformMatrix = Matrix3x2Extensions.CreateRotationDegrees(-this.Angle, PointF.Empty); - } - - return this.transformMatrix; + return Matrix3x2Extensions.CreateRotationDegrees(-this.Degrees, PointF.Empty); } /// @@ -74,7 +70,7 @@ namespace SixLabors.ImageSharp.Processing.Processors return; } - if (MathF.Abs(this.Angle) < Constants.Epsilon) + if (MathF.Abs(this.Degrees) < Constants.Epsilon) { // No need to do anything so return. return; @@ -82,7 +78,7 @@ namespace SixLabors.ImageSharp.Processing.Processors profile.RemoveValue(ExifTag.Orientation); - if (this.Expand && profile.GetValue(ExifTag.PixelXDimension) != null) + if (profile.GetValue(ExifTag.PixelXDimension) != null) { profile.SetValue(ExifTag.PixelXDimension, source.Width); profile.SetValue(ExifTag.PixelYDimension, source.Height); @@ -100,26 +96,26 @@ namespace SixLabors.ImageSharp.Processing.Processors /// private bool OptimizedApply(ImageFrame source, ImageFrame destination, Configuration configuration) { - if (MathF.Abs(this.Angle) < Constants.Epsilon) + if (MathF.Abs(this.Degrees) < Constants.Epsilon) { // The destination will be blank here so copy all the pixel data over source.GetPixelSpan().CopyTo(destination.GetPixelSpan()); return true; } - if (MathF.Abs(this.Angle - 90) < Constants.Epsilon) + if (MathF.Abs(this.Degrees - 90) < Constants.Epsilon) { this.Rotate90(source, destination, configuration); return true; } - if (MathF.Abs(this.Angle - 180) < Constants.Epsilon) + if (MathF.Abs(this.Degrees - 180) < Constants.Epsilon) { this.Rotate180(source, destination, configuration); return true; } - if (MathF.Abs(this.Angle - 270) < Constants.Epsilon) + if (MathF.Abs(this.Degrees - 270) < Constants.Epsilon) { this.Rotate270(source, destination, configuration); return true; diff --git a/src/ImageSharp/Processing/Processors/Transforms/SkewProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/SkewProcessor.cs index 61526747ea..8da8b1e57b 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/SkewProcessor.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/SkewProcessor.cs @@ -14,36 +14,43 @@ namespace SixLabors.ImageSharp.Processing.Processors internal class SkewProcessor : AffineProcessor where TPixel : struct, IPixel { - private Matrix3x2 transformMatrix; + /// + /// Initializes a new instance of the class. + /// + /// The angle in degrees to perform the skew along the x-axis. + /// The angle in degrees to perform the skew along the y-axis. + public SkewProcessor(float degreesX, float degreesY) + : this(degreesX, degreesY, KnownResamplers.NearestNeighbor) + { + } /// /// Initializes a new instance of the class. /// + /// The angle in degrees to perform the skew along the x-axis. + /// The angle in degrees to perform the skew along the y-axis. /// The sampler to perform the skew operation. - public SkewProcessor(IResampler sampler) + public SkewProcessor(float degreesX, float degreesY, IResampler sampler) : base(sampler) { + this.DegreesX = degreesX; + this.DegreesY = degreesY; } /// - /// Gets or sets the angle of rotation along the x-axis in degrees. + /// Gets the angle of rotation along the x-axis in degrees. /// - public float AngleX { get; set; } + public float DegreesX { get; } /// - /// Gets or sets the angle of rotation along the y-axis in degrees. + /// Gets the angle of rotation along the y-axis in degrees. /// - public float AngleY { get; set; } + public float DegreesY { get; } /// - protected override Matrix3x2 CreateProcessingMatrix(Rectangle rectangle) + protected override Matrix3x2 GetTransformMatrix() { - if (this.transformMatrix == default(Matrix3x2)) - { - this.transformMatrix = Matrix3x2Extensions.CreateSkewDegrees(-this.AngleX, -this.AngleY, PointF.Empty); - } - - return this.transformMatrix; + return Matrix3x2Extensions.CreateSkewDegrees(-this.DegreesX, -this.DegreesY, PointF.Empty); } } } \ No newline at end of file diff --git a/src/ImageSharp/Processing/Transforms/Resamplers/BicubicResampler.cs b/src/ImageSharp/Processing/Transforms/Resamplers/BicubicResampler.cs index 9fb1313d9f..be9de9edaa 100644 --- a/src/ImageSharp/Processing/Transforms/Resamplers/BicubicResampler.cs +++ b/src/ImageSharp/Processing/Transforms/Resamplers/BicubicResampler.cs @@ -1,8 +1,6 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using System.Runtime.CompilerServices; - namespace SixLabors.ImageSharp.Processing { /// @@ -16,7 +14,6 @@ namespace SixLabors.ImageSharp.Processing public float Radius => 2; /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] public float GetValue(float x) { if (x < 0F) diff --git a/src/ImageSharp/Processing/Transforms/Resamplers/BoxResampler.cs b/src/ImageSharp/Processing/Transforms/Resamplers/BoxResampler.cs index 8255af4fe5..5aab0d07fa 100644 --- a/src/ImageSharp/Processing/Transforms/Resamplers/BoxResampler.cs +++ b/src/ImageSharp/Processing/Transforms/Resamplers/BoxResampler.cs @@ -1,8 +1,6 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using System.Runtime.CompilerServices; - namespace SixLabors.ImageSharp.Processing { /// @@ -15,7 +13,6 @@ namespace SixLabors.ImageSharp.Processing public float Radius => 0.5F; /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] public float GetValue(float x) { if (x > -0.5F && x <= 0.5F) diff --git a/src/ImageSharp/Processing/Transforms/Resamplers/CatmullRomResampler.cs b/src/ImageSharp/Processing/Transforms/Resamplers/CatmullRomResampler.cs index 19f466287c..1c84676188 100644 --- a/src/ImageSharp/Processing/Transforms/Resamplers/CatmullRomResampler.cs +++ b/src/ImageSharp/Processing/Transforms/Resamplers/CatmullRomResampler.cs @@ -1,8 +1,6 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using System.Runtime.CompilerServices; - namespace SixLabors.ImageSharp.Processing { /// @@ -17,7 +15,6 @@ namespace SixLabors.ImageSharp.Processing public float Radius => 2; /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] public float GetValue(float x) { const float B = 0; diff --git a/src/ImageSharp/Processing/Transforms/Resamplers/HermiteResampler.cs b/src/ImageSharp/Processing/Transforms/Resamplers/HermiteResampler.cs index afc1427f48..33435059f1 100644 --- a/src/ImageSharp/Processing/Transforms/Resamplers/HermiteResampler.cs +++ b/src/ImageSharp/Processing/Transforms/Resamplers/HermiteResampler.cs @@ -1,8 +1,6 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using System.Runtime.CompilerServices; - namespace SixLabors.ImageSharp.Processing { /// @@ -16,7 +14,6 @@ namespace SixLabors.ImageSharp.Processing public float Radius => 2; /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] public float GetValue(float x) { const float B = 0F; diff --git a/src/ImageSharp/Processing/Transforms/Resamplers/Lanczos2Resampler.cs b/src/ImageSharp/Processing/Transforms/Resamplers/Lanczos2Resampler.cs index 3d5af528e2..29568db021 100644 --- a/src/ImageSharp/Processing/Transforms/Resamplers/Lanczos2Resampler.cs +++ b/src/ImageSharp/Processing/Transforms/Resamplers/Lanczos2Resampler.cs @@ -1,8 +1,6 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using System.Runtime.CompilerServices; - namespace SixLabors.ImageSharp.Processing { /// @@ -16,7 +14,6 @@ namespace SixLabors.ImageSharp.Processing public float Radius => 2; /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] public float GetValue(float x) { if (x < 0F) diff --git a/src/ImageSharp/Processing/Transforms/Resamplers/Lanczos3Resampler.cs b/src/ImageSharp/Processing/Transforms/Resamplers/Lanczos3Resampler.cs index 7e46b05f33..492ef69e4c 100644 --- a/src/ImageSharp/Processing/Transforms/Resamplers/Lanczos3Resampler.cs +++ b/src/ImageSharp/Processing/Transforms/Resamplers/Lanczos3Resampler.cs @@ -1,8 +1,6 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using System.Runtime.CompilerServices; - namespace SixLabors.ImageSharp.Processing { /// @@ -16,7 +14,6 @@ namespace SixLabors.ImageSharp.Processing public float Radius => 3; /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] public float GetValue(float x) { if (x < 0F) diff --git a/src/ImageSharp/Processing/Transforms/Resamplers/Lanczos5Resampler.cs b/src/ImageSharp/Processing/Transforms/Resamplers/Lanczos5Resampler.cs index d593dbcf43..cae152a53c 100644 --- a/src/ImageSharp/Processing/Transforms/Resamplers/Lanczos5Resampler.cs +++ b/src/ImageSharp/Processing/Transforms/Resamplers/Lanczos5Resampler.cs @@ -1,8 +1,6 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using System.Runtime.CompilerServices; - namespace SixLabors.ImageSharp.Processing { /// @@ -16,7 +14,6 @@ namespace SixLabors.ImageSharp.Processing public float Radius => 5; /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] public float GetValue(float x) { if (x < 0F) diff --git a/src/ImageSharp/Processing/Transforms/Resamplers/Lanczos8Resampler.cs b/src/ImageSharp/Processing/Transforms/Resamplers/Lanczos8Resampler.cs index 5d7c708f2d..b390c55419 100644 --- a/src/ImageSharp/Processing/Transforms/Resamplers/Lanczos8Resampler.cs +++ b/src/ImageSharp/Processing/Transforms/Resamplers/Lanczos8Resampler.cs @@ -1,8 +1,6 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using System.Runtime.CompilerServices; - namespace SixLabors.ImageSharp.Processing { /// @@ -16,7 +14,6 @@ namespace SixLabors.ImageSharp.Processing public float Radius => 8; /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] public float GetValue(float x) { if (x < 0F) diff --git a/src/ImageSharp/Processing/Transforms/Resamplers/MitchellNetravaliResampler.cs b/src/ImageSharp/Processing/Transforms/Resamplers/MitchellNetravaliResampler.cs index f6e9a9fa09..df351d9505 100644 --- a/src/ImageSharp/Processing/Transforms/Resamplers/MitchellNetravaliResampler.cs +++ b/src/ImageSharp/Processing/Transforms/Resamplers/MitchellNetravaliResampler.cs @@ -1,8 +1,6 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using System.Runtime.CompilerServices; - namespace SixLabors.ImageSharp.Processing { /// @@ -15,7 +13,6 @@ namespace SixLabors.ImageSharp.Processing public float Radius => 2; /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] public float GetValue(float x) { const float B = 0.3333333F; diff --git a/src/ImageSharp/Processing/Transforms/Resamplers/NearestNeighborResampler.cs b/src/ImageSharp/Processing/Transforms/Resamplers/NearestNeighborResampler.cs index b1cc8609e7..7a7785be36 100644 --- a/src/ImageSharp/Processing/Transforms/Resamplers/NearestNeighborResampler.cs +++ b/src/ImageSharp/Processing/Transforms/Resamplers/NearestNeighborResampler.cs @@ -1,8 +1,6 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using System.Runtime.CompilerServices; - namespace SixLabors.ImageSharp.Processing { /// @@ -15,7 +13,6 @@ namespace SixLabors.ImageSharp.Processing public float Radius => 1; /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] public float GetValue(float x) { return x; diff --git a/src/ImageSharp/Processing/Transforms/Resamplers/RobidouxSharpResampler.cs b/src/ImageSharp/Processing/Transforms/Resamplers/RobidouxSharpResampler.cs index 9db4b125f2..a345da3f42 100644 --- a/src/ImageSharp/Processing/Transforms/Resamplers/RobidouxSharpResampler.cs +++ b/src/ImageSharp/Processing/Transforms/Resamplers/RobidouxSharpResampler.cs @@ -1,8 +1,6 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using System.Runtime.CompilerServices; - namespace SixLabors.ImageSharp.Processing { /// @@ -15,7 +13,6 @@ namespace SixLabors.ImageSharp.Processing public float Radius => 2; /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] public float GetValue(float x) { const float B = 0.2620145123990142F; diff --git a/src/ImageSharp/Processing/Transforms/Resamplers/SplineResampler.cs b/src/ImageSharp/Processing/Transforms/Resamplers/SplineResampler.cs index 815fd9c3dc..ac5e2dedba 100644 --- a/src/ImageSharp/Processing/Transforms/Resamplers/SplineResampler.cs +++ b/src/ImageSharp/Processing/Transforms/Resamplers/SplineResampler.cs @@ -1,8 +1,6 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using System.Runtime.CompilerServices; - namespace SixLabors.ImageSharp.Processing { /// @@ -15,7 +13,6 @@ namespace SixLabors.ImageSharp.Processing public float Radius => 2; /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] public float GetValue(float x) { const float B = 1F; diff --git a/src/ImageSharp/Processing/Transforms/Resamplers/TriangleResampler.cs b/src/ImageSharp/Processing/Transforms/Resamplers/TriangleResampler.cs index 4b62c767bc..842da87e06 100644 --- a/src/ImageSharp/Processing/Transforms/Resamplers/TriangleResampler.cs +++ b/src/ImageSharp/Processing/Transforms/Resamplers/TriangleResampler.cs @@ -1,8 +1,6 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using System.Runtime.CompilerServices; - namespace SixLabors.ImageSharp.Processing { /// @@ -16,7 +14,6 @@ namespace SixLabors.ImageSharp.Processing public float Radius => 1; /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] public float GetValue(float x) { if (x < 0F) diff --git a/src/ImageSharp/Processing/Transforms/Resamplers/WelchResampler.cs b/src/ImageSharp/Processing/Transforms/Resamplers/WelchResampler.cs index 9bf19573af..9e18a24710 100644 --- a/src/ImageSharp/Processing/Transforms/Resamplers/WelchResampler.cs +++ b/src/ImageSharp/Processing/Transforms/Resamplers/WelchResampler.cs @@ -1,8 +1,6 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using System.Runtime.CompilerServices; - namespace SixLabors.ImageSharp.Processing { /// @@ -15,7 +13,6 @@ namespace SixLabors.ImageSharp.Processing public float Radius => 3; /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] public float GetValue(float x) { if (x < 0F) diff --git a/src/ImageSharp/Processing/Transforms/Rotate.cs b/src/ImageSharp/Processing/Transforms/Rotate.cs index 2ec1385bb9..e9ae4fcf32 100644 --- a/src/ImageSharp/Processing/Transforms/Rotate.cs +++ b/src/ImageSharp/Processing/Transforms/Rotate.cs @@ -12,29 +12,6 @@ namespace SixLabors.ImageSharp /// public static partial class ImageExtensions { - /// - /// Rotates an image by the given angle in degrees, expanding the image to fit the rotated result. - /// - /// The pixel format. - /// The image to rotate. - /// The angle in degrees to perform the rotation. - /// The - public static IImageProcessingContext Rotate(this IImageProcessingContext source, float degrees) - where TPixel : struct, IPixel - => Rotate(source, degrees, true); - - /// - /// Rotates an image by the given angle in degrees, expanding the image to fit the rotated result. - /// - /// The pixel format. - /// The image to rotate. - /// The angle in degrees to perform the rotation. - /// The to perform the resampling. - /// The - public static IImageProcessingContext Rotate(this IImageProcessingContext source, float degrees, IResampler sampler) - where TPixel : struct, IPixel - => Rotate(source, degrees, sampler, true); - /// /// Rotates and flips an image by the given instructions. /// @@ -44,7 +21,7 @@ namespace SixLabors.ImageSharp /// The public static IImageProcessingContext Rotate(this IImageProcessingContext source, RotateType rotateType) where TPixel : struct, IPixel - => Rotate(source, (float)rotateType, false); + => Rotate(source, (float)rotateType); /// /// Rotates an image by the given angle in degrees. @@ -52,11 +29,10 @@ namespace SixLabors.ImageSharp /// The pixel format. /// The image to rotate. /// The angle in degrees to perform the rotation. - /// Whether to expand the image to fit the rotated result. /// The - public static IImageProcessingContext Rotate(this IImageProcessingContext source, float degrees, bool expand) + public static IImageProcessingContext Rotate(this IImageProcessingContext source, float degrees) where TPixel : struct, IPixel - => Rotate(source, degrees, KnownResamplers.NearestNeighbor, expand); + => Rotate(source, degrees, KnownResamplers.NearestNeighbor); /// /// Rotates an image by the given angle in degrees using the specified sampling algorithm. @@ -65,10 +41,9 @@ namespace SixLabors.ImageSharp /// The image to rotate. /// The angle in degrees to perform the rotation. /// The to perform the resampling. - /// Whether to expand the image to fit the rotated result. /// The - public static IImageProcessingContext Rotate(this IImageProcessingContext source, float degrees, IResampler sampler, bool expand) + public static IImageProcessingContext Rotate(this IImageProcessingContext source, float degrees, IResampler sampler) where TPixel : struct, IPixel - => source.ApplyProcessor(new RotateProcessor(sampler) { Angle = degrees, Expand = expand }); + => source.ApplyProcessor(new RotateProcessor(degrees, sampler)); } -} +} \ No newline at end of file diff --git a/src/ImageSharp/Processing/Transforms/Skew.cs b/src/ImageSharp/Processing/Transforms/Skew.cs index f03e60e3da..b7a431cce4 100644 --- a/src/ImageSharp/Processing/Transforms/Skew.cs +++ b/src/ImageSharp/Processing/Transforms/Skew.cs @@ -12,56 +12,29 @@ namespace SixLabors.ImageSharp /// public static partial class ImageExtensions { - /// - /// Skews an image by the given angles in degrees, expanding the image to fit the skewed result. - /// - /// The pixel format. - /// The image to skew. - /// The angle in degrees to perform the rotation along the x-axis. - /// The angle in degrees to perform the rotation along the y-axis. - /// The - public static IImageProcessingContext Skew(this IImageProcessingContext source, float degreesX, float degreesY) - where TPixel : struct, IPixel - => Skew(source, degreesX, degreesY, true); - - /// - /// Skews an image by the given angles in degrees using the given sampler, expanding the image to fit the skewed result. - /// - /// The pixel format. - /// The image to skew. - /// The angle in degrees to perform the rotation along the x-axis. - /// The angle in degrees to perform the rotation along the y-axis. - /// The to perform the resampling. - /// The - public static IImageProcessingContext Skew(this IImageProcessingContext source, float degreesX, float degreesY, IResampler sampler) - where TPixel : struct, IPixel - => Skew(source, degreesX, degreesY, sampler, true); - /// /// Skews an image by the given angles in degrees. /// /// The pixel format. /// The image to skew. - /// The angle in degrees to perform the rotation along the x-axis. - /// The angle in degrees to perform the rotation along the y-axis. - /// Whether to expand the image to fit the skewed result. + /// The angle in degrees to perform the skew along the x-axis. + /// The angle in degrees to perform the skew along the y-axis. /// The - public static IImageProcessingContext Skew(this IImageProcessingContext source, float degreesX, float degreesY, bool expand) + public static IImageProcessingContext Skew(this IImageProcessingContext source, float degreesX, float degreesY) where TPixel : struct, IPixel - => Skew(source, degreesX, degreesY, KnownResamplers.NearestNeighbor, expand); + => Skew(source, degreesX, degreesY, KnownResamplers.NearestNeighbor); /// /// Skews an image by the given angles in degrees using the specified sampling algorithm. /// /// The pixel format. /// The image to skew. - /// The angle in degrees to perform the rotation along the x-axis. - /// The angle in degrees to perform the rotation along the y-axis. + /// The angle in degrees to perform the skew along the x-axis. + /// The angle in degrees to perform the skew along the y-axis. /// The to perform the resampling. - /// Whether to expand the image to fit the skewed result. /// The - public static IImageProcessingContext Skew(this IImageProcessingContext source, float degreesX, float degreesY, IResampler sampler, bool expand) + public static IImageProcessingContext Skew(this IImageProcessingContext source, float degreesX, float degreesY, IResampler sampler) where TPixel : struct, IPixel - => source.ApplyProcessor(new SkewProcessor(sampler) { AngleX = degreesX, AngleY = degreesY, Expand = expand }); + => source.ApplyProcessor(new SkewProcessor(degreesX, degreesY, sampler)); } -} +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Transforms/RotateFlipTests.cs b/tests/ImageSharp.Tests/Processing/Transforms/RotateFlipTests.cs index 67602131b0..75d7067702 100644 --- a/tests/ImageSharp.Tests/Processing/Transforms/RotateFlipTests.cs +++ b/tests/ImageSharp.Tests/Processing/Transforms/RotateFlipTests.cs @@ -25,14 +25,13 @@ namespace SixLabors.ImageSharp.Tests.Processing.Transforms [InlineData(RotateType.Rotate90, FlipType.Vertical, 90)] [InlineData(RotateType.Rotate180, FlipType.Vertical, 180)] [InlineData(RotateType.Rotate270, FlipType.Vertical, 270)] - public void Rotate_degreesFloat_RotateProcessorWithAnglesSetAndExpandTrue(RotateType angle, FlipType flip, float expectedAngle) + public void Rotate_degreesFloat_RotateProcessorWithAnglesSetrue(RotateType angle, FlipType flip, float expectedAngle) { this.operations.RotateFlip(angle, flip); - var rotateProcessor = this.Verify>(0); - var flipProcessor = this.Verify>(1); + RotateProcessor rotateProcessor = this.Verify>(0); + FlipProcessor flipProcessor = this.Verify>(1); - Assert.Equal(expectedAngle, rotateProcessor.Angle); - Assert.False(rotateProcessor.Expand); + Assert.Equal(expectedAngle, rotateProcessor.Degrees); Assert.Equal(flip, flipProcessor.FlipType); } } diff --git a/tests/ImageSharp.Tests/Processing/Transforms/RotateTests.cs b/tests/ImageSharp.Tests/Processing/Transforms/RotateTests.cs index 80eccd00cd..a990fa88ca 100644 --- a/tests/ImageSharp.Tests/Processing/Transforms/RotateTests.cs +++ b/tests/ImageSharp.Tests/Processing/Transforms/RotateTests.cs @@ -1,7 +1,6 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Processing.Processors; using Xunit; @@ -10,46 +9,28 @@ namespace SixLabors.ImageSharp.Tests.Processing.Transforms { public class RotateTests : BaseImageOperationsExtensionTest { - [Theory] [InlineData(85.6f)] [InlineData(21)] - public void Rotate_degreesFloat_RotateProcessorWithAnglesSetAndExpandTrue(float angle) + public void RotateDegreesFloatRotateProcessorWithAnglesSet(float angle) { this.operations.Rotate(angle); - var processor = this.Verify>(); + RotateProcessor processor = this.Verify>(); - Assert.Equal(angle, processor.Angle); - Assert.True(processor.Expand); + Assert.Equal(angle, processor.Degrees); } - [Theory] [InlineData(RotateType.None, 0)] [InlineData(RotateType.Rotate90, 90)] [InlineData(RotateType.Rotate180, 180)] [InlineData(RotateType.Rotate270, 270)] - public void Rotate_RotateType_RotateProcessorWithAnglesConvertedFromEnumAndExpandTrue(RotateType angle, float expectedangle) + public void RotateRotateTypeRotateProcessorWithAnglesConvertedFromEnum(RotateType angle, float expectedangle) { this.operations.Rotate(angle); // is this api needed ??? - var processor = this.Verify>(); - - Assert.Equal(expectedangle, processor.Angle); - Assert.False(processor.Expand); - } - - - [Theory] - [InlineData(85.6f, false)] - [InlineData(21, true)] - [InlineData(21, false)] - public void Rotate_degreesFloat_expand_RotateProcessorWithAnglesSetAndExpandSet(float angle, bool expand) - { - this.operations.Rotate(angle, expand); - var processor = this.Verify>(); + RotateProcessor processor = this.Verify>(); - Assert.Equal(angle, processor.Angle); - Assert.Equal(expand, processor.Expand); + Assert.Equal(expectedangle, processor.Degrees); } } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Transforms/SkewTest.cs b/tests/ImageSharp.Tests/Processing/Transforms/SkewTest.cs index 28a0e0d8f8..d2cc5764ed 100644 --- a/tests/ImageSharp.Tests/Processing/Transforms/SkewTest.cs +++ b/tests/ImageSharp.Tests/Processing/Transforms/SkewTest.cs @@ -1,7 +1,6 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. -using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing.Processors; using Xunit; @@ -10,25 +9,13 @@ namespace SixLabors.ImageSharp.Tests.Processing.Transforms public class SkewTest : BaseImageOperationsExtensionTest { [Fact] - public void Skew_x_y_CreateSkewProcessorWithAnglesSetAndExpandTrue() + public void SkewXYCreateSkewProcessorWithAnglesSet() { this.operations.Skew(10, 20); - var processor = this.Verify>(); + SkewProcessor processor = this.Verify>(); - Assert.Equal(10, processor.AngleX); - Assert.Equal(20, processor.AngleY); - Assert.True(processor.Expand); - } - - [Fact] - public void Skew_x_y_expand_CreateSkewProcessorWithAnglesSetAndExpandTrue() - { - this.operations.Skew(10, 20, false); - var processor = this.Verify>(); - - Assert.Equal(10, processor.AngleX); - Assert.Equal(20, processor.AngleY); - Assert.False(processor.Expand); + Assert.Equal(10, processor.DegreesX); + Assert.Equal(20, processor.DegreesY); } } } \ No newline at end of file