Skip to content

Commit a6fd96b

Browse files
Refactor helper to reduce code duplication
1 parent 4edf86f commit a6fd96b

File tree

5 files changed

+79
-71
lines changed

5 files changed

+79
-71
lines changed

src/ImageSharp/Processing/Extensions/ResizeExtensions.cs

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) Six Labors and contributors.
1+
// Copyright (c) Six Labors and contributors.
22
// Licensed under the Apache License, Version 2.0.
33

44
using SixLabors.ImageSharp.Processing.Processors.Transforms;
@@ -12,16 +12,6 @@ namespace SixLabors.ImageSharp.Processing
1212
/// </summary>
1313
public static class ResizeExtensions
1414
{
15-
/// <summary>
16-
/// Resizes an image in accordance with the given <see cref="ResizeOptions"/>.
17-
/// </summary>
18-
/// <param name="source">The image to resize.</param>
19-
/// <param name="options">The resize options.</param>
20-
/// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
21-
/// <remarks>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.</remarks>
22-
public static IImageProcessingContext Resize(this IImageProcessingContext source, ResizeOptions options)
23-
=> source.ApplyProcessor(new ResizeProcessor(options, source.GetCurrentSize()));
24-
2515
/// <summary>
2616
/// Resizes an image to the given <see cref="Size"/>.
2717
/// </summary>
@@ -128,7 +118,18 @@ public static IImageProcessingContext Resize(
128118
Rectangle sourceRectangle,
129119
Rectangle targetRectangle,
130120
bool compand)
131-
=> source.ApplyProcessor(new ResizeProcessor(sampler, width, height, source.GetCurrentSize(), targetRectangle, compand), sourceRectangle);
121+
{
122+
var options = new ResizeOptions
123+
{
124+
Size = new Size(width, height),
125+
Mode = ResizeMode.Manual,
126+
Sampler = sampler,
127+
TargetRectangle = targetRectangle,
128+
Compand = compand
129+
};
130+
131+
return source.ApplyProcessor(new ResizeProcessor(options, source.GetCurrentSize()), sourceRectangle);
132+
}
132133

133134
/// <summary>
134135
/// Resizes an image to the given width and height with the given sampler and source rectangle.
@@ -150,6 +151,27 @@ public static IImageProcessingContext Resize(
150151
IResampler sampler,
151152
Rectangle targetRectangle,
152153
bool compand)
153-
=> source.ApplyProcessor(new ResizeProcessor(sampler, width, height, source.GetCurrentSize(), targetRectangle, compand));
154+
{
155+
var options = new ResizeOptions
156+
{
157+
Size = new Size(width, height),
158+
Mode = ResizeMode.Manual,
159+
Sampler = sampler,
160+
TargetRectangle = targetRectangle,
161+
Compand = compand
162+
};
163+
164+
return Resize(source, options);
165+
}
166+
167+
/// <summary>
168+
/// Resizes an image in accordance with the given <see cref="ResizeOptions"/>.
169+
/// </summary>
170+
/// <param name="source">The image to resize.</param>
171+
/// <param name="options">The resize options.</param>
172+
/// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
173+
/// <remarks>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.</remarks>
174+
public static IImageProcessingContext Resize(this IImageProcessingContext source, ResizeOptions options)
175+
=> source.ApplyProcessor(new ResizeProcessor(options, source.GetCurrentSize()));
154176
}
155-
}
177+
}

src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeHelper.cs

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@ public static (Size, Rectangle) CalculateTargetLocationAndBounds(Size sourceSize
3636
int width = options.Size.Width;
3737
int height = options.Size.Height;
3838

39+
if (width <= 0 && height <= 0)
40+
{
41+
ThrowInvalid($"Target width {width} and height {height} must be greater than zero.");
42+
}
43+
3944
// Ensure target size is populated across both dimensions.
4045
// These dimensions are used to calculate the final dimensions determined by the mode algorithm.
4146
// If only one of the incoming dimensions is 0, it will be modified here to maintain aspect ratio.
@@ -51,9 +56,6 @@ public static (Size, Rectangle) CalculateTargetLocationAndBounds(Size sourceSize
5156
height = (int)MathF.Max(Min, MathF.Round(sourceSize.Height * width / (float)sourceSize.Width));
5257
}
5358

54-
Guard.MustBeGreaterThan(width, 0, nameof(width));
55-
Guard.MustBeGreaterThan(height, 0, nameof(height));
56-
5759
switch (options.Mode)
5860
{
5961
case ResizeMode.Crop:
@@ -66,8 +68,10 @@ public static (Size, Rectangle) CalculateTargetLocationAndBounds(Size sourceSize
6668
return CalculateMaxRectangle(sourceSize, width, height);
6769
case ResizeMode.Min:
6870
return CalculateMinRectangle(sourceSize, width, height);
71+
case ResizeMode.Manual:
72+
return CalculateManualRectangle(options, width, height);
6973

70-
// Last case ResizeMode.Stretch:
74+
// case ResizeMode.Stretch:
7175
default:
7276
return (new Size(width, height), new Rectangle(0, 0, width, height));
7377
}
@@ -397,5 +401,28 @@ private static (Size, Rectangle) CalculatePadRectangle(
397401
// Target image width and height can be different to the rectangle width and height.
398402
return (new Size(width, height), new Rectangle(targetX, targetY, targetWidth, targetHeight));
399403
}
404+
405+
private static (Size, Rectangle) CalculateManualRectangle(
406+
ResizeOptions options,
407+
int width,
408+
int height)
409+
{
410+
if (!options.TargetRectangle.HasValue)
411+
{
412+
ThrowInvalid("Manual resizing requires a target location and size.");
413+
}
414+
415+
Rectangle targetRectangle = options.TargetRectangle.Value;
416+
417+
int targetX = targetRectangle.X;
418+
int targetY = targetRectangle.Y;
419+
int targetWidth = targetRectangle.Width > 0 ? targetRectangle.Width : width;
420+
int targetHeight = targetRectangle.Height > 0 ? targetRectangle.Height : height;
421+
422+
// Target image width and height can be different to the rectangle width and height.
423+
return (new Size(width, height), new Rectangle(targetX, targetY, targetWidth, targetHeight));
424+
}
425+
426+
private static void ThrowInvalid(string message) => throw new InvalidOperationException(message);
400427
}
401428
}

