2023-05-09 10:09:54 +02:00
|
|
|
using SixLabors.ImageSharp;
|
2023-09-19 11:23:20 +02:00
|
|
|
using SixLabors.ImageSharp.Formats;
|
2023-05-09 10:09:54 +02:00
|
|
|
using SixLabors.ImageSharp.Metadata.Profiles.Exif;
|
|
|
|
|
using Umbraco.Cms.Core.Media;
|
|
|
|
|
using Size = System.Drawing.Size;
|
|
|
|
|
|
2023-05-11 11:01:59 +02:00
|
|
|
namespace Umbraco.Cms.Imaging.ImageSharp.Media;
|
2023-05-09 10:09:54 +02:00
|
|
|
|
|
|
|
|
public sealed class ImageSharpDimensionExtractor : IImageDimensionExtractor
|
|
|
|
|
{
|
2023-09-19 11:23:20 +02:00
|
|
|
private readonly DecoderOptions _decoderOptions;
|
2023-05-09 10:09:54 +02:00
|
|
|
|
|
|
|
|
/// <inheritdoc />
|
|
|
|
|
public IEnumerable<string> SupportedImageFileTypes { get; }
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Initializes a new instance of the <see cref="ImageSharpDimensionExtractor" /> class.
|
|
|
|
|
/// </summary>
|
2023-09-19 11:23:20 +02:00
|
|
|
/// <param name="decoderOptions">The configuration.</param>
|
|
|
|
|
public ImageSharpDimensionExtractor(DecoderOptions decoderOptions)
|
2023-05-09 10:09:54 +02:00
|
|
|
{
|
2023-09-19 11:23:20 +02:00
|
|
|
_decoderOptions = decoderOptions ?? throw new ArgumentNullException(nameof(decoderOptions));
|
2023-05-09 10:09:54 +02:00
|
|
|
|
2023-09-19 11:23:20 +02:00
|
|
|
SupportedImageFileTypes = decoderOptions.Configuration.ImageFormats.SelectMany(f => f.FileExtensions).ToArray();
|
2023-05-09 10:09:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <inheritdoc />
|
|
|
|
|
public Size? GetDimensions(Stream? stream)
|
|
|
|
|
{
|
|
|
|
|
Size? size = null;
|
|
|
|
|
|
2023-09-19 11:23:20 +02:00
|
|
|
if (stream == null)
|
|
|
|
|
{
|
|
|
|
|
return size;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ImageInfo imageInfo = Image.Identify(_decoderOptions, stream);
|
2023-05-09 10:09:54 +02:00
|
|
|
if (imageInfo != null)
|
|
|
|
|
{
|
|
|
|
|
size = IsExifOrientationRotated(imageInfo)
|
|
|
|
|
? new Size(imageInfo.Height, imageInfo.Width)
|
|
|
|
|
: new Size(imageInfo.Width, imageInfo.Height);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return size;
|
|
|
|
|
}
|
|
|
|
|
|
2023-09-19 11:23:20 +02:00
|
|
|
private static bool IsExifOrientationRotated(ImageInfo imageInfo)
|
2023-05-09 10:09:54 +02:00
|
|
|
=> GetExifOrientation(imageInfo) switch
|
|
|
|
|
{
|
|
|
|
|
ExifOrientationMode.LeftTop
|
|
|
|
|
or ExifOrientationMode.RightTop
|
|
|
|
|
or ExifOrientationMode.RightBottom
|
|
|
|
|
or ExifOrientationMode.LeftBottom => true,
|
|
|
|
|
_ => false,
|
|
|
|
|
};
|
|
|
|
|
|
2023-09-19 11:23:20 +02:00
|
|
|
private static ushort GetExifOrientation(ImageInfo imageInfo)
|
2023-05-09 10:09:54 +02:00
|
|
|
{
|
2023-09-19 11:23:20 +02:00
|
|
|
|
|
|
|
|
if(imageInfo.Metadata.ExifProfile != null && imageInfo.Metadata.ExifProfile.TryGetValue(ExifTag.Orientation, out IExifValue<ushort>? orientation))
|
2023-05-09 10:09:54 +02:00
|
|
|
{
|
|
|
|
|
if (orientation.DataType == ExifDataType.Short)
|
|
|
|
|
{
|
|
|
|
|
return orientation.Value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return Convert.ToUInt16(orientation.Value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ExifOrientationMode.Unknown;
|
|
|
|
|
}
|
|
|
|
|
}
|