2020-02-07 15:01:03 -08:00
using System ;
using System.Globalization ;
2021-02-10 11:42:04 +01:00
using Newtonsoft.Json.Linq ;
2021-02-09 10:22:42 +01:00
using Umbraco.Cms.Core.Media ;
using Umbraco.Cms.Core.Models ;
using Umbraco.Cms.Core.Models.PublishedContent ;
using Umbraco.Cms.Core.Routing ;
2020-02-07 15:01:03 -08:00
using Umbraco.Core.PropertyEditors.ValueConverters ;
2020-08-04 14:12:22 +02:00
namespace Umbraco.Extensions
2020-02-07 15:01:03 -08:00
{
public static class ImageCropperTemplateCoreExtensions
{
/// <summary>
2020-10-05 20:48:38 +02:00
/// Gets the ImageProcessor URL by the crop alias (from the "umbracoFile" property alias) on the IPublishedContent item
2020-02-07 15:01:03 -08:00
/// </summary>
/// <param name="mediaItem">
/// The IPublishedContent item.
/// </param>
/// <param name="cropAlias">
/// The crop alias e.g. thumbnail
/// </param>
2020-08-04 14:12:22 +02:00
/// <param name="imageUrlGenerator">The image url generator.</param>
/// <param name="publishedValueFallback">The published value fallback.</param>
/// <param name="publishedUrlProvider">The published url provider.</param>
2020-02-07 15:01:03 -08:00
/// <returns>
2020-10-05 20:48:38 +02:00
/// The ImageProcessor.Web URL.
2020-02-07 15:01:03 -08:00
/// </returns>
2020-08-04 14:12:22 +02:00
public static string GetCropUrl (
this IPublishedContent mediaItem ,
string cropAlias ,
IImageUrlGenerator imageUrlGenerator ,
IPublishedValueFallback publishedValueFallback ,
IPublishedUrlProvider publishedUrlProvider )
2020-02-07 15:01:03 -08:00
{
2020-08-04 14:12:22 +02:00
return mediaItem . GetCropUrl ( imageUrlGenerator , publishedValueFallback , publishedUrlProvider , cropAlias : cropAlias , useCropDimensions : true ) ;
2020-02-07 15:01:03 -08:00
}
/// <summary>
2020-10-05 20:48:38 +02:00
/// Gets the ImageProcessor URL by the crop alias using the specified property containing the image cropper Json data on the IPublishedContent item.
2020-02-07 15:01:03 -08:00
/// </summary>
/// <param name="mediaItem">
/// The IPublishedContent item.
/// </param>
/// <param name="propertyAlias">
/// The property alias of the property containing the Json data e.g. umbracoFile
/// </param>
/// <param name="cropAlias">
/// The crop alias e.g. thumbnail
/// </param>
2020-08-04 14:12:22 +02:00
/// <param name="imageUrlGenerator">The image url generator.</param>
/// <param name="publishedValueFallback">The published value fallback.</param>
/// <param name="publishedUrlProvider">The published url provider.</param>
2020-02-07 15:01:03 -08:00
/// <returns>
2020-10-05 20:48:38 +02:00
/// The ImageProcessor.Web URL.
2020-02-07 15:01:03 -08:00
/// </returns>
2020-08-04 14:12:22 +02:00
public static string GetCropUrl (
this IPublishedContent mediaItem ,
string propertyAlias ,
string cropAlias ,
IImageUrlGenerator imageUrlGenerator ,
IPublishedValueFallback publishedValueFallback ,
IPublishedUrlProvider publishedUrlProvider )
2020-02-07 15:01:03 -08:00
{
2020-08-04 14:12:22 +02:00
return mediaItem . GetCropUrl ( imageUrlGenerator , publishedValueFallback , publishedUrlProvider , propertyAlias : propertyAlias , cropAlias : cropAlias , useCropDimensions : true ) ;
2020-02-07 15:01:03 -08:00
}
/// <summary>
2020-10-05 20:48:38 +02:00
/// Gets the ImageProcessor URL from the IPublishedContent item.
2020-02-07 15:01:03 -08:00
/// </summary>
/// <param name="mediaItem">
/// The IPublishedContent item.
/// </param>
2020-08-04 14:12:22 +02:00
/// <param name="imageUrlGenerator">The image url generator.</param>
/// <param name="publishedValueFallback">The published value fallback.</param>
/// <param name="publishedUrlProvider">The published url provider.</param>
2020-02-07 15:01:03 -08:00
/// <param name="width">
/// The width of the output image.
/// </param>
/// <param name="height">
/// The height of the output image.
/// </param>
/// <param name="propertyAlias">
/// Property alias of the property containing the Json data.
/// </param>
/// <param name="cropAlias">
/// The crop alias.
/// </param>
/// <param name="quality">
/// Quality percentage of the output image.
/// </param>
/// <param name="imageCropMode">
/// The image crop mode.
/// </param>
/// <param name="imageCropAnchor">
/// The image crop anchor.
/// </param>
/// <param name="preferFocalPoint">
/// Use focal point, to generate an output image using the focal point instead of the predefined crop
/// </param>
/// <param name="useCropDimensions">
/// Use crop dimensions to have the output image sized according to the predefined crop sizes, this will override the width and height parameters.
/// </param>
/// <param name="cacheBuster">
/// Add a serialized date of the last edit of the item to ensure client cache refresh when updated
/// </param>
/// <param name="furtherOptions">
/// These are any query string parameters (formatted as query strings) that ImageProcessor supports. For example:
/// <example>
/// <![CDATA[
/// furtherOptions: "&bgcolor=fff"
/// ]]>
/// </example>
/// </param>
/// <param name="ratioMode">
/// Use a dimension as a ratio
/// </param>
/// <param name="upScale">
/// If the image should be upscaled to requested dimensions
/// </param>
2020-08-04 14:12:22 +02:00
2020-02-07 15:01:03 -08:00
/// <returns>
/// The <see cref="string"/>.
/// </returns>
public static string GetCropUrl (
this IPublishedContent mediaItem ,
IImageUrlGenerator imageUrlGenerator ,
2020-08-04 14:12:22 +02:00
IPublishedValueFallback publishedValueFallback ,
IPublishedUrlProvider publishedUrlProvider ,
2020-02-07 15:01:03 -08:00
int? width = null ,
int? height = null ,
2021-02-10 11:42:04 +01:00
string propertyAlias = Cms . Core . Constants . Conventions . Media . File ,
2020-02-07 15:01:03 -08:00
string cropAlias = null ,
int? quality = null ,
ImageCropMode ? imageCropMode = null ,
ImageCropAnchor ? imageCropAnchor = null ,
bool preferFocalPoint = false ,
bool useCropDimensions = false ,
bool cacheBuster = true ,
string furtherOptions = null ,
ImageCropRatioMode ? ratioMode = null ,
bool upScale = true )
{
if ( mediaItem = = null ) throw new ArgumentNullException ( "mediaItem" ) ;
var cacheBusterValue = cacheBuster ? mediaItem . UpdateDate . ToFileTimeUtc ( ) . ToString ( CultureInfo . InvariantCulture ) : null ;
if ( mediaItem . HasProperty ( propertyAlias ) = = false | | mediaItem . HasValue ( propertyAlias ) = = false )
return string . Empty ;
2020-08-04 14:12:22 +02:00
var mediaItemUrl = mediaItem . MediaUrl ( publishedUrlProvider , propertyAlias : propertyAlias ) ;
2020-02-07 15:01:03 -08:00
//get the default obj from the value converter
2020-08-04 14:12:22 +02:00
var cropperValue = mediaItem . Value ( publishedValueFallback , propertyAlias ) ;
2020-02-07 15:01:03 -08:00
//is it strongly typed?
var stronglyTyped = cropperValue as ImageCropperValue ;
if ( stronglyTyped ! = null )
{
return GetCropUrl (
mediaItemUrl , imageUrlGenerator , stronglyTyped , width , height , cropAlias , quality , imageCropMode , imageCropAnchor , preferFocalPoint , useCropDimensions ,
cacheBusterValue , furtherOptions , ratioMode , upScale ) ;
}
//this shouldn't be the case but we'll check
var jobj = cropperValue as JObject ;
if ( jobj ! = null )
{
stronglyTyped = jobj . ToObject < ImageCropperValue > ( ) ;
return GetCropUrl (
mediaItemUrl , imageUrlGenerator , stronglyTyped , width , height , cropAlias , quality , imageCropMode , imageCropAnchor , preferFocalPoint , useCropDimensions ,
cacheBusterValue , furtherOptions , ratioMode , upScale ) ;
}
//it's a single string
return GetCropUrl (
mediaItemUrl , imageUrlGenerator , width , height , mediaItemUrl , cropAlias , quality , imageCropMode , imageCropAnchor , preferFocalPoint , useCropDimensions ,
cacheBusterValue , furtherOptions , ratioMode , upScale ) ;
}
/// <summary>
2020-10-05 20:48:38 +02:00
/// Gets the ImageProcessor URL from the image path.
2020-02-07 15:01:03 -08:00
/// </summary>
/// <param name="imageUrl">
2020-10-05 20:48:38 +02:00
/// The image URL.
2020-02-07 15:01:03 -08:00
/// </param>
/// <param name="width">
/// The width of the output image.
/// </param>
/// <param name="height">
/// The height of the output image.
/// </param>
/// <param name="imageCropperValue">
/// The Json data from the Umbraco Core Image Cropper property editor
/// </param>
/// <param name="cropAlias">
/// The crop alias.
/// </param>
/// <param name="quality">
/// Quality percentage of the output image.
/// </param>
/// <param name="imageCropMode">
/// The image crop mode.
/// </param>
/// <param name="imageCropAnchor">
/// The image crop anchor.
/// </param>
/// <param name="preferFocalPoint">
/// Use focal point to generate an output image using the focal point instead of the predefined crop if there is one
/// </param>
/// <param name="useCropDimensions">
/// Use crop dimensions to have the output image sized according to the predefined crop sizes, this will override the width and height parameters
/// </param>
/// <param name="cacheBusterValue">
/// Add a serialized date of the last edit of the item to ensure client cache refresh when updated
/// </param>
/// <param name="furtherOptions">
/// These are any query string parameters (formatted as query strings) that ImageProcessor supports. For example:
/// <example>
/// <![CDATA[
/// furtherOptions: "&bgcolor=fff"
/// ]]>
/// </example>
/// </param>
/// <param name="ratioMode">
/// Use a dimension as a ratio
/// </param>
/// <param name="upScale">
/// If the image should be upscaled to requested dimensions
/// </param>
/// <returns>
/// The <see cref="string"/>.
/// </returns>
public static string GetCropUrl (
this string imageUrl ,
IImageUrlGenerator imageUrlGenerator ,
int? width = null ,
int? height = null ,
string imageCropperValue = null ,
string cropAlias = null ,
int? quality = null ,
ImageCropMode ? imageCropMode = null ,
ImageCropAnchor ? imageCropAnchor = null ,
bool preferFocalPoint = false ,
bool useCropDimensions = false ,
string cacheBusterValue = null ,
string furtherOptions = null ,
ImageCropRatioMode ? ratioMode = null ,
bool upScale = true )
{
if ( string . IsNullOrEmpty ( imageUrl ) ) return string . Empty ;
ImageCropperValue cropDataSet = null ;
if ( string . IsNullOrEmpty ( imageCropperValue ) = = false & & imageCropperValue . DetectIsJson ( ) & & ( imageCropMode = = ImageCropMode . Crop | | imageCropMode = = null ) )
{
cropDataSet = imageCropperValue . DeserializeImageCropperValue ( ) ;
}
return GetCropUrl (
imageUrl , imageUrlGenerator , cropDataSet , width , height , cropAlias , quality , imageCropMode ,
imageCropAnchor , preferFocalPoint , useCropDimensions , cacheBusterValue , furtherOptions , ratioMode , upScale ) ;
}
/// <summary>
2020-10-05 20:48:38 +02:00
/// Gets the ImageProcessor URL from the image path.
2020-02-07 15:01:03 -08:00
/// </summary>
/// <param name="imageUrl">
2020-10-05 20:48:38 +02:00
/// The image URL.
2020-02-07 15:01:03 -08:00
/// </param>
/// <param name="imageUrlGenerator">
2020-10-05 20:48:38 +02:00
/// The generator that will process all the options and the image URL to return a full image URLs with all processing options appended
2020-02-07 15:01:03 -08:00
/// </param>
/// <param name="cropDataSet"></param>
/// <param name="width">
/// The width of the output image.
/// </param>
/// <param name="height">
/// The height of the output image.
/// </param>
/// <param name="cropAlias">
/// The crop alias.
/// </param>
/// <param name="quality">
/// Quality percentage of the output image.
/// </param>
/// <param name="imageCropMode">
/// The image crop mode.
/// </param>
/// <param name="imageCropAnchor">
/// The image crop anchor.
/// </param>
/// <param name="preferFocalPoint">
/// Use focal point to generate an output image using the focal point instead of the predefined crop if there is one
/// </param>
/// <param name="useCropDimensions">
/// Use crop dimensions to have the output image sized according to the predefined crop sizes, this will override the width and height parameters
/// </param>
/// <param name="cacheBusterValue">
/// Add a serialized date of the last edit of the item to ensure client cache refresh when updated
/// </param>
/// <param name="furtherOptions">
/// These are any query string parameters (formatted as query strings) that ImageProcessor supports. For example:
/// <example>
/// <![CDATA[
/// furtherOptions: "&bgcolor=fff"
/// ]]>
/// </example>
/// </param>
/// <param name="ratioMode">
/// Use a dimension as a ratio
/// </param>
/// <param name="upScale">
/// If the image should be upscaled to requested dimensions
/// </param>
/// <returns>
/// The <see cref="string"/>.
/// </returns>
public static string GetCropUrl (
this string imageUrl ,
IImageUrlGenerator imageUrlGenerator ,
ImageCropperValue cropDataSet ,
int? width = null ,
int? height = null ,
string cropAlias = null ,
int? quality = null ,
ImageCropMode ? imageCropMode = null ,
ImageCropAnchor ? imageCropAnchor = null ,
bool preferFocalPoint = false ,
bool useCropDimensions = false ,
string cacheBusterValue = null ,
string furtherOptions = null ,
ImageCropRatioMode ? ratioMode = null ,
2020-02-08 16:49:12 -08:00
bool upScale = true ,
string animationProcessMode = null )
2020-02-07 15:01:03 -08:00
{
2020-02-08 11:05:14 -08:00
if ( string . IsNullOrEmpty ( imageUrl ) ) return string . Empty ;
2020-02-07 15:01:03 -08:00
2020-02-08 11:05:14 -08:00
ImageUrlGenerationOptions options ;
2020-02-07 15:01:03 -08:00
2020-02-08 11:05:14 -08:00
if ( cropDataSet ! = null & & ( imageCropMode = = ImageCropMode . Crop | | imageCropMode = = null ) )
{
var crop = cropDataSet . GetCrop ( cropAlias ) ;
2020-02-07 15:01:03 -08:00
2020-02-08 11:05:14 -08:00
// if a crop was specified, but not found, return null
if ( crop = = null & & ! string . IsNullOrWhiteSpace ( cropAlias ) )
return null ;
2020-02-07 15:01:03 -08:00
2020-02-08 11:05:14 -08:00
options = cropDataSet . GetCropBaseOptions ( imageUrl , crop , string . IsNullOrWhiteSpace ( cropAlias ) , preferFocalPoint ) ;
2020-02-07 15:01:03 -08:00
2020-02-08 11:05:14 -08:00
if ( crop ! = null & useCropDimensions )
2020-02-07 15:01:03 -08:00
{
2020-02-08 11:05:14 -08:00
width = crop . Width ;
height = crop . Height ;
2020-02-07 15:01:03 -08:00
}
2020-02-08 11:05:14 -08:00
// If a predefined crop has been specified & there are no coordinates & no ratio mode, but a width parameter has been passed we can get the crop ratio for the height
if ( crop ! = null & & string . IsNullOrEmpty ( cropAlias ) = = false & & crop . Coordinates = = null & & ratioMode = = null & & width ! = null & & height = = null )
2020-02-07 15:01:03 -08:00
{
2020-02-08 11:05:14 -08:00
options . HeightRatio = ( decimal ) crop . Height / crop . Width ;
2020-02-07 15:01:03 -08:00
}
2020-02-08 11:05:14 -08:00
// If a predefined crop has been specified & there are no coordinates & no ratio mode, but a height parameter has been passed we can get the crop ratio for the width
if ( crop ! = null & & string . IsNullOrEmpty ( cropAlias ) = = false & & crop . Coordinates = = null & & ratioMode = = null & & width = = null & & height ! = null )
2020-02-07 15:01:03 -08:00
{
2020-02-08 11:05:14 -08:00
options . WidthRatio = ( decimal ) crop . Width / crop . Height ;
2020-02-07 15:01:03 -08:00
}
2020-02-08 11:05:14 -08:00
}
else
{
2020-02-09 11:12:29 -08:00
options = new ImageUrlGenerationOptions ( imageUrl )
2020-02-08 11:05:14 -08:00
{
2020-05-20 17:39:07 +02:00
ImageCropMode = ( imageCropMode ? ? ImageCropMode . Pad ) ,
ImageCropAnchor = imageCropAnchor
2020-02-08 11:05:14 -08:00
} ;
}
2020-02-07 15:01:03 -08:00
2020-02-08 11:05:14 -08:00
options . Quality = quality ;
options . Width = ratioMode ! = null & & ratioMode . Value = = ImageCropRatioMode . Width ? null : width ;
options . Height = ratioMode ! = null & & ratioMode . Value = = ImageCropRatioMode . Height ? null : height ;
2020-02-08 16:49:12 -08:00
options . AnimationProcessMode = animationProcessMode ;
2020-02-07 15:01:03 -08:00
2020-02-08 11:05:14 -08:00
if ( ratioMode = = ImageCropRatioMode . Width & & height ! = null )
{
// if only height specified then assume a square
if ( width = = null ) width = height ;
options . WidthRatio = ( decimal ) width / ( decimal ) height ;
2020-02-07 15:01:03 -08:00
}
2020-02-08 11:05:14 -08:00
if ( ratioMode = = ImageCropRatioMode . Height & & width ! = null )
{
// if only width specified then assume a square
if ( height = = null ) height = width ;
options . HeightRatio = ( decimal ) height / ( decimal ) width ;
}
options . UpScale = upScale ;
options . FurtherOptions = furtherOptions ;
options . CacheBusterValue = cacheBusterValue ;
return imageUrlGenerator . GetImageUrl ( options ) ;
2020-02-07 15:01:03 -08:00
}
}
}