diff --git a/src/ImageSharp/Processing/Extensions/ResizeExtensions.cs b/src/ImageSharp/Processing/Extensions/ResizeExtensions.cs
index 81b1c2c66..f494ed909 100644
--- a/src/ImageSharp/Processing/Extensions/ResizeExtensions.cs
+++ b/src/ImageSharp/Processing/Extensions/ResizeExtensions.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.Processing.Processors.Transforms;
@@ -12,16 +12,6 @@ namespace SixLabors.ImageSharp.Processing
///
public static class ResizeExtensions
{
- ///
- /// Resizes an image in accordance with the given .
- ///
- /// The image to resize.
- /// The resize options.
- /// The to allow chaining of operations.
- /// Passing zero for one of height or width within the resize options will automatically preserve the aspect ratio of the original image or the nearest possible ratio.
- public static IImageProcessingContext Resize(this IImageProcessingContext source, ResizeOptions options)
- => source.ApplyProcessor(new ResizeProcessor(options, source.GetCurrentSize()));
-
///
/// Resizes an image to the given .
///
@@ -128,7 +118,18 @@ namespace SixLabors.ImageSharp.Processing
Rectangle sourceRectangle,
Rectangle targetRectangle,
bool compand)
- => source.ApplyProcessor(new ResizeProcessor(sampler, width, height, source.GetCurrentSize(), targetRectangle, compand), sourceRectangle);
+ {
+ var options = new ResizeOptions
+ {
+ Size = new Size(width, height),
+ Mode = ResizeMode.Manual,
+ Sampler = sampler,
+ TargetRectangle = targetRectangle,
+ Compand = compand
+ };
+
+ return source.ApplyProcessor(new ResizeProcessor(options, source.GetCurrentSize()), sourceRectangle);
+ }
///
/// Resizes an image to the given width and height with the given sampler and source rectangle.
@@ -150,6 +151,27 @@ namespace SixLabors.ImageSharp.Processing
IResampler sampler,
Rectangle targetRectangle,
bool compand)
- => source.ApplyProcessor(new ResizeProcessor(sampler, width, height, source.GetCurrentSize(), targetRectangle, compand));
+ {
+ var options = new ResizeOptions
+ {
+ Size = new Size(width, height),
+ Mode = ResizeMode.Manual,
+ Sampler = sampler,
+ TargetRectangle = targetRectangle,
+ Compand = compand
+ };
+
+ return Resize(source, options);
+ }
+
+ ///
+ /// Resizes an image in accordance with the given .
+ ///
+ /// The image to resize.
+ /// The resize options.
+ /// The to allow chaining of operations.
+ /// Passing zero for one of height or width within the resize options will automatically preserve the aspect ratio of the original image or the nearest possible ratio.
+ public static IImageProcessingContext Resize(this IImageProcessingContext source, ResizeOptions options)
+ => source.ApplyProcessor(new ResizeProcessor(options, source.GetCurrentSize()));
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeHelper.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeHelper.cs
index c9df1b254..eacd3834f 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeHelper.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeHelper.cs
@@ -36,6 +36,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
int width = options.Size.Width;
int height = options.Size.Height;
+ if (width <= 0 && height <= 0)
+ {
+ ThrowInvalid($"Target width {width} and height {height} must be greater than zero.");
+ }
+
// Ensure target size is populated across both dimensions.
// These dimensions are used to calculate the final dimensions determined by the mode algorithm.
// If only one of the incoming dimensions is 0, it will be modified here to maintain aspect ratio.
@@ -51,9 +56,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
height = (int)MathF.Max(Min, MathF.Round(sourceSize.Height * width / (float)sourceSize.Width));
}
- Guard.MustBeGreaterThan(width, 0, nameof(width));
- Guard.MustBeGreaterThan(height, 0, nameof(height));
-
switch (options.Mode)
{
case ResizeMode.Crop:
@@ -66,8 +68,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
return CalculateMaxRectangle(sourceSize, width, height);
case ResizeMode.Min:
return CalculateMinRectangle(sourceSize, width, height);
+ case ResizeMode.Manual:
+ return CalculateManualRectangle(options, width, height);
- // Last case ResizeMode.Stretch:
+ // case ResizeMode.Stretch:
default:
return (new Size(width, height), new Rectangle(0, 0, width, height));
}
@@ -397,5 +401,28 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
// Target image width and height can be different to the rectangle width and height.
return (new Size(width, height), new Rectangle(targetX, targetY, targetWidth, targetHeight));
}
+
+ private static (Size, Rectangle) CalculateManualRectangle(
+ ResizeOptions options,
+ int width,
+ int height)
+ {
+ if (!options.TargetRectangle.HasValue)
+ {
+ ThrowInvalid("Manual resizing requires a target location and size.");
+ }
+
+ Rectangle targetRectangle = options.TargetRectangle.Value;
+
+ int targetX = targetRectangle.X;
+ int targetY = targetRectangle.Y;
+ int targetWidth = targetRectangle.Width > 0 ? targetRectangle.Width : width;
+ int targetHeight = targetRectangle.Height > 0 ? targetRectangle.Height : height;
+
+ // Target image width and height can be different to the rectangle width and height.
+ return (new Size(width, height), new Rectangle(targetX, targetY, targetWidth, targetHeight));
+ }
+
+ private static void ThrowInvalid(string message) => throw new InvalidOperationException(message);
}
}
diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs
index 6f5f09e71..35e22757c 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs
@@ -13,45 +13,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
///
public class ResizeProcessor : IImageProcessor
{
- ///
- /// Initializes a new instance of the class.
- ///
- /// The .
- /// The width.
- /// The height.
- /// The size of the source image.
- /// The target rectangle to resize into.
- /// A value indicating whether to apply RGBA companding.
- public ResizeProcessor(IResampler sampler, int width, int height, Size sourceSize, Rectangle targetRectangle, bool compand)
- {
- Guard.NotNull(sampler, nameof(sampler));
-
- // Ensure target size is populated across both dimensions.
- // 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 the minimum is is kept.
- const int Min = 1;
- if (width == 0 && height > 0)
- {
- width = (int)MathF.Max(Min, MathF.Round(sourceSize.Width * height / (float)sourceSize.Height));
- targetRectangle.Width = width;
- }
-
- if (height == 0 && width > 0)
- {
- height = (int)MathF.Max(Min, MathF.Round(sourceSize.Height * width / (float)sourceSize.Width));
- targetRectangle.Height = height;
- }
-
- Guard.MustBeGreaterThan(width, 0, nameof(width));
- Guard.MustBeGreaterThan(height, 0, nameof(height));
-
- this.Sampler = sampler;
- this.TargetWidth = width;
- this.TargetHeight = height;
- this.TargetRectangle = targetRectangle;
- this.Compand = compand;
- }
-
///
/// Initializes a new instance of the class.
///
@@ -71,18 +32,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
this.Compand = options.Compand;
}
- ///
- /// Initializes a new instance of the class.
- ///
- /// The sampler to perform the resize operation.
- /// The target width.
- /// The target height.
- /// The source image size
- public ResizeProcessor(IResampler sampler, int width, int height, Size sourceSize)
- : this(sampler, width, height, sourceSize, new Rectangle(0, 0, width, height), false)
- {
- }
-
///
/// Gets the sampler to perform the resize operation.
///
diff --git a/src/ImageSharp/Processing/ResizeMode.cs b/src/ImageSharp/Processing/ResizeMode.cs
index 6adeac66d..142a926b3 100644
--- a/src/ImageSharp/Processing/ResizeMode.cs
+++ b/src/ImageSharp/Processing/ResizeMode.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Six Labors and contributors.
+// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
namespace SixLabors.ImageSharp.Processing
@@ -42,6 +42,11 @@ namespace SixLabors.ImageSharp.Processing
///
/// Stretches the resized image to fit the bounds of its container.
///
- Stretch
+ Stretch,
+
+ ///
+ /// The target location and size of the resized image has been manually set.
+ ///
+ Manual
}
}
diff --git a/src/ImageSharp/Processing/ResizeOptions.cs b/src/ImageSharp/Processing/ResizeOptions.cs
index 96de1eee1..ef88dc35b 100644
--- a/src/ImageSharp/Processing/ResizeOptions.cs
+++ b/src/ImageSharp/Processing/ResizeOptions.cs
@@ -41,5 +41,10 @@ namespace SixLabors.ImageSharp.Processing
/// or expand individual pixel colors the value on processing.
///
public bool Compand { get; set; } = false;
+
+ ///
+ /// Gets or sets the target rectangle to resize into.
+ ///
+ public Rectangle? TargetRectangle { get; set; }
}
}