From a8dd90d9d61538edb5069491afeaa7662f338407 Mon Sep 17 00:00:00 2001 From: Mole Date: Thu, 8 Jul 2021 13:48:44 +0200 Subject: [PATCH] Add CropWebProcessor --- .../UmbracoBuilder.ImageSharp.cs | 3 + .../ImageProcessors/CropWebProcessor.cs | 78 +++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 src/Umbraco.Web.Common/ImageProcessors/CropWebProcessor.cs diff --git a/src/Umbraco.Web.Common/DependencyInjection/UmbracoBuilder.ImageSharp.cs b/src/Umbraco.Web.Common/DependencyInjection/UmbracoBuilder.ImageSharp.cs index 96bf7017cb..775d36eaf5 100644 --- a/src/Umbraco.Web.Common/DependencyInjection/UmbracoBuilder.ImageSharp.cs +++ b/src/Umbraco.Web.Common/DependencyInjection/UmbracoBuilder.ImageSharp.cs @@ -10,6 +10,7 @@ using SixLabors.ImageSharp.Web.Processors; using SixLabors.ImageSharp.Web.Providers; using Umbraco.Cms.Core.Configuration.Models; using Umbraco.Cms.Core.DependencyInjection; +using Umbraco.Cms.Web.Common.ImageProcessors; namespace Umbraco.Extensions { @@ -51,6 +52,8 @@ namespace Umbraco.Extensions .SetCache() .SetCacheHash() .AddProvider() + .ClearProcessors() // ImageSharp includes the processors by default, so we have to clear and re-add to control the order + .AddProcessor() .AddProcessor() .AddProcessor() .AddProcessor(); diff --git a/src/Umbraco.Web.Common/ImageProcessors/CropWebProcessor.cs b/src/Umbraco.Web.Common/ImageProcessors/CropWebProcessor.cs new file mode 100644 index 0000000000..6393e9455f --- /dev/null +++ b/src/Umbraco.Web.Common/ImageProcessors/CropWebProcessor.cs @@ -0,0 +1,78 @@ +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; +using ImageCropperCropCoordinates = Umbraco.Cms.Core.PropertyEditors.ValueConverters.ImageCropperValue.ImageCropperCropCoordinates; + +namespace Umbraco.Cms.Web.Common.ImageProcessors +{ + public class CropWebProcessor : IImageWebProcessor + { + /// + /// The command constant for the crop definition + /// + public const string Crop = "crop"; + + public FormattedImage Process( + FormattedImage image, + ILogger logger, + IDictionary commands, + CommandParser parser, + CultureInfo culture) + { + ImageCropperCropCoordinates cropCoordinates = GetCropCoordinates(commands); + if (cropCoordinates is null) + { + return image; + } + + Size size = image.Image.Size(); + Rectangle crop = GetCropRectangle(size.Width, size.Height, cropCoordinates); + image.Image.Mutate(x => x.Crop(crop)); + return image; + } + + private static readonly IEnumerable CropCommands = new[] {Crop}; + + public IEnumerable Commands { get; } = CropCommands; + + private static Rectangle GetCropRectangle(int width, int height, ImageCropperCropCoordinates coordinates) + { + + // Get coordinates of top left corner of the rectangle + var topX = decimal.ToInt32(width * coordinates.X1); + var topY = decimal.ToInt32(height * coordinates.Y1); + // Get coordinated of bottom right corner + var bottomX = decimal.ToInt32(width - (width * coordinates.X2)); + var bottomY = decimal.ToInt32(height - (height * coordinates.Y2)); + + // Get width and height of crop + var cropWidth = bottomX - topX; + var cropHeight = bottomY - topY; + + return new Rectangle(topX, topY, cropWidth, cropHeight); + } + + private static ImageCropperCropCoordinates GetCropCoordinates(IDictionary commands) + { + if (!commands.TryGetValue(Crop, out var crop)) + { + return null; + } + + var crops = crop.Split(','); + + return new ImageCropperCropCoordinates() + { + X1 = decimal.Parse(crops[0], CultureInfo.InvariantCulture), + Y1 = decimal.Parse(crops[1], CultureInfo.InvariantCulture), + X2 = decimal.Parse(crops[2], CultureInfo.InvariantCulture), + Y2 = decimal.Parse(crops[3], CultureInfo.InvariantCulture) + }; + } + } +}