diff --git a/src/ImageProcessor.UnitTests/Imaging/RotationUnitTests.cs b/src/ImageProcessor.UnitTests/Imaging/Helpers/ImageMathsUnitTests.cs
similarity index 78%
rename from src/ImageProcessor.UnitTests/Imaging/RotationUnitTests.cs
rename to src/ImageProcessor.UnitTests/Imaging/Helpers/ImageMathsUnitTests.cs
index 0e33eb5dc..9b42e7f85 100644
--- a/src/ImageProcessor.UnitTests/Imaging/RotationUnitTests.cs
+++ b/src/ImageProcessor.UnitTests/Imaging/Helpers/ImageMathsUnitTests.cs
@@ -1,11 +1,11 @@
-namespace ImageProcessor.UnitTests.Imaging
+namespace ImageProcessor.UnitTests.Imaging.Helpers
{
using System.Drawing;
using FluentAssertions;
- using ImageProcessor.Imaging;
+ using ImageProcessor.Imaging.Helpers;
using NUnit.Framework;
- public class RotationUnitTests
+ public class ImageMathsUnitTests
{
[Test]
[TestCase(100, 100, 45, 141, 141)]
@@ -13,7 +13,7 @@
[TestCase(100, 200, 50, 217, 205)]
public void NewSizeAfterRotationIsCalculated(int width, int height, float angle, int expectedWidth, int expectedHeight)
{
- Size result = Rotation.NewSizeAfterRotation(width, height, angle);
+ Size result = ImageMaths.GetBoundingRotatedRectangle(width, height, angle);
result.Width.Should().Be(expectedWidth, "because the rotated width should have been calculated");
result.Height.Should().Be(expectedHeight, "because the rotated height should have been calculated");
@@ -28,7 +28,7 @@
[TestCase(600, 450, 45, 1.64f)]
public void RotationZoomIsCalculated(int imageWidth, int imageHeight, float angle, float expected)
{
- float result = Rotation.ZoomAfterRotation(imageWidth, imageHeight, angle);
+ float result = ImageMaths.ZoomAfterRotation(imageWidth, imageHeight, angle);
result.Should().BeApproximately(expected, 0.01f, "because the zoom level after rotation should have been calculated");
}
diff --git a/src/ImageProcessor/Imaging/Helpers/ImageMaths.cs b/src/ImageProcessor/Imaging/Helpers/ImageMaths.cs
index af0593976..60b35989f 100644
--- a/src/ImageProcessor/Imaging/Helpers/ImageMaths.cs
+++ b/src/ImageProcessor/Imaging/Helpers/ImageMaths.cs
@@ -12,7 +12,6 @@ namespace ImageProcessor.Imaging.Helpers
{
using System;
using System.Drawing;
-
using ImageProcessor.Imaging.Colors;
///
@@ -20,6 +19,27 @@ namespace ImageProcessor.Imaging.Helpers
///
public static class ImageMaths
{
+ ///
+ /// Gets a representing the child centered relative to the parent.
+ ///
+ ///
+ /// The parent .
+ ///
+ ///
+ /// The child .
+ ///
+ ///
+ /// The centered .
+ ///
+ public static RectangleF CenteredRectangle(Rectangle parent, Rectangle child)
+ {
+ float x = (parent.Width - child.Width) / 2.0F;
+ float y = (parent.Height - child.Height) / 2.0F;
+ int width = child.Width;
+ int height = child.Height;
+ return new RectangleF(x, y, width, height);
+ }
+
///
/// Restricts a value to be within a specified range.
///
@@ -53,6 +73,20 @@ namespace ImageProcessor.Imaging.Helpers
return value;
}
+ ///
+ /// Returns the given degrees converted to radians.
+ ///
+ ///
+ /// The angle in degrees.
+ ///
+ ///
+ /// The representing the degree as radians.
+ ///
+ public static double DegreesToRadians(double angleInDegrees)
+ {
+ return angleInDegrees * (Math.PI / 180);
+ }
+
///
/// Gets the bounding from the given points.
///
@@ -70,6 +104,38 @@ namespace ImageProcessor.Imaging.Helpers
return new Rectangle(topLeft.X, topLeft.Y, bottomRight.X - topLeft.X, bottomRight.Y - topLeft.Y);
}
+ ///
+ /// Calculates the new size after rotation.
+ ///
+ /// The width of the image.
+ /// The height of the image.
+ /// The angle of rotation.
+ /// The new size of the image
+ public static Size GetBoundingRotatedRectangle(int width, int height, float angle)
+ {
+ double widthAsDouble = width;
+ double heightAsDouble = height;
+
+ double radians = DegreesToRadians(angle);
+ double radiansSin = Math.Sin(radians);
+ double radiansCos = Math.Cos(radians);
+ double width1 = (heightAsDouble * radiansSin) + (widthAsDouble * radiansCos);
+ double height1 = (widthAsDouble * radiansSin) + (heightAsDouble * radiansCos);
+
+ // Find dimensions in the other direction
+ radiansSin = Math.Sin(-radians);
+ radiansCos = Math.Cos(-radians);
+ double width2 = (heightAsDouble * radiansSin) + (widthAsDouble * radiansCos);
+ double height2 = (widthAsDouble * radiansSin) + (heightAsDouble * radiansCos);
+
+ // Get the external vertex for the rotation
+ Size result = new Size();
+ result.Width = Convert.ToInt32(Math.Max(Math.Abs(width1), Math.Abs(width2)));
+ result.Height = Convert.ToInt32(Math.Max(Math.Abs(height1), Math.Abs(height2)));
+
+ return result;
+ }
+
///
/// Finds the bounding rectangle based on the first instance of any color component other
/// than the given one.
@@ -101,12 +167,15 @@ namespace ImageProcessor.Imaging.Helpers
case RgbaComponent.R:
delegateFunc = (fastBitmap, x, y, b) => fastBitmap.GetPixel(x, y).R != b;
break;
+
case RgbaComponent.G:
delegateFunc = (fastBitmap, x, y, b) => fastBitmap.GetPixel(x, y).G != b;
break;
+
case RgbaComponent.A:
delegateFunc = (fastBitmap, x, y, b) => fastBitmap.GetPixel(x, y).A != b;
break;
+
default:
delegateFunc = (fastBitmap, x, y, b) => fastBitmap.GetPixel(x, y).B != b;
break;
@@ -188,24 +257,31 @@ namespace ImageProcessor.Imaging.Helpers
}
///
- /// Gets a representing the child centered relative to the parent.
+ /// Rotates one point around another
+ ///
///
- ///
- /// The parent .
- ///
- ///
- /// The child .
+ /// The point to rotate.
+ /// The rotation angle in degrees.
+ /// The centre point of rotation. If not set the point will equal
+ ///
///
- ///
- /// The centered .
- ///
- public static RectangleF CenteredRectangle(Rectangle parent, Rectangle child)
+ /// Rotated point
+ public static Point RotatePoint(Point pointToRotate, double angleInDegrees, Point? centerPoint = null)
{
- float x = (parent.Width - child.Width) / 2.0F;
- float y = (parent.Height - child.Height) / 2.0F;
- int width = child.Width;
- int height = child.Height;
- return new RectangleF(x, y, width, height);
+ Point center = centerPoint ?? Point.Empty;
+
+ double angleInRadians = DegreesToRadians(angleInDegrees);
+ double cosTheta = Math.Cos(angleInRadians);
+ double sinTheta = Math.Sin(angleInRadians);
+ return new Point
+ {
+ X =
+ (int)((cosTheta * (pointToRotate.X - center.X)) -
+ ((sinTheta * (pointToRotate.Y - center.Y)) + center.X)),
+ Y =
+ (int)((sinTheta * (pointToRotate.X - center.X)) +
+ ((cosTheta * (pointToRotate.Y - center.Y)) + center.Y))
+ };
}
///
@@ -221,55 +297,33 @@ namespace ImageProcessor.Imaging.Helpers
{
return new[]
{
- new Point(rectangle.Left, rectangle.Top),
- new Point(rectangle.Right, rectangle.Top),
- new Point(rectangle.Right, rectangle.Bottom),
+ new Point(rectangle.Left, rectangle.Top),
+ new Point(rectangle.Right, rectangle.Top),
+ new Point(rectangle.Right, rectangle.Bottom),
new Point(rectangle.Left, rectangle.Bottom)
};
}
///
- /// Returns the given degrees converted to radians.
+ /// Calculates the zoom needed after the rotation.
///
- ///
- /// The angle in degrees.
- ///
- ///
- /// The representing the degree as radians.
- ///
- public static double DegreesToRadians(double angleInDegrees)
+ /// Width of the image.
+ /// Height of the image.
+ /// The angle.
+ ///
+ /// Based on
+ ///
+ /// The zoom needed
+ public static float ZoomAfterRotation(int imageWidth, int imageHeight, float angle)
{
- return angleInDegrees * (Math.PI / 180);
- }
+ double radians = angle * Math.PI / 180d;
+ double radiansSin = Math.Sin(radians);
+ double radiansCos = Math.Cos(radians);
- ///
- /// Rotates one point around another
- ///
- ///
- /// The point to rotate.
- /// The rotation angle in degrees.
- /// The centre point of rotation. If not set the point will equal
- ///
- ///
- /// Rotated point
- public static Point RotatePoint(Point pointToRotate, double angleInDegrees, Point? centerPoint = null)
- {
- Point center = centerPoint ?? Point.Empty;
+ double widthRotated = (imageWidth * radiansCos) + (imageHeight * radiansSin);
+ double heightRotated = (imageWidth * radiansSin) + (imageHeight * radiansCos);
- double angleInRadians = DegreesToRadians(angleInDegrees);
- double cosTheta = Math.Cos(angleInRadians);
- double sinTheta = Math.Sin(angleInRadians);
- return new Point
- {
- X =
- (int)
- ((cosTheta * (pointToRotate.X - center.X)) -
- ((sinTheta * (pointToRotate.Y - center.Y)) + center.X)),
- Y =
- (int)
- ((sinTheta * (pointToRotate.X - center.X)) +
- ((cosTheta * (pointToRotate.Y - center.Y)) + center.Y))
- };
+ return (float)Math.Max(widthRotated / imageWidth, heightRotated / imageHeight);
}
}
-}
+}
\ No newline at end of file
diff --git a/src/ImageProcessor/Imaging/Rotation.cs b/src/ImageProcessor/Imaging/Rotation.cs
deleted file mode 100644
index 0b841c297..000000000
--- a/src/ImageProcessor/Imaging/Rotation.cs
+++ /dev/null
@@ -1,65 +0,0 @@
-namespace ImageProcessor.Imaging
-{
- using System;
- using System.Drawing;
-
- ///
- /// Provides rotation calculation methods
- ///
- internal class Rotation
- {
- ///
- /// Calculates the new size after rotation.
- ///
- /// The width of the image.
- /// The height of the image.
- /// The angle of rotation.
- /// The new size of the image
- public static Size NewSizeAfterRotation(int width, int height, float angle)
- {
- double widthAsDouble = width;
- double heightAsDouble = height;
-
- double radians = angle * Math.PI / 180d;
- double radiansSin = Math.Sin(radians);
- double radiansCos = Math.Cos(radians);
- double width1 = (heightAsDouble * radiansSin) + (widthAsDouble * radiansCos);
- double height1 = (widthAsDouble * radiansSin) + (heightAsDouble * radiansCos);
-
- // Find dimensions in the other direction
- radiansSin = Math.Sin(-radians);
- radiansCos = Math.Cos(-radians);
- double width2 = (heightAsDouble * radiansSin) + (widthAsDouble * radiansCos);
- double height2 = (widthAsDouble * radiansSin) + (heightAsDouble * radiansCos);
-
- // Get the external vertex for the rotation
- Size result = new Size();
- result.Width = Convert.ToInt32(Math.Max(Math.Abs(width1), Math.Abs(width2)));
- result.Height = Convert.ToInt32(Math.Max(Math.Abs(height1), Math.Abs(height2)));
-
- return result;
- }
-
- ///
- /// Calculates the zoom needed after the rotation.
- ///
- /// Width of the image.
- /// Height of the image.
- /// The angle.
- ///
- /// Based on
- ///
- /// The zoom needed
- public static float ZoomAfterRotation(int imageWidth, int imageHeight, float angle)
- {
- double radians = angle * Math.PI / 180d;
- double radiansSin = Math.Sin(radians);
- double radiansCos = Math.Cos(radians);
-
- double widthRotated = (imageWidth * radiansCos) + (imageHeight * radiansSin);
- double heightRotated = (imageWidth * radiansSin) + (imageHeight * radiansCos);
-
- return (float)Math.Max(widthRotated / imageWidth, heightRotated / imageHeight);
- }
- }
-}
\ No newline at end of file
diff --git a/src/ImageProcessor/Processors/Rotate.cs b/src/ImageProcessor/Processors/Rotate.cs
index d0715884f..cb8cc1733 100644
--- a/src/ImageProcessor/Processors/Rotate.cs
+++ b/src/ImageProcessor/Processors/Rotate.cs
@@ -104,7 +104,7 @@ namespace ImageProcessor.Processors
///
private Bitmap RotateImage(Image image, float rotateAtX, float rotateAtY, float angle)
{
- Size newSize = Imaging.Rotation.NewSizeAfterRotation(image.Width, image.Height, angle);
+ Size newSize = Imaging.Helpers.ImageMaths.GetBoundingRotatedRectangle(image.Width, image.Height, angle);
int x = (newSize.Width - image.Width) / 2;
int y = (newSize.Height - image.Height) / 2;
diff --git a/src/ImageProcessor/Processors/RotateInside.cs b/src/ImageProcessor/Processors/RotateInside.cs
index b715aa416..8d4436cda 100644
--- a/src/ImageProcessor/Processors/RotateInside.cs
+++ b/src/ImageProcessor/Processors/RotateInside.cs
@@ -84,7 +84,7 @@ namespace ImageProcessor.Processors
{
Size newSize = new Size(image.Width, image.Height);
- float zoom = Imaging.Rotation.ZoomAfterRotation(image.Width, image.Height, rotateLayer.Angle);
+ float zoom = Imaging.Helpers.ImageMaths.ZoomAfterRotation(image.Width, image.Height, rotateLayer.Angle);
// if we don't keep the image dimensions, calculate the new ones
if (!rotateLayer.KeepImageDimensions)