Browse Source

Refactor helper to reduce code duplication

af/merge-core
James Jackson-South 7 years ago
parent
commit
855e75f674
  1. 50
      src/ImageSharp/Processing/Extensions/ResizeExtensions.cs
  2. 35
      src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeHelper.cs
  3. 51
      src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs
  4. 9
      src/ImageSharp/Processing/ResizeMode.cs
  5. 5
      src/ImageSharp/Processing/ResizeOptions.cs

50
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. // Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.Processing.Processors.Transforms; using SixLabors.ImageSharp.Processing.Processors.Transforms;
@ -12,16 +12,6 @@ namespace SixLabors.ImageSharp.Processing
/// </summary> /// </summary>
public static class ResizeExtensions public static class ResizeExtensions
{ {
/// <summary>
/// Resizes an image in accordance with the given <see cref="ResizeOptions"/>.
/// </summary>
/// <param name="source">The image to resize.</param>
/// <param name="options">The resize options.</param>
/// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
/// <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>
public static IImageProcessingContext Resize(this IImageProcessingContext source, ResizeOptions options)
=> source.ApplyProcessor(new ResizeProcessor(options, source.GetCurrentSize()));
/// <summary> /// <summary>
/// Resizes an image to the given <see cref="Size"/>. /// Resizes an image to the given <see cref="Size"/>.
/// </summary> /// </summary>
@ -128,7 +118,18 @@ namespace SixLabors.ImageSharp.Processing
Rectangle sourceRectangle, Rectangle sourceRectangle,
Rectangle targetRectangle, Rectangle targetRectangle,
bool compand) 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);
}
/// <summary> /// <summary>
/// Resizes an image to the given width and height with the given sampler and source rectangle. /// 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, IResampler sampler,
Rectangle targetRectangle, Rectangle targetRectangle,
bool compand) 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);
}
/// <summary>
/// Resizes an image in accordance with the given <see cref="ResizeOptions"/>.
/// </summary>
/// <param name="source">The image to resize.</param>
/// <param name="options">The resize options.</param>
/// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
/// <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>
public static IImageProcessingContext Resize(this IImageProcessingContext source, ResizeOptions options)
=> source.ApplyProcessor(new ResizeProcessor(options, source.GetCurrentSize()));
} }
} }

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

@ -36,6 +36,11 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
int width = options.Size.Width; int width = options.Size.Width;
int height = options.Size.Height; 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. // Ensure target size is populated across both dimensions.
// These dimensions are used to calculate the final dimensions determined by the mode algorithm. // 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. // 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)); 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) switch (options.Mode)
{ {
case ResizeMode.Crop: case ResizeMode.Crop:
@ -66,8 +68,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
return CalculateMaxRectangle(sourceSize, width, height); return CalculateMaxRectangle(sourceSize, width, height);
case ResizeMode.Min: case ResizeMode.Min:
return CalculateMinRectangle(sourceSize, width, height); return CalculateMinRectangle(sourceSize, width, height);
case ResizeMode.Manual:
return CalculateManualRectangle(options, width, height);
// Last case ResizeMode.Stretch: // case ResizeMode.Stretch:
default: default:
return (new Size(width, height), new Rectangle(0, 0, width, height)); 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. // 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)); 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);
} }
} }

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

@ -13,45 +13,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
/// </summary> /// </summary>
public class ResizeProcessor : IImageProcessor public class ResizeProcessor : IImageProcessor
{ {
/// <summary>
/// Initializes a new instance of the <see cref="ResizeProcessor"/> class.
/// </summary>
/// <param name="sampler">The <see cref="IResampler"/>.</param>
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
/// <param name="sourceSize">The size of the source image.</param>
/// <param name="targetRectangle">The target rectangle to resize into.</param>
/// <param name="compand">A value indicating whether to apply RGBA companding.</param>
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;
}
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="ResizeProcessor"/> class. /// Initializes a new instance of the <see cref="ResizeProcessor"/> class.
/// </summary> /// </summary>
@ -71,18 +32,6 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
this.Compand = options.Compand; this.Compand = options.Compand;
} }
/// <summary>
/// Initializes a new instance of the <see cref="ResizeProcessor"/> class.
/// </summary>
/// <param name="sampler">The sampler to perform the resize operation.</param>
/// <param name="width">The target width.</param>
/// <param name="height">The target height.</param>
/// <param name="sourceSize">The source image size</param>
public ResizeProcessor(IResampler sampler, int width, int height, Size sourceSize)
: this(sampler, width, height, sourceSize, new Rectangle(0, 0, width, height), false)
{
}
/// <summary> /// <summary>
/// Gets the sampler to perform the resize operation. /// Gets the sampler to perform the resize operation.
/// </summary> /// </summary>

9
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. // Licensed under the Apache License, Version 2.0.
namespace SixLabors.ImageSharp.Processing namespace SixLabors.ImageSharp.Processing
@ -42,6 +42,11 @@ namespace SixLabors.ImageSharp.Processing
/// <summary> /// <summary>
/// Stretches the resized image to fit the bounds of its container. /// Stretches the resized image to fit the bounds of its container.
/// </summary> /// </summary>
Stretch Stretch,
/// <summary>
/// The target location and size of the resized image has been manually set.
/// </summary>
Manual
} }
} }

5
src/ImageSharp/Processing/ResizeOptions.cs

@ -41,5 +41,10 @@ namespace SixLabors.ImageSharp.Processing
/// or expand individual pixel colors the value on processing. /// or expand individual pixel colors the value on processing.
/// </summary> /// </summary>
public bool Compand { get; set; } = false; public bool Compand { get; set; } = false;
/// <summary>
/// Gets or sets the target rectangle to resize into.
/// </summary>
public Rectangle? TargetRectangle { get; set; }
} }
} }

Loading…
Cancel
Save