2021-08-10 23:55:37 +02:00
|
|
|
using System;
|
2021-07-08 13:48:44 +02:00
|
|
|
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
|
|
|
|
|
{
|
2021-08-06 12:59:23 +02:00
|
|
|
/// <summary>
|
|
|
|
|
/// Allows the cropping of images.
|
|
|
|
|
/// </summary>
|
2021-07-08 13:48:44 +02:00
|
|
|
public class CropWebProcessor : IImageWebProcessor
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
2021-08-10 23:55:37 +02:00
|
|
|
/// The command constant for the crop coordinates.
|
2021-07-08 13:48:44 +02:00
|
|
|
/// </summary>
|
2021-08-10 23:55:37 +02:00
|
|
|
public const string Coordinates = "cc";
|
2021-08-06 12:59:23 +02:00
|
|
|
|
|
|
|
|
/// <inheritdoc/>
|
|
|
|
|
public IEnumerable<string> Commands { get; } = new[]
|
2021-07-08 13:48:44 +02:00
|
|
|
{
|
2021-08-10 23:55:37 +02:00
|
|
|
Coordinates
|
2021-08-06 12:59:23 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/// <inheritdoc/>
|
|
|
|
|
public FormattedImage Process(FormattedImage image, ILogger logger, IDictionary<string, string> commands, CommandParser parser, CultureInfo culture)
|
|
|
|
|
{
|
2021-08-10 23:55:37 +02:00
|
|
|
RectangleF? coordinates = GetCoordinates(commands, parser, culture);
|
|
|
|
|
if (coordinates != null)
|
2021-07-08 13:48:44 +02:00
|
|
|
{
|
2021-08-11 09:53:58 +02:00
|
|
|
// Convert the coordinates to a pixel based rectangle
|
2021-08-10 23:55:37 +02:00
|
|
|
int sourceWidth = image.Image.Width;
|
|
|
|
|
int sourceHeight = image.Image.Height;
|
2021-08-11 09:53:58 +02:00
|
|
|
int x = (int)MathF.Round(coordinates.Value.X * sourceWidth);
|
|
|
|
|
int y = (int)MathF.Round(coordinates.Value.Y * sourceHeight);
|
|
|
|
|
int width = (int)MathF.Round(coordinates.Value.Width * sourceWidth);
|
|
|
|
|
int height = (int)MathF.Round(coordinates.Value.Height * sourceHeight);
|
2021-08-10 23:55:37 +02:00
|
|
|
|
|
|
|
|
var cropRectangle = new Rectangle(x, y, width, height);
|
2021-08-09 14:52:07 +02:00
|
|
|
|
|
|
|
|
image.Image.Mutate(x => x.Crop(cropRectangle));
|
2021-07-08 13:48:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return image;
|
|
|
|
|
}
|
|
|
|
|
|
2021-08-10 23:55:37 +02:00
|
|
|
private static RectangleF? GetCoordinates(IDictionary<string, string> commands, CommandParser parser, CultureInfo culture)
|
2021-07-08 13:48:44 +02:00
|
|
|
{
|
2021-08-10 23:55:37 +02:00
|
|
|
float[] coordinates = parser.ParseValue<float[]>(commands.GetValueOrDefault(Coordinates), culture);
|
2021-08-09 12:00:37 +02:00
|
|
|
|
|
|
|
|
if (coordinates.Length != 4)
|
|
|
|
|
{
|
|
|
|
|
return null;
|
|
|
|
|
}
|
2021-08-06 12:59:23 +02:00
|
|
|
|
2021-08-11 09:53:58 +02:00
|
|
|
// The right and bottom values are actually the distance from those sides, so convert them into real coordinates
|
|
|
|
|
return RectangleF.FromLTRB(coordinates[0], coordinates[1], 1 - coordinates[2], 1 - coordinates[3]);
|
2021-07-08 13:48:44 +02:00
|
|
|
}
|
2021-08-06 12:59:23 +02:00
|
|
|
}
|
2021-07-08 13:48:44 +02:00
|
|
|
}
|