diff --git a/src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs
index 76abc64996..2f1ef68652 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs
@@ -40,25 +40,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
Guard.NotNull(options, nameof(options));
Guard.NotNull(options.Sampler, nameof(options.Sampler));
- int tempWidth = options.Size.Width;
- int tempHeight = options.Size.Height;
+ int targetWidth = options.Size.Width;
+ int targetHeight = options.Size.Height;
// Ensure size is populated across both dimensions.
// These dimensions are used to calculate the final dimensions determined by the mode algorithm.
- if (tempWidth == 0 && tempHeight > 0)
- {
- tempWidth = (int)MathF.Round(sourceSize.Width * tempHeight / (float)sourceSize.Height);
- }
-
- if (tempHeight == 0 && tempWidth > 0)
- {
- tempHeight = (int)MathF.Round(sourceSize.Height * tempWidth / (float)sourceSize.Width);
- }
-
- Guard.MustBeGreaterThan(tempWidth, 0, nameof(tempWidth));
- Guard.MustBeGreaterThan(tempHeight, 0, nameof(tempHeight));
+ EnsureSizeBothDimensions(sourceSize.Width, sourceSize.Height, ref targetWidth, ref targetHeight, out _, out _);
- (Size size, Rectangle rectangle) = ResizeHelper.CalculateTargetLocationAndBounds(sourceSize, options, tempWidth, tempHeight);
+ (Size size, Rectangle rectangle) = ResizeHelper.CalculateTargetLocationAndBounds(sourceSize, options, targetWidth, targetHeight);
this.Sampler = options.Sampler;
this.Width = size.Width;
@@ -95,15 +84,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
Guard.NotNull(sampler, nameof(sampler));
// Ensure size is populated across both dimensions.
- if (width == 0 && height > 0)
+ EnsureSizeBothDimensions(sourceSize.Width, sourceSize.Height, ref width, ref height, out bool changedWidth, out bool changedHeight);
+ if (changedWidth)
{
- width = (int)MathF.Round(sourceSize.Width * height / (float)sourceSize.Height);
resizeRectangle.Width = width;
}
- if (height == 0 && width > 0)
+ if (changedHeight)
{
- height = (int)MathF.Round(sourceSize.Height * width / (float)sourceSize.Width);
resizeRectangle.Height = height;
}
@@ -142,6 +130,43 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
///
public bool Compand { get; }
+ ///
+ /// Makes sure both target dimensions are >= 1.
+ /// If only one of the incoming dimensions is 0, it will be modified here to maintain aspect ratio.
+ /// If it is not possible to keep aspect ratio, make sure at least 1 pixel is kept.
+ ///
+ private static void EnsureSizeBothDimensions(
+ int sourceWidth,
+ int sourceHeight,
+ ref int targetWidth,
+ ref int targetHeight,
+ out bool changedTargetWidth,
+ out bool changedTargetHeight)
+ {
+ if (targetWidth == 0 && targetHeight > 0)
+ {
+ targetWidth = Math.Max(1, (int)MathF.Round(sourceWidth * targetHeight / (float)sourceHeight));
+ changedTargetWidth = true;
+ }
+ else
+ {
+ changedTargetWidth = false;
+ }
+
+ if (targetHeight == 0 && targetWidth > 0)
+ {
+ targetHeight = Math.Max(1, (int)MathF.Round(sourceHeight * targetWidth / (float)sourceWidth));
+ changedTargetHeight = true;
+ }
+ else
+ {
+ changedTargetHeight = false;
+ }
+
+ Guard.MustBeGreaterThan(targetWidth, 0, nameof(targetWidth));
+ Guard.MustBeGreaterThan(targetHeight, 0, nameof(targetHeight));
+ }
+
///
/// Computes the weights to apply at each pixel when resizing.
///
diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs
index 746d8da16e..d1d473bbd2 100644
--- a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs
+++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs
@@ -178,6 +178,32 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms
}
}
+ [Theory]
+ [WithTestPatternImages(100, 10, DefaultPixelType)]
+ public void ResizeWidthCannotKeepAspectKeepsOnePixel(TestImageProvider provider)
+ where TPixel : struct, IPixel
+ {
+ using (Image image = provider.GetImage())
+ {
+ image.Mutate(x => x.Resize(5, 0));
+ Assert.Equal(5, image.Width);
+ Assert.Equal(1, image.Height);
+ }
+ }
+
+ [Theory]
+ [WithTestPatternImages(10, 100, DefaultPixelType)]
+ public void ResizeHeightCannotKeepAspectKeepsOnePixel(TestImageProvider provider)
+ where TPixel : struct, IPixel
+ {
+ using (Image image = provider.GetImage())
+ {
+ image.Mutate(x => x.Resize(0, 5));
+ Assert.Equal(1, image.Width);
+ Assert.Equal(5, image.Height);
+ }
+ }
+
[Theory]
[WithFileCollection(nameof(CommonTestImages), DefaultPixelType)]
public void ResizeWithCropWidthMode(TestImageProvider provider)
@@ -324,7 +350,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms
[InlineData(2, 0)]
public static void BicubicWindowOscillatesCorrectly(float x, float expected)
{
- var sampler = KnownResamplers.Bicubic;
+ IResampler sampler = KnownResamplers.Bicubic;
float result = sampler.GetValue(x);
Assert.Equal(result, expected);
@@ -338,7 +364,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms
[InlineData(2, 0)]
public static void TriangleWindowOscillatesCorrectly(float x, float expected)
{
- var sampler = KnownResamplers.Triangle;
+ IResampler sampler = KnownResamplers.Triangle;
float result = sampler.GetValue(x);
Assert.Equal(result, expected);
@@ -352,7 +378,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms
[InlineData(2, 0)]
public static void Lanczos3WindowOscillatesCorrectly(float x, float expected)
{
- var sampler = KnownResamplers.Lanczos3;
+ IResampler sampler = KnownResamplers.Lanczos3;
float result = sampler.GetValue(x);
Assert.Equal(result, expected);
@@ -366,7 +392,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms
[InlineData(4, 0)]
public static void Lanczos5WindowOscillatesCorrectly(float x, float expected)
{
- var sampler = KnownResamplers.Lanczos5;
+ IResampler sampler = KnownResamplers.Lanczos5;
float result = sampler.GetValue(x);
Assert.Equal(result, expected);