src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs

Lines changed: 0 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -13,45 +13,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
1313
/// </summary>
1414
public class ResizeProcessor : IImageProcessor
1515
{
16-
/// <summary>
17-
/// Initializes a new instance of the <see cref="ResizeProcessor"/> class.
18-
/// </summary>
19-
/// <param name="sampler">The <see cref="IResampler"/>.</param>
20-
/// <param name="width">The width.</param>
21-
/// <param name="height">The height.</param>
22-
/// <param name="sourceSize">The size of the source image.</param>
23-
/// <param name="targetRectangle">The target rectangle to resize into.</param>
24-
/// <param name="compand">A value indicating whether to apply RGBA companding.</param>
25-
public ResizeProcessor(IResampler sampler, int width, int height, Size sourceSize, Rectangle targetRectangle, bool compand)
26-
{
27-
Guard.NotNull(sampler, nameof(sampler));
28-
29-
// Ensure target size is populated across both dimensions.
30-
// If only one of the incoming dimensions is 0, it will be modified here to maintain aspect ratio.
31-
// If it is not possible to keep aspect ratio, make sure at least the minimum is is kept.
32-
const int Min = 1;
33-
if (width == 0 && height > 0)
34-
{
35-
width = (int)MathF.Max(Min, MathF.Round(sourceSize.Width * height / (float)sourceSize.Height));
36-
targetRectangle.Width = width;
37-
}
38-
39-
if (height == 0 && width > 0)
40-
{
41-
height = (int)MathF.Max(Min, MathF.Round(sourceSize.Height * width / (float)sourceSize.Width));
42-
targetRectangle.Height = height;
43-
}
44-
45-
Guard.MustBeGreaterThan(width, 0, nameof(width));
46-
Guard.MustBeGreaterThan(height, 0, nameof(height));
47-
48-
this.Sampler = sampler;
49-
this.TargetWidth = width;
50-
this.TargetHeight = height;
51-
this.TargetRectangle = targetRectangle;
52-
this.Compand = compand;
53-
}
54-
5516
/// <summary>
5617
/// Initializes a new instance of the <see cref="ResizeProcessor"/> class.
5718
/// </summary>
@@ -71,18 +32,6 @@ public ResizeProcessor(ResizeOptions options, Size sourceSize)
7132
this.Compand = options.Compand;
7233
}
7334

74-
/// <summary>
75-
/// Initializes a new instance of the <see cref="ResizeProcessor"/> class.
76-
/// </summary>
77-
/// <param name="sampler">The sampler to perform the resize operation.</param>
78-
/// <param name="width">The target width.</param>
79-
/// <param name="height">The target height.</param>
80-
/// <param name="sourceSize">The source image size</param>
81-
public ResizeProcessor(IResampler sampler, int width, int height, Size sourceSize)
82-
: this(sampler, width, height, sourceSize, new Rectangle(0, 0, width, height), false)
83-
{
84-
}
85-
8635
/// <summary>
8736
/// Gets the sampler to perform the resize operation.
8837
/// </summary>

src/ImageSharp/Processing/ResizeMode.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) Six Labors and contributors.
1+
// Copyright (c) Six Labors and contributors.
22
// Licensed under the Apache License, Version 2.0.
33

44
namespace SixLabors.ImageSharp.Processing
@@ -42,6 +42,11 @@ public enum ResizeMode
4242
/// <summary>
4343
/// Stretches the resized image to fit the bounds of its container.
4444
/// </summary>
45-
Stretch
45+
Stretch,
46+
47+
/// <summary>
48+
/// The target location and size of the resized image has been manually set.
49+
/// </summary>
50+
Manual
4651
}
4752
}

src/ImageSharp/Processing/ResizeOptions.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,5 +41,10 @@ public class ResizeOptions
4141
/// or expand individual pixel colors the value on processing.
4242
/// </summary>
4343
public bool Compand { get; set; } = false;
44+
45+
/// <summary>
46+
/// Gets or sets the target rectangle to resize into.
47+
/// </summary>
48+
public Rectangle? TargetRectangle { get; set; }
4449
}
4550
}

0 commit comments

Comments
 (0)