Skip to content

Commit

Permalink
Merge pull request #7616 from umbraco/temp-7538-image-url-generator
Browse files Browse the repository at this point in the history
Introduce Image URL Generator abstraction
  • Loading branch information
benjaminc authored Feb 11, 2020
2 parents ad8d908 + 4309489 commit c63af8e
Show file tree
Hide file tree
Showing 27 changed files with 1,057 additions and 295 deletions.
3 changes: 3 additions & 0 deletions src/Umbraco.Core/Composing/Current.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Mapping;
using Umbraco.Core.Models;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.PackageActions;
using Umbraco.Core.Packaging;
Expand Down Expand Up @@ -208,6 +209,8 @@ public static IPublishedValueFallback PublishedValueFallback
public static IVariationContextAccessor VariationContextAccessor
=> Factory.GetInstance<IVariationContextAccessor>();

public static IImageUrlGenerator ImageUrlGenerator
=> Factory.GetInstance<IImageUrlGenerator>();
#endregion
}
}
7 changes: 7 additions & 0 deletions src/Umbraco.Core/Models/IImageUrlGenerator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Umbraco.Core.Models
{
public interface IImageUrlGenerator
{
string GetImageUrl(ImageUrlGenerationOptions options);
}
}
66 changes: 66 additions & 0 deletions src/Umbraco.Core/Models/ImageUrlGenerationOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
namespace Umbraco.Core.Models
{
/// <summary>
/// These are options that are passed to the IImageUrlGenerator implementation to determine
/// the propery URL that is needed
/// </summary>
public class ImageUrlGenerationOptions
{
public ImageUrlGenerationOptions (string imageUrl)
{
ImageUrl = imageUrl;
}

public string ImageUrl { get; }
public int? Width { get; set; }
public int? Height { get; set; }
public decimal? WidthRatio { get; set; }
public decimal? HeightRatio { get; set; }
public int? Quality { get; set; }
public string ImageCropMode { get; set; }
public string ImageCropAnchor { get; set; }
public bool DefaultCrop { get; set; }
public FocalPointPosition FocalPoint { get; set; }
public CropCoordinates Crop { get; set; }
public string CacheBusterValue { get; set; }
public string FurtherOptions { get; set; }
public bool UpScale { get; set; } = true;
public string AnimationProcessMode { get; set; }

/// <summary>
/// The focal point position, in whatever units the registered IImageUrlGenerator uses,
/// typically a percentage of the total image from 0.0 to 1.0.
/// </summary>
public class FocalPointPosition
{
public FocalPointPosition (decimal top, decimal left)
{
Left = left;
Top = top;
}

public decimal Left { get; }
public decimal Top { get; }
}

/// <summary>
/// The bounds of the crop within the original image, in whatever units the registered
/// IImageUrlGenerator uses, typically a percentage between 0 and 100.
/// </summary>
public class CropCoordinates
{
public CropCoordinates (decimal x1, decimal y1, decimal x2, decimal y2)
{
X1 = x1;
Y1 = y1;
X2 = x2;
Y2 = y2;
}

public decimal X1 { get; }
public decimal Y1 { get; }
public decimal X2 { get; }
public decimal Y2 { get; }
}
}
}
11 changes: 6 additions & 5 deletions src/Umbraco.Core/Models/UserExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -106,13 +106,14 @@ internal static string[] GetUserAvatarUrls(this IUser user, IAppCache cache)

//use the custom avatar
var avatarUrl = Current.MediaFileSystem.GetUrl(user.Avatar);
var urlGenerator = Current.ImageUrlGenerator;
return new[]
{
avatarUrl + "?width=30&height=30&mode=crop",
avatarUrl + "?width=60&height=60&mode=crop",
avatarUrl + "?width=90&height=90&mode=crop",
avatarUrl + "?width=150&height=150&mode=crop",
avatarUrl + "?width=300&height=300&mode=crop"
urlGenerator.GetImageUrl(new ImageUrlGenerationOptions(avatarUrl) { ImageCropMode = "crop", Width = 30, Height = 30 }),
urlGenerator.GetImageUrl(new ImageUrlGenerationOptions(avatarUrl) { ImageCropMode = "crop", Width = 60, Height = 60 }),
urlGenerator.GetImageUrl(new ImageUrlGenerationOptions(avatarUrl) { ImageCropMode = "crop", Width = 90, Height = 90 }),
urlGenerator.GetImageUrl(new ImageUrlGenerationOptions(avatarUrl) { ImageCropMode = "crop", Width = 150, Height = 150 }),
urlGenerator.GetImageUrl(new ImageUrlGenerationOptions(avatarUrl) { ImageCropMode = "crop", Width = 300, Height = 300 })
};

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
using System.Text;
using System.Web;
using Newtonsoft.Json;
using Umbraco.Core.Composing;
using Umbraco.Core.Models;
using Umbraco.Core.Serialization;

namespace Umbraco.Core.PropertyEditors.ValueConverters
Expand Down Expand Up @@ -59,77 +61,72 @@ public ImageCropperCrop GetCrop(string alias)
: Crops.FirstOrDefault(x => x.Alias.InvariantEquals(alias));
}

internal void AppendCropBaseUrl(StringBuilder url, ImageCropperCrop crop, bool defaultCrop, bool preferFocalPoint)
internal ImageUrlGenerationOptions GetCropBaseOptions(string url, ImageCropperCrop crop, bool defaultCrop, bool preferFocalPoint)
{
if (preferFocalPoint && HasFocalPoint()
|| crop != null && crop.Coordinates == null && HasFocalPoint()
|| defaultCrop && HasFocalPoint())
{
url.Append("?center=");
url.Append(FocalPoint.Top.ToString(CultureInfo.InvariantCulture));
url.Append(",");
url.Append(FocalPoint.Left.ToString(CultureInfo.InvariantCulture));
url.Append("&mode=crop");
return new ImageUrlGenerationOptions(url) { FocalPoint = new ImageUrlGenerationOptions.FocalPointPosition(FocalPoint.Top, FocalPoint.Left) };
}
else if (crop != null && crop.Coordinates != null && preferFocalPoint == false)
{
url.Append("?crop=");
url.Append(crop.Coordinates.X1.ToString(CultureInfo.InvariantCulture)).Append(",");
url.Append(crop.Coordinates.Y1.ToString(CultureInfo.InvariantCulture)).Append(",");
url.Append(crop.Coordinates.X2.ToString(CultureInfo.InvariantCulture)).Append(",");
url.Append(crop.Coordinates.Y2.ToString(CultureInfo.InvariantCulture));
url.Append("&cropmode=percentage");
return new ImageUrlGenerationOptions(url) { Crop = new ImageUrlGenerationOptions.CropCoordinates(crop.Coordinates.X1, crop.Coordinates.Y1, crop.Coordinates.X2, crop.Coordinates.Y2) };
}
else
{
url.Append("?anchor=center");
url.Append("&mode=crop");
return new ImageUrlGenerationOptions(url) { DefaultCrop = true };
}
}

/// <summary>
/// Gets the value image url for a specified crop.
/// </summary>
public string GetCropUrl(string alias, bool useCropDimensions = true, bool useFocalPoint = false, string cacheBusterValue = null)
[Obsolete("Use the overload that takes an IImageUrlGenerator")]
public string GetCropUrl(string alias, bool useCropDimensions = true, bool useFocalPoint = false, string cacheBusterValue = null) => GetCropUrl(alias, Current.ImageUrlGenerator, useCropDimensions, useFocalPoint, cacheBusterValue);

/// <summary>
/// Gets the value image url for a specified crop.
/// </summary>
public string GetCropUrl(string alias, IImageUrlGenerator imageUrlGenerator, bool useCropDimensions = true, bool useFocalPoint = false, string cacheBusterValue = null)
{
var crop = GetCrop(alias);

// could not find a crop with the specified, non-empty, alias
if (crop == null && !string.IsNullOrWhiteSpace(alias))
return null;

var url = new StringBuilder();

AppendCropBaseUrl(url, crop, string.IsNullOrWhiteSpace(alias), useFocalPoint);
var options = GetCropBaseOptions(string.Empty, crop, string.IsNullOrWhiteSpace(alias), useFocalPoint);

if (crop != null && useCropDimensions)
{
url.Append("&width=").Append(crop.Width);
url.Append("&height=").Append(crop.Height);
options.Width = crop.Width;
options.Height = crop.Height;
}

if (cacheBusterValue != null)
url.Append("&rnd=").Append(cacheBusterValue);
options.CacheBusterValue = cacheBusterValue;

return url.ToString();
return imageUrlGenerator.GetImageUrl(options);
}

/// <summary>
/// Gets the value image url for a specific width and height.
/// </summary>
public string GetCropUrl(int width, int height, bool useFocalPoint = false, string cacheBusterValue = null)
{
var url = new StringBuilder();
[Obsolete("Use the overload that takes an IImageUrlGenerator")]
public string GetCropUrl(int width, int height, bool useFocalPoint = false, string cacheBusterValue = null) => GetCropUrl(width, height, Current.ImageUrlGenerator, useFocalPoint, cacheBusterValue);

AppendCropBaseUrl(url, null, true, useFocalPoint);

url.Append("&width=").Append(width);
url.Append("&height=").Append(height);
/// <summary>
/// Gets the value image url for a specific width and height.
/// </summary>
public string GetCropUrl(int width, int height, IImageUrlGenerator imageUrlGenerator, bool useFocalPoint = false, string cacheBusterValue = null)
{
var options = GetCropBaseOptions(string.Empty, null, true, useFocalPoint);

if (cacheBusterValue != null)
url.Append("&rnd=").Append(cacheBusterValue);
options.Width = width;
options.Height = height;
options.CacheBusterValue = cacheBusterValue;

return url.ToString();
return imageUrlGenerator.GetImageUrl(options);
}

/// <summary>
Expand Down
2 changes: 2 additions & 0 deletions src/Umbraco.Core/Umbraco.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,8 @@
<Compile Include="Migrations\Upgrade\V_8_0_0\Models\PropertyDataDto80.cs" />
<Compile Include="Migrations\Upgrade\V_8_0_0\Models\PropertyTypeDto80.cs" />
<Compile Include="Migrations\Upgrade\V_8_6_0\AddMainDomLock.cs" />
<Compile Include="Models\IImageUrlGenerator.cs" />
<Compile Include="Models\ImageUrlGenerationOptions.cs" />
<Compile Include="Runtime\IMainDomLock.cs" />
<Compile Include="Runtime\MainDomSemaphoreLock.cs" />
<Compile Include="Runtime\SqlMainDomLock.cs" />
Expand Down
Loading

0 comments on commit c63af8e

Please sign in to comment.