using System.Globalization; using Microsoft.AspNetCore.WebUtilities; using Microsoft.Extensions.Primitives; using SixLabors.ImageSharp; using SixLabors.ImageSharp.Web.Processors; using Umbraco.Cms.Core.Media; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Imaging.ImageSharp.ImageProcessors; using static Umbraco.Cms.Core.Models.ImageUrlGenerationOptions; namespace Umbraco.Cms.Imaging.ImageSharp.Media; /// /// Exposes a method that generates an image URL based on the specified options that can be processed by ImageSharp. /// /// public sealed class ImageSharpImageUrlGenerator : IImageUrlGenerator { /// public IEnumerable SupportedImageFileTypes { get; } /// /// Initializes a new instance of the class. /// /// The ImageSharp configuration. public ImageSharpImageUrlGenerator(Configuration configuration) : this(configuration.ImageFormats.SelectMany(f => f.FileExtensions).ToArray()) { } /// /// Initializes a new instance of the class. /// /// The supported image file types/extensions. /// /// This constructor is only used for testing. /// internal ImageSharpImageUrlGenerator(IEnumerable supportedImageFileTypes) => SupportedImageFileTypes = supportedImageFileTypes; /// public string? GetImageUrl(ImageUrlGenerationOptions? options) { if (options?.ImageUrl == null) { return null; } var queryString = new Dictionary(); if (options.Crop is not null) { CropCoordinates? crop = options.Crop; queryString.Add( CropWebProcessor.Coordinates, FormattableString.Invariant($"{crop.Left},{crop.Top},{crop.Right},{crop.Bottom}")); } if (options.FocalPoint is not null) { queryString.Add(ResizeWebProcessor.Xy, FormattableString.Invariant($"{options.FocalPoint.Left},{options.FocalPoint.Top}")); } if (options.ImageCropMode is not null) { queryString.Add(ResizeWebProcessor.Mode, options.ImageCropMode.ToString()?.ToLowerInvariant()); } if (options.ImageCropAnchor is not null) { queryString.Add(ResizeWebProcessor.Anchor, options.ImageCropAnchor.ToString()?.ToLowerInvariant()); } if (options.Width is not null) { queryString.Add(ResizeWebProcessor.Width, options.Width?.ToString(CultureInfo.InvariantCulture)); } if (options.Height is not null) { queryString.Add(ResizeWebProcessor.Height, options.Height?.ToString(CultureInfo.InvariantCulture)); } if (options.Quality is not null) { queryString.Add(QualityWebProcessor.Quality, options.Quality?.ToString(CultureInfo.InvariantCulture)); } foreach (KeyValuePair kvp in QueryHelpers.ParseQuery(options.FurtherOptions)) { queryString.Add(kvp.Key, kvp.Value); } if (options.CacheBusterValue is not null && !string.IsNullOrWhiteSpace(options.CacheBusterValue)) { queryString.Add("rnd", options.CacheBusterValue); } return QueryHelpers.AddQueryString(options.ImageUrl, queryString); } }