Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v10: Update to ImageSharp v2 #12185

Merged
merged 22 commits into from
Apr 29, 2022
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
ff153cd
Update to ImageSharp 2.1.0 and ImageSharp.Web 2.0.0-alpha.0.23
ronaldbarendse Mar 27, 2022
e8d82af
Rename CachedNameLength to CacheHashLength and add CacheFolderDepth s…
ronaldbarendse Mar 27, 2022
5fa02e9
Replace PhysicalFileSystemProvider with WebRootImageProvider
ronaldbarendse Mar 27, 2022
da34c09
Support EXIF-orientation in image dimention extractor
ronaldbarendse Mar 28, 2022
91fbdb2
Remove virtual methods on FileProviderImageProvider
ronaldbarendse Mar 30, 2022
827ae60
Simplify FileInfoImageResolver
ronaldbarendse Mar 30, 2022
8efb526
Update to SixLabors.ImageSharp.Web 2.0.0-alpha.0.25 and remove custom…
ronaldbarendse Apr 4, 2022
d35dfc6
Make CropWebProcessor EXIF orientation-aware
ronaldbarendse Apr 4, 2022
ba491ec
Improve width/height sanitization
ronaldbarendse Apr 4, 2022
5b973a9
Also use 'v' as cache buster value
ronaldbarendse Apr 4, 2022
2cbef09
Add WebP to supported image file types
ronaldbarendse Apr 4, 2022
e7f74dc
Update to SixLabors.ImageSharp.Web 2.0.0-alpha.0.27 and fix test
ronaldbarendse Apr 5, 2022
70e2437
Fix rounding error and add test cases
ronaldbarendse Apr 9, 2022
67b8dbc
Update to newest and stable releases
ronaldbarendse Apr 25, 2022
5b758db
Merge branch 'v10/dev' into v10/feature/imagesharp2
ronaldbarendse Apr 25, 2022
798a3bd
Merge branch 'origin/v10/dev' into v10/feature/imagesharp2
ronaldbarendse Apr 28, 2022
cac5402
Move ImageSharpImageUrlGenerator to Umbraco.Web.Common
ronaldbarendse Apr 28, 2022
3cae534
Use IConfigureOptions to configure ImageSharp options
ronaldbarendse Apr 28, 2022
10eb181
Implement IEquatable on ImageUrlGenerationOptions classes
ronaldbarendse Apr 28, 2022
2de5520
Fix empty/null values in image URL generation and corresponding tests
ronaldbarendse Apr 28, 2022
5898b0c
Use IsSupportedImageFormat extension method
ronaldbarendse Apr 28, 2022
5cb9a9b
Remove unneeded reflection
ronaldbarendse Apr 28, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public class ContentImagingSettings
}
};

internal const string StaticImageFileTypes = "jpeg,jpg,gif,bmp,png,tiff,tif";
internal const string StaticImageFileTypes = "jpeg,jpg,gif,bmp,png,tiff,tif,webp";
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This setting doesn't seem to be used: the supported image file types are now retrieved from the IImageUrlGenerator.SupportedImageFileTypes property and the ImageSharpImageUrlGenerator implementation dynamically retrieves the supported ones from the ImageSharp configuration instead.

These image file types are then used to for more then just generating image URLs though (e.g. whether to extract image dimensions to auto-fill properties, disallow file uploads that are not images and automatically changing the media type from File to Image).

I suggest keeping this setting and create a separate PR to fix the mixed usage, so:

  • ContentImagingSettings.ImageFileTypes is used to determine whether the uploaded file is a valid image and if it can automatically change the media type to Image;
  • IImageUrlGenerator.SupportedImageFileTypes is used whether it can generate an image URL for a specified file;
  • A new IImageDimensionExtractor.SupportedImageFileTypes property is added that exposes whether it can get dimensions for a specified file (and have the ImageSharpDimensionExtractor populate this the same way as the ImageSharpImageUrlGenerator currently does).


/// <summary>
/// Gets or sets a value for the collection of accepted image file extensions.
Expand Down
19 changes: 13 additions & 6 deletions src/Umbraco.Core/Configuration/Models/ImagingCacheSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ public class ImagingCacheSettings
{
internal const string StaticBrowserMaxAge = "7.00:00:00";
internal const string StaticCacheMaxAge = "365.00:00:00";
internal const int StaticCachedNameLength = 8;
internal const string StaticCacheFolder = Constants.SystemDirectories.TempData + "/MediaCache";
internal const int StaticCacheHashLength = 12;
internal const int StaticCacheFolderDepth = 8;
internal const string StaticCacheFolder = Constants.SystemDirectories.TempData + "/MediaCache";

/// <summary>
/// Gets or sets a value for the browser image cache maximum age.
Expand All @@ -30,13 +31,19 @@ public class ImagingCacheSettings
public TimeSpan CacheMaxAge { get; set; } = TimeSpan.Parse(StaticCacheMaxAge);

/// <summary>
/// Gets or sets a value for length of the cached name.
/// Gets or sets a value for the image cache hash length.
/// </summary>
[DefaultValue(StaticCachedNameLength)]
public uint CachedNameLength { get; set; } = StaticCachedNameLength;
[DefaultValue(StaticCacheHashLength)]
public uint CacheHashLength { get; set; } = StaticCacheHashLength;

/// <summary>
/// Gets or sets a value for the cache folder.
/// Gets or sets a value for the image cache folder depth.
/// </summary>
[DefaultValue(StaticCacheFolderDepth)]
public uint CacheFolderDepth { get; set; } = StaticCacheFolderDepth;

/// <summary>
/// Gets or sets a value for the image cache folder.
/// </summary>
[DefaultValue(StaticCacheFolder)]
public string CacheFolder { get; set; } = StaticCacheFolder;
Expand Down
62 changes: 59 additions & 3 deletions src/Umbraco.Core/Models/ImageUrlGenerationOptions.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
using System;
using System.Collections.Generic;

namespace Umbraco.Cms.Core.Models
{
/// <summary>
/// These are options that are passed to the IImageUrlGenerator implementation to determine the URL that is generated.
/// </summary>
public class ImageUrlGenerationOptions
public class ImageUrlGenerationOptions : IEquatable<ImageUrlGenerationOptions>
{
public ImageUrlGenerationOptions(string? imageUrl) => ImageUrl = imageUrl;

Expand All @@ -27,10 +30,43 @@ public class ImageUrlGenerationOptions

public string? FurtherOptions { get; set; }

public override bool Equals(object? obj) => Equals(obj as ImageUrlGenerationOptions);

public bool Equals(ImageUrlGenerationOptions? other)
=> other != null &&
ImageUrl == other.ImageUrl &&
Width == other.Width &&
Height == other.Height &&
Quality == other.Quality &&
ImageCropMode == other.ImageCropMode &&
ImageCropAnchor == other.ImageCropAnchor &&
EqualityComparer<FocalPointPosition>.Default.Equals(FocalPoint, other.FocalPoint) &&
EqualityComparer<CropCoordinates>.Default.Equals(Crop, other.Crop) &&
CacheBusterValue == other.CacheBusterValue &&
FurtherOptions == other.FurtherOptions;

public override int GetHashCode()
{
var hash = new HashCode();

hash.Add(ImageUrl);
hash.Add(Width);
hash.Add(Height);
hash.Add(Quality);
hash.Add(ImageCropMode);
hash.Add(ImageCropAnchor);
hash.Add(FocalPoint);
hash.Add(Crop);
hash.Add(CacheBusterValue);
hash.Add(FurtherOptions);

return hash.ToHashCode();
}

/// <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 class FocalPointPosition : IEquatable<FocalPointPosition>
{
public FocalPointPosition(decimal left, decimal top)
{
Expand All @@ -41,12 +77,21 @@ public FocalPointPosition(decimal left, decimal top)
public decimal Left { get; }

public decimal Top { get; }

public override bool Equals(object? obj) => Equals(obj as FocalPointPosition);

public bool Equals(FocalPointPosition? other)
=> other != null &&
Left == other.Left &&
Top == other.Top;

public override int GetHashCode() => HashCode.Combine(Left, Top);
}

/// <summary>
/// The bounds of the crop within the original image, in whatever units the registered IImageUrlGenerator uses, typically a percentage between 0.0 and 1.0.
/// </summary>
public class CropCoordinates
public class CropCoordinates : IEquatable<CropCoordinates>
{
public CropCoordinates(decimal left, decimal top, decimal right, decimal bottom)
{
Expand All @@ -63,6 +108,17 @@ public CropCoordinates(decimal left, decimal top, decimal right, decimal bottom)
public decimal Right { get; }

public decimal Bottom { get; }

public override bool Equals(object? obj) => Equals(obj as CropCoordinates);

public bool Equals(CropCoordinates? other)
=> other != null &&
Left == other.Left &&
Top == other.Top &&
Right == other.Right &&
Bottom == other.Bottom;

public override int GetHashCode() => HashCode.Combine(Left, Top, Right, Bottom);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,6 @@ public static IUmbracoBuilder AddCoreInitialServices(this IUmbracoBuilder builde
// Add default ImageSharp configuration and service implementations
builder.Services.AddSingleton(SixLabors.ImageSharp.Configuration.Default);
builder.Services.AddSingleton<IImageDimensionExtractor, ImageSharpDimensionExtractor>();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Normally we add a NoopImpementation so you can boot Infrastructure without the web assemblies

builder.Services.AddSingleton<IImageUrlGenerator, ImageSharpImageUrlGenerator>();

builder.Services.AddSingleton<PackageDataInstallation>();

Expand Down
34 changes: 33 additions & 1 deletion src/Umbraco.Infrastructure/Media/ImageSharpDimensionExtractor.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using System;
using System.IO;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Metadata.Profiles.Exif;
using Umbraco.Cms.Core.Media;
using Size = System.Drawing.Size;

Expand Down Expand Up @@ -30,10 +32,40 @@ public ImageSharpDimensionExtractor(Configuration configuration)
IImageInfo imageInfo = Image.Identify(_configuration, stream);
if (imageInfo != null)
{
size = new Size(imageInfo.Width, imageInfo.Height);
size = IsExifOrientationRotated(imageInfo)
? new Size(imageInfo.Height, imageInfo.Width)
: new Size(imageInfo.Width, imageInfo.Height);
}

return size;
}

private static bool IsExifOrientationRotated(IImageInfo imageInfo)
=> GetExifOrientation(imageInfo) switch
{
ExifOrientationMode.LeftTop
or ExifOrientationMode.RightTop
or ExifOrientationMode.RightBottom
or ExifOrientationMode.LeftBottom => true,
_ => false,
};

private static ushort GetExifOrientation(IImageInfo imageInfo)
{
IExifValue<ushort> orientation = imageInfo.Metadata.ExifProfile?.GetValue(ExifTag.Orientation);
if (orientation is not null)
{
if (orientation.DataType == ExifDataType.Short)
{
return orientation.Value;
}
else
{
return Convert.ToUInt16(orientation.Value);
}
}

return ExifOrientationMode.Unknown;
}
}
}
107 changes: 0 additions & 107 deletions src/Umbraco.Infrastructure/Media/ImageSharpImageUrlGenerator.cs

This file was deleted.

2 changes: 1 addition & 1 deletion src/Umbraco.Infrastructure/Umbraco.Infrastructure.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
<PackageReference Include="Serilog.Sinks.Async" Version="1.5.0" />
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
<PackageReference Include="Serilog.Sinks.Map" Version="1.0.2" />
<PackageReference Include="SixLabors.ImageSharp" Version="1.0.4" />
<PackageReference Include="SixLabors.ImageSharp" Version="2.1.1" />
<PackageReference Include="System.IO.FileSystem.AccessControl" Version="5.0.0" />
<PackageReference Include="System.Text.Encodings.Web" Version="6.0.0" /> <!-- Explicit updated this nested dependency due to this https://github.com/dotnet/announcements/issues/178-->
<PackageReference Include="System.Threading.Tasks.Dataflow" Version="6.0.0" />
Expand Down
Loading