using System.Collections.Generic; using System.Globalization; using Microsoft.Extensions.Logging; using SixLabors.ImageSharp; using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Web; using SixLabors.ImageSharp.Web.Commands; using SixLabors.ImageSharp.Web.Processors; namespace Umbraco.Cms.Web.Common.ImageProcessors { /// /// Allows the cropping of images. /// public class CropWebProcessor : IImageWebProcessor { /// /// The command constant for the crop definition. /// public const string Crop = "crop"; /// /// The command constant for the crop mode. /// public const string Mode = "cropmode"; /// public IEnumerable Commands { get; } = new[] { Crop, Mode }; /// public FormattedImage Process(FormattedImage image, ILogger logger, IDictionary commands, CommandParser parser, CultureInfo culture) { if (GetCrop(commands, parser, culture) is RectangleF crop) { if (GetMode(commands, parser, culture) == CropMode.Percentage) { // Convert the percentage based model of left, top, right, bottom to x, y, width, height int sourceWidth = image.Image.Width; int sourceHeight = image.Image.Height; float left = crop.Left * sourceWidth; float top = crop.Top * sourceHeight; float width = sourceWidth - (sourceWidth * crop.Width) - left; float height = sourceHeight - (sourceHeight * crop.Height) - top; crop = new RectangleF(left, top, width, height); } var cropRectangle = Rectangle.Round(crop); image.Image.Mutate(x => x.Crop(cropRectangle)); } return image; } private static RectangleF? GetCrop(IDictionary commands, CommandParser parser, CultureInfo culture) { float[] coordinates = parser.ParseValue(commands.GetValueOrDefault(Crop), culture); if (coordinates.Length != 4) { return null; } return new RectangleF(coordinates[0], coordinates[1], coordinates[2], coordinates[3]); } private static CropMode GetMode(IDictionary commands, CommandParser parser, CultureInfo culture) => parser.ParseValue(commands.GetValueOrDefault(Mode), culture); } }