diff --git a/src/ImageProcessor.UnitTests/ImageFactoryUnitTests.cs b/src/ImageProcessor.UnitTests/ImageFactoryUnitTests.cs
index 847c63904..ac3f9cdb6 100644
--- a/src/ImageProcessor.UnitTests/ImageFactoryUnitTests.cs
+++ b/src/ImageProcessor.UnitTests/ImageFactoryUnitTests.cs
@@ -122,16 +122,18 @@ namespace ImageProcessor.UnitTests
[Test]
public void AlphaIsModified()
{
+ int i = 0;
foreach (ImageFactory imageFactory in this.ListInputImages())
{
Image original = (Image)imageFactory.Image.Clone();
imageFactory.Alpha(50);
-
AssertionHelpers.AssertImagesAreDifferent(
original,
imageFactory.Image,
"because the alpha operation should have been applied on {0}",
imageFactory.ImagePath);
+
+ imageFactory.Format(new ImageProcessor.Imaging.Formats.JpegFormat()).Save("./output/alpha-" + i++.ToString() + ".jpg");
}
}
@@ -141,11 +143,14 @@ namespace ImageProcessor.UnitTests
[Test]
public void BrightnessIsModified()
{
+ int i = 0;
foreach (ImageFactory imageFactory in this.ListInputImages())
{
Image original = (Image)imageFactory.Image.Clone();
imageFactory.Brightness(50);
AssertionHelpers.AssertImagesAreDifferent(original, imageFactory.Image, "because the brightness operation should have been applied on {0}", imageFactory.ImagePath);
+
+ imageFactory.Format(new ImageProcessor.Imaging.Formats.JpegFormat()).Save("./output/brightness-" + i++.ToString() + ".jpg");
}
}
@@ -168,11 +173,14 @@ namespace ImageProcessor.UnitTests
[Test]
public void ContrastIsModified()
{
+ int i = 0;
foreach (ImageFactory imageFactory in this.ListInputImages())
{
Image original = (Image)imageFactory.Image.Clone();
imageFactory.Contrast(50);
AssertionHelpers.AssertImagesAreDifferent(original, imageFactory.Image, "because the contrast operation should have been applied on {0}", imageFactory.ImagePath);
+
+ imageFactory.Format(new ImageProcessor.Imaging.Formats.JpegFormat()).Save("./output/contrast-" + i++.ToString() + ".jpg");
}
}
@@ -182,11 +190,14 @@ namespace ImageProcessor.UnitTests
[Test]
public void SaturationIsModified()
{
+ int i = 0;
foreach (ImageFactory imageFactory in this.ListInputImages())
{
Image original = (Image)imageFactory.Image.Clone();
imageFactory.Saturation(50);
AssertionHelpers.AssertImagesAreDifferent(original, imageFactory.Image, "because the saturation operation should have been applied on {0}", imageFactory.ImagePath);
+
+ imageFactory.Format(new ImageProcessor.Imaging.Formats.JpegFormat()).Save("./output/saturation-" + i++.ToString() + ".jpg");
}
}
@@ -196,11 +207,14 @@ namespace ImageProcessor.UnitTests
[Test]
public void TintIsModified()
{
+ int i = 0;
foreach (ImageFactory imageFactory in this.ListInputImages())
{
Image original = (Image)imageFactory.Image.Clone();
imageFactory.Tint(Color.FromKnownColor(KnownColor.AliceBlue));
AssertionHelpers.AssertImagesAreDifferent(original, imageFactory.Image, "because the tint operation should have been applied on {0}", imageFactory.ImagePath);
+
+ imageFactory.Format(new ImageProcessor.Imaging.Formats.JpegFormat()).Save("./output/tint-" + i++.ToString() + ".jpg");
}
}
@@ -210,11 +224,14 @@ namespace ImageProcessor.UnitTests
[Test]
public void VignetteEffectIsApplied()
{
+ int i = 0;
foreach (ImageFactory imageFactory in this.ListInputImages())
{
Image original = (Image)imageFactory.Image.Clone();
imageFactory.Vignette(Color.FromKnownColor(KnownColor.AliceBlue));
AssertionHelpers.AssertImagesAreDifferent(original, imageFactory.Image, "because the vignette operation should have been applied on {0}", imageFactory.ImagePath);
+
+ imageFactory.Format(new ImageProcessor.Imaging.Formats.JpegFormat()).Save("./output/vignette-" + i++.ToString() + ".jpg");
}
}
@@ -224,6 +241,7 @@ namespace ImageProcessor.UnitTests
[Test]
public void WatermarkIsApplied()
{
+ int i = 0;
foreach (ImageFactory imageFactory in this.ListInputImages())
{
Image original = (Image)imageFactory.Image.Clone();
@@ -235,6 +253,8 @@ namespace ImageProcessor.UnitTests
Text = "Lorem ipsum dolor"
});
AssertionHelpers.AssertImagesAreDifferent(original, imageFactory.Image, "because the watermark operation should have been applied on {0}", imageFactory.ImagePath);
+
+ imageFactory.Format(new ImageProcessor.Imaging.Formats.JpegFormat()).Save("./output/watermark-" + i++.ToString() + ".jpg");
}
}
@@ -244,11 +264,14 @@ namespace ImageProcessor.UnitTests
[Test]
public void BlurEffectIsApplied()
{
+ int i = 0;
foreach (ImageFactory imageFactory in this.ListInputImages())
{
Image original = (Image)imageFactory.Image.Clone();
imageFactory.GaussianBlur(5);
AssertionHelpers.AssertImagesAreDifferent(original, imageFactory.Image, "because the blur operation should have been applied on {0}", imageFactory.ImagePath);
+
+ imageFactory.Format(new ImageProcessor.Imaging.Formats.JpegFormat()).Save("./output/blur-" + i++.ToString() + ".jpg");
}
}
@@ -258,11 +281,14 @@ namespace ImageProcessor.UnitTests
[Test]
public void BlurWithLayerIsApplied()
{
+ int i = 0;
foreach (ImageFactory imageFactory in this.ListInputImages())
{
Image original = (Image)imageFactory.Image.Clone();
imageFactory.GaussianBlur(new GaussianLayer { Sigma = 10, Size = 5, Threshold = 2 });
AssertionHelpers.AssertImagesAreDifferent(original, imageFactory.Image, "because the layered blur operation should have been applied on {0}", imageFactory.ImagePath);
+
+ imageFactory.Format(new ImageProcessor.Imaging.Formats.JpegFormat()).Save("./output/blurlayer-" + i++.ToString() + ".jpg");
}
}
@@ -272,11 +298,14 @@ namespace ImageProcessor.UnitTests
[Test]
public void SharpenEffectIsApplied()
{
+ int i = 0;
foreach (ImageFactory imageFactory in this.ListInputImages())
{
Image original = (Image)imageFactory.Image.Clone();
imageFactory.GaussianSharpen(5);
AssertionHelpers.AssertImagesAreDifferent(original, imageFactory.Image, "because the sharpen operation should have been applied on {0}", imageFactory.ImagePath);
+
+ imageFactory.Format(new ImageProcessor.Imaging.Formats.JpegFormat()).Save("./output/sharpen-" + i++.ToString() + ".jpg");
}
}
@@ -286,11 +315,14 @@ namespace ImageProcessor.UnitTests
[Test]
public void SharpenWithLayerIsApplied()
{
+ int i = 0;
foreach (ImageFactory imageFactory in this.ListInputImages())
{
Image original = (Image)imageFactory.Image.Clone();
imageFactory.GaussianSharpen(new GaussianLayer { Sigma = 10, Size = 5, Threshold = 2 });
AssertionHelpers.AssertImagesAreDifferent(original, imageFactory.Image, "because the layered sharpen operation should have been applied on {0}", imageFactory.ImagePath);
+
+ imageFactory.Format(new ImageProcessor.Imaging.Formats.JpegFormat()).Save("./output/sharpenlayer-" + i++.ToString() + ".jpg");
}
}
@@ -300,6 +332,7 @@ namespace ImageProcessor.UnitTests
[Test]
public void FilterIsApplied()
{
+ int i = 0;
foreach (ImageFactory imageFactory in this.ListInputImages())
{
Image original = (Image)imageFactory.Image.Clone();
@@ -318,13 +351,18 @@ namespace ImageProcessor.UnitTests
MatrixFilters.Sepia
};
+ int j = 0;
foreach (IMatrixFilter filter in filters)
{
imageFactory.Filter(filter);
AssertionHelpers.AssertImagesAreDifferent(original, imageFactory.Image, "because the filter operation should have been applied on {0}", imageFactory.ImagePath);
imageFactory.Reset();
AssertionHelpers.AssertImagesAreIdentical(original, imageFactory.Image, "because the image should be reset");
+
+ imageFactory.Format(new ImageProcessor.Imaging.Formats.JpegFormat()).Save("./output/filter-" + j++.ToString() + "-image-" + i.ToString() + ".jpg");
}
+
+ i++;
}
}
@@ -334,11 +372,14 @@ namespace ImageProcessor.UnitTests
[Test]
public void RoundedCornersAreApplied()
{
+ int i = 0;
foreach (ImageFactory imageFactory in this.ListInputImages())
{
Image original = (Image)imageFactory.Image.Clone();
imageFactory.RoundedCorners(new RoundedCornerLayer(5));
AssertionHelpers.AssertImagesAreDifferent(original, imageFactory.Image, "because the rounded corners operation should have been applied on {0}", imageFactory.ImagePath);
+
+ imageFactory.Format(new ImageProcessor.Imaging.Formats.JpegFormat()).Save("./output/roundedcorners-" + i++.ToString() + ".jpg");
}
}
@@ -348,12 +389,15 @@ namespace ImageProcessor.UnitTests
[Test]
public void ImageIsResizedWithinConstraints()
{
+ int i = 0;
const int MaxSize = 200;
foreach (ImageFactory imageFactory in this.ListInputImages())
{
imageFactory.Constrain(new Size(MaxSize, MaxSize));
imageFactory.Image.Width.Should().BeLessOrEqualTo(MaxSize, "because the image size should have been reduced");
imageFactory.Image.Height.Should().BeLessOrEqualTo(MaxSize, "because the image size should have been reduced");
+
+ imageFactory.Format(new ImageProcessor.Imaging.Formats.JpegFormat()).Save("./output/resizedcontraints-" + i++.ToString() + ".jpg");
}
}
@@ -363,6 +407,7 @@ namespace ImageProcessor.UnitTests
[Test]
public void ImageIsCropped()
{
+ int i = 0;
const int MaxSize = 20;
foreach (ImageFactory imageFactory in this.ListInputImages())
{
@@ -372,6 +417,8 @@ namespace ImageProcessor.UnitTests
imageFactory.Image.Width.Should().Be(MaxSize, "because the cropped image should be {0}x{0}", MaxSize);
imageFactory.Image.Height.Should().Be(MaxSize, "because the cropped image should be {0}x{0}", MaxSize);
+
+ imageFactory.Format(new ImageProcessor.Imaging.Formats.JpegFormat()).Save("./output/crop-" + i++.ToString() + ".jpg");
}
}
@@ -381,6 +428,7 @@ namespace ImageProcessor.UnitTests
[Test]
public void ImageIsCroppedWithLayer()
{
+ int i = 0;
const int MaxSize = 20;
foreach (ImageFactory imageFactory in this.ListInputImages())
{
@@ -390,6 +438,8 @@ namespace ImageProcessor.UnitTests
imageFactory.Image.Width.Should().Be(MaxSize, "because the cropped image should be {0}x{0}", MaxSize);
imageFactory.Image.Height.Should().Be(MaxSize, "because the cropped image should be {0}x{0}", MaxSize);
+
+ imageFactory.Format(new ImageProcessor.Imaging.Formats.JpegFormat()).Save("./output/croplayer-" + i++.ToString() + ".jpg");
}
}
@@ -399,6 +449,7 @@ namespace ImageProcessor.UnitTests
[Test]
public void ImageIsFlipped()
{
+ int i = 0;
foreach (ImageFactory imageFactory in this.ListInputImages())
{
Image original = (Image)imageFactory.Image.Clone();
@@ -413,6 +464,8 @@ namespace ImageProcessor.UnitTests
AssertionHelpers.AssertImagesAreDifferent(original, imageFactory.Image, "because the horizontal flip operation should have been applied on {0}", imageFactory.ImagePath);
imageFactory.Image.Width.Should().Be(original.Width, "because the dimensions should not have changed");
imageFactory.Image.Height.Should().Be(original.Height, "because the dimensions should not have changed");
+
+ imageFactory.Format(new ImageProcessor.Imaging.Formats.JpegFormat()).Save("./output/flip-" + i++.ToString() + ".jpg");
}
}
@@ -422,6 +475,7 @@ namespace ImageProcessor.UnitTests
[Test]
public void ImageIsResized()
{
+ int i = 0;
const int NewSize = 150;
foreach (ImageFactory imageFactory in this.ListInputImages())
{
@@ -429,6 +483,8 @@ namespace ImageProcessor.UnitTests
imageFactory.Image.Width.Should().Be(NewSize, "because the new image's size should be {0}x{0}", NewSize);
imageFactory.Image.Height.Should().Be(NewSize, "because the new image's size should be {0}x{0}", NewSize);
+
+ imageFactory.Format(new ImageProcessor.Imaging.Formats.JpegFormat()).Save("./output/resized-" + i++.ToString() + ".jpg");
}
}
@@ -438,6 +494,7 @@ namespace ImageProcessor.UnitTests
[Test]
public void ImageIsResizedWithLayer()
{
+ int i = 0;
const int NewSize = 150;
foreach (ImageFactory imageFactory in this.ListInputImages())
{
@@ -445,6 +502,8 @@ namespace ImageProcessor.UnitTests
imageFactory.Image.Width.Should().Be(NewSize, "because the new image's size should be {0}x{0}", NewSize);
imageFactory.Image.Height.Should().Be(NewSize, "because the new image's size should be {0}x{0}", NewSize);
+
+ imageFactory.Format(new ImageProcessor.Imaging.Formats.JpegFormat()).Save("./output/resizedlayer-" + i++.ToString() + ".jpg");
}
}
@@ -454,6 +513,7 @@ namespace ImageProcessor.UnitTests
[Test]
public void ImageIsRotated()
{
+ int i = 0;
foreach (ImageFactory imageFactory in this.ListInputImages())
{
Image original = (Image)imageFactory.Image.Clone();
@@ -461,6 +521,8 @@ namespace ImageProcessor.UnitTests
imageFactory.Image.Width.Should().Be(original.Height, "because the rotated image dimensions should have been switched");
imageFactory.Image.Height.Should().Be(original.Width, "because the rotated image dimensions should have been switched");
+
+ imageFactory.Format(new ImageProcessor.Imaging.Formats.JpegFormat()).Save("./output/rotated-" + i++.ToString() + ".jpg");
}
}
@@ -470,6 +532,7 @@ namespace ImageProcessor.UnitTests
[Test]
public void ImageIsRotatedInside()
{
+ int i = 0;
foreach (ImageFactory imageFactory in this.ListInputImages())
{
Image original = (Image)imageFactory.Image.Clone();
@@ -477,6 +540,31 @@ namespace ImageProcessor.UnitTests
imageFactory.Image.Width.Should().Be(original.Width, "because the rotated image dimensions should not have changed");
imageFactory.Image.Height.Should().Be(original.Height, "because the rotated image dimensions should not have changed");
+
+ AssertionHelpers.AssertImagesAreDifferent(original, imageFactory.Image, "because the inside image should have been rotated on {0}", imageFactory.ImagePath);
+
+ imageFactory.Format(new ImageProcessor.Imaging.Formats.JpegFormat()).Save("./output/rotatebounded-" + i++.ToString() + ".jpg");
+ }
+ }
+
+ ///
+ /// Tests that the image's inside is rotated counter-clockwise
+ ///
+ [Test]
+ public void ImageIsRotatedInsideCounterClockwise()
+ {
+ int i = 0;
+ foreach (ImageFactory imageFactory in this.ListInputImages())
+ {
+ Image original = (Image)imageFactory.Image.Clone();
+ imageFactory.RotateBounded(-45, true);
+
+ imageFactory.Image.Width.Should().Be(original.Width, "because the rotated image dimensions should not have changed");
+ imageFactory.Image.Height.Should().Be(original.Height, "because the rotated image dimensions should not have changed");
+
+ AssertionHelpers.AssertImagesAreDifferent(original, imageFactory.Image, "because the inside image should have been rotated on {0}", imageFactory.ImagePath);
+
+ imageFactory.Format(new ImageProcessor.Imaging.Formats.JpegFormat()).Save("./output/rotateboundedccw-" + i++.ToString() + ".jpg");
}
}
@@ -486,6 +574,7 @@ namespace ImageProcessor.UnitTests
[Test]
public void ImageIsRotatedInsideAndResized()
{
+ int i = 0;
foreach (ImageFactory imageFactory in this.ListInputImages())
{
Image original = (Image)imageFactory.Image.Clone();
@@ -493,6 +582,10 @@ namespace ImageProcessor.UnitTests
imageFactory.Image.Width.Should().NotBe(original.Width, "because the rotated image dimensions should have changed");
imageFactory.Image.Height.Should().NotBe(original.Height, "because the rotated image dimensions should have changed");
+
+ AssertionHelpers.AssertImagesAreDifferent(original, imageFactory.Image, "because the inside image should have been rotated on {0}", imageFactory.ImagePath);
+
+ imageFactory.Format(new ImageProcessor.Imaging.Formats.JpegFormat()).Save("./output/rotateboundedresized-" + i++.ToString() + ".jpg");
}
}
@@ -502,6 +595,7 @@ namespace ImageProcessor.UnitTests
[Test]
public void HueIsModified()
{
+ int i = 0;
foreach (ImageFactory imageFactory in this.ListInputImages())
{
Image original = (Image)imageFactory.Image.Clone();
@@ -513,6 +607,8 @@ namespace ImageProcessor.UnitTests
imageFactory.Hue(116, true);
AssertionHelpers.AssertImagesAreDifferent(original, imageFactory.Image, "because the hue+rotate operation should have been applied on {0}", imageFactory.ImagePath);
+
+ imageFactory.Format(new ImageProcessor.Imaging.Formats.JpegFormat()).Save("./output/hue-" + i++.ToString() + ".jpg");
}
}
@@ -522,11 +618,14 @@ namespace ImageProcessor.UnitTests
[Test]
public void PixelateEffectIsApplied()
{
+ int i = 0;
foreach (ImageFactory imageFactory in this.ListInputImages())
{
Image original = (Image)imageFactory.Image.Clone();
imageFactory.Pixelate(8);
AssertionHelpers.AssertImagesAreDifferent(original, imageFactory.Image, "because the pixelate operation should have been applied on {0}", imageFactory.ImagePath);
+
+ imageFactory.Format(new ImageProcessor.Imaging.Formats.JpegFormat()).Save("./output/pixelate-" + i++.ToString() + ".jpg");
}
}
@@ -552,11 +651,14 @@ namespace ImageProcessor.UnitTests
[Test]
public void ColorIsReplaced()
{
+ int i = 0;
foreach (ImageFactory imageFactory in this.ListInputImages())
{
Image original = (Image)imageFactory.Image.Clone();
imageFactory.ReplaceColor(Color.White, Color.Black, 90);
AssertionHelpers.AssertImagesAreDifferent(original, imageFactory.Image, "because the color replace operation should have been applied on {0}", imageFactory.ImagePath);
+
+ imageFactory.Format(new ImageProcessor.Imaging.Formats.JpegFormat()).Save("./output/colorreplace-" + i++.ToString() + ".jpg");
}
}
@@ -566,6 +668,7 @@ namespace ImageProcessor.UnitTests
[Test]
public void EdgeDetectionEffectIsApplied()
{
+ int i = 0;
foreach (ImageFactory imageFactory in this.ListInputImages())
{
Image original = (Image)imageFactory.Image.Clone();
@@ -583,13 +686,18 @@ namespace ImageProcessor.UnitTests
new SobelEdgeFilter()
};
+ int j = 0;
foreach (IEdgeFilter filter in filters)
{
imageFactory.DetectEdges(filter);
AssertionHelpers.AssertImagesAreDifferent(original, imageFactory.Image, "because the edge operation should have been applied on {0}", imageFactory.ImagePath);
imageFactory.Reset();
AssertionHelpers.AssertImagesAreIdentical(original, imageFactory.Image, "because the image should be reset");
+
+ imageFactory.Format(new ImageProcessor.Imaging.Formats.JpegFormat()).Save("./output/edgefilter-" + j++.ToString() + "-image-" + i.ToString() + ".jpg");
}
+
+ i++;
}
}
diff --git a/src/ImageProcessor.UnitTests/ImageProcessor.UnitTests.csproj b/src/ImageProcessor.UnitTests/ImageProcessor.UnitTests.csproj
index 1d808f963..f7a94845a 100644
--- a/src/ImageProcessor.UnitTests/ImageProcessor.UnitTests.csproj
+++ b/src/ImageProcessor.UnitTests/ImageProcessor.UnitTests.csproj
@@ -134,6 +134,9 @@
PreserveNewest
+
+ PreserveNewest
+
PreserveNewest
diff --git a/src/ImageProcessor.UnitTests/Images/stretched.jpg b/src/ImageProcessor.UnitTests/Images/stretched.jpg
new file mode 100644
index 000000000..8e7f73148
--- /dev/null
+++ b/src/ImageProcessor.UnitTests/Images/stretched.jpg
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:1444d3336f0f04126c31850ff9dd89205bd7a553f7d4d1eb1df406fb6c344fa3
+size 32300
diff --git a/src/ImageProcessor.UnitTests/Imaging/Helpers/ImageMathsUnitTests.cs b/src/ImageProcessor.UnitTests/Imaging/Helpers/ImageMathsUnitTests.cs
index 3e1ffdfb3..f8d56fd54 100644
--- a/src/ImageProcessor.UnitTests/Imaging/Helpers/ImageMathsUnitTests.cs
+++ b/src/ImageProcessor.UnitTests/Imaging/Helpers/ImageMathsUnitTests.cs
@@ -22,6 +22,7 @@
[TestCase(100, 100, 45, 141, 141)]
[TestCase(100, 100, 30, 137, 137)]
[TestCase(100, 200, 50, 217, 205)]
+ [TestCase(100, 200, -50, 217, 205)]
public void BoundingRotatedRectangleIsCalculated(int width, int height, float angle, int expectedWidth, int expectedHeight)
{
Rectangle result = ImageMaths.GetBoundingRotatedRectangle(width, height, angle);
@@ -44,11 +45,16 @@
[TestCase(200, 100, 45, 2.12f)]
[TestCase(600, 450, 20, 1.39f)]
[TestCase(600, 450, 45, 1.64f)]
+ [TestCase(100, 200, -45, 1.22f)]
public void RotationZoomIsCalculated(int imageWidth, int imageHeight, float angle, float expected)
{
float result = ImageMaths.ZoomAfterRotation(imageWidth, imageHeight, angle);
result.Should().BeApproximately(expected, 0.01f, "because the zoom level after rotation should have been calculated");
+
+ result.Should().BePositive("because we're always zooming in so the zoom level should always be positive");
+
+ result.Should().BeGreaterOrEqualTo(1, "because the zoom should always increase the size and not reduce it");
}
}
}
\ No newline at end of file
diff --git a/src/ImageProcessor/Imaging/Helpers/ImageMaths.cs b/src/ImageProcessor/Imaging/Helpers/ImageMaths.cs
index d23219840..f8ebc5d90 100644
--- a/src/ImageProcessor/Imaging/Helpers/ImageMaths.cs
+++ b/src/ImageProcessor/Imaging/Helpers/ImageMaths.cs
@@ -316,7 +316,7 @@ namespace ImageProcessor.Imaging.Helpers
/// The zoom needed
public static float ZoomAfterRotation(int imageWidth, int imageHeight, float angleInDegrees)
{
- double radians = DegreesToRadians(angleInDegrees);
+ double radians = Math.Abs(DegreesToRadians(angleInDegrees));
double radiansSin = Math.Sin(radians);
double radiansCos = Math.Cos(radians);