aboutsummaryrefslogtreecommitdiff
path: root/Emby.Drawing/ImageProcessor.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Emby.Drawing/ImageProcessor.cs')
-rw-r--r--Emby.Drawing/ImageProcessor.cs52
1 files changed, 41 insertions, 11 deletions
diff --git a/Emby.Drawing/ImageProcessor.cs b/Emby.Drawing/ImageProcessor.cs
index 0b3bbe29e..f585b90ca 100644
--- a/Emby.Drawing/ImageProcessor.cs
+++ b/Emby.Drawing/ImageProcessor.cs
@@ -4,6 +4,7 @@ using System.Globalization;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
+using Jellyfin.Data.Entities;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Drawing;
@@ -14,6 +15,7 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Net;
using Microsoft.Extensions.Logging;
+using Photo = MediaBrowser.Controller.Entities.Photo;
namespace Emby.Drawing
{
@@ -28,7 +30,7 @@ namespace Emby.Drawing
private static readonly HashSet<string> _transparentImageTypes
= new HashSet<string>(StringComparer.OrdinalIgnoreCase) { ".png", ".webp", ".gif" };
- private readonly ILogger _logger;
+ private readonly ILogger<ImageProcessor> _logger;
private readonly IFileSystem _fileSystem;
private readonly IServerApplicationPaths _appPaths;
private readonly IImageEncoder _imageEncoder;
@@ -114,7 +116,7 @@ namespace Emby.Drawing
=> _transparentImageTypes.Contains(Path.GetExtension(path));
/// <inheritdoc />
- public async Task<(string path, string mimeType, DateTime dateModified)> ProcessImage(ImageProcessingOptions options)
+ public async Task<(string path, string? mimeType, DateTime dateModified)> ProcessImage(ImageProcessingOptions options)
{
ItemImageInfo originalImage = options.Image;
BaseItem item = options.Item;
@@ -230,7 +232,7 @@ namespace Emby.Drawing
return ImageFormat.Jpg;
}
- private string GetMimeType(ImageFormat format, string path)
+ private string? GetMimeType(ImageFormat format, string path)
=> format switch
{
ImageFormat.Bmp => MimeTypes.GetMimeType("i.bmp"),
@@ -300,7 +302,7 @@ namespace Emby.Drawing
}
string path = info.Path;
- _logger.LogInformation("Getting image size for item {ItemType} {Path}", item.GetType().Name, path);
+ _logger.LogDebug("Getting image size for item {ItemType} {Path}", item.GetType().Name, path);
ImageDimensions size = GetImageDimensions(path);
info.Width = size.Width;
@@ -314,6 +316,27 @@ namespace Emby.Drawing
=> _imageEncoder.GetImageSize(path);
/// <inheritdoc />
+ public string GetImageBlurHash(string path)
+ {
+ var size = GetImageDimensions(path);
+ if (size.Width <= 0 || size.Height <= 0)
+ {
+ return string.Empty;
+ }
+
+ // We want tiles to be as close to square as possible, and to *mostly* keep under 16 tiles for performance.
+ // One tile is (width / xComp) x (height / yComp) pixels, which means that ideally yComp = xComp * height / width.
+ // See more at https://github.com/woltapp/blurhash/#how-do-i-pick-the-number-of-x-and-y-components
+ float xCompF = MathF.Sqrt(16.0f * size.Width / size.Height);
+ float yCompF = xCompF * size.Height / size.Width;
+
+ int xComp = Math.Min((int)xCompF + 1, 9);
+ int yComp = Math.Min((int)yCompF + 1, 9);
+
+ return _imageEncoder.GetImageBlurHash(xComp, yComp, path);
+ }
+
+ /// <inheritdoc />
public string GetImageCacheTag(BaseItem item, ItemImageInfo image)
=> (item.Path + image.DateModified.Ticks).GetMD5().ToString("N", CultureInfo.InvariantCulture);
@@ -328,6 +351,13 @@ namespace Emby.Drawing
});
}
+ /// <inheritdoc />
+ public string GetImageCacheTag(User user)
+ {
+ return (user.ProfileImage.Path + user.ProfileImage.LastModified.Ticks).GetMD5()
+ .ToString("N", CultureInfo.InvariantCulture);
+ }
+
private async Task<(string path, DateTime dateModified)> GetSupportedImage(string originalImagePath, DateTime dateModified)
{
var inputFormat = Path.GetExtension(originalImagePath)
@@ -418,21 +448,21 @@ namespace Emby.Drawing
/// or
/// filename.
/// </exception>
- public string GetCachePath(string path, string filename)
+ public string GetCachePath(ReadOnlySpan<char> path, ReadOnlySpan<char> filename)
{
- if (string.IsNullOrEmpty(path))
+ if (path.IsEmpty)
{
- throw new ArgumentNullException(nameof(path));
+ throw new ArgumentException("Path can't be empty.", nameof(path));
}
- if (string.IsNullOrEmpty(filename))
+ if (path.IsEmpty)
{
- throw new ArgumentNullException(nameof(filename));
+ throw new ArgumentException("Filename can't be empty.", nameof(filename));
}
- var prefix = filename.Substring(0, 1);
+ var prefix = filename.Slice(0, 1);
- return Path.Combine(path, prefix, filename);
+ return Path.Join(path, prefix, filename);
}
/// <inheritdoc />