Cleanup ImageProcessor

This commit is contained in:
Bond_009 2019-01-12 14:46:17 +01:00
parent 3a5e3ade01
commit 8fc8fc0622
4 changed files with 97 additions and 143 deletions

View file

@ -1,4 +1,3 @@
using SkiaSharp;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
@ -18,9 +17,8 @@ using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Extensions; using MediaBrowser.Model.Extensions;
using MediaBrowser.Model.IO; using MediaBrowser.Model.IO;
using MediaBrowser.Model.Net; using MediaBrowser.Model.Net;
using MediaBrowser.Model.Serialization;
using MediaBrowser.Model.Threading;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using SkiaSharp;
namespace Emby.Drawing namespace Emby.Drawing
{ {
@ -47,28 +45,27 @@ namespace Emby.Drawing
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly IFileSystem _fileSystem; private readonly IFileSystem _fileSystem;
private readonly IJsonSerializer _jsonSerializer;
private readonly IServerApplicationPaths _appPaths; private readonly IServerApplicationPaths _appPaths;
private IImageEncoder _imageEncoder; private IImageEncoder _imageEncoder;
private readonly Func<ILibraryManager> _libraryManager; private readonly Func<ILibraryManager> _libraryManager;
private readonly Func<IMediaEncoder> _mediaEncoder; private readonly Func<IMediaEncoder> _mediaEncoder;
public ImageProcessor(ILogger logger, public ImageProcessor(
ILogger logger,
IServerApplicationPaths appPaths, IServerApplicationPaths appPaths,
IFileSystem fileSystem, IFileSystem fileSystem,
IJsonSerializer jsonSerializer,
IImageEncoder imageEncoder, IImageEncoder imageEncoder,
Func<ILibraryManager> libraryManager, ITimerFactory timerFactory, Func<IMediaEncoder> mediaEncoder) Func<ILibraryManager> libraryManager,
Func<IMediaEncoder> mediaEncoder)
{ {
_logger = logger; _logger = logger;
_appPaths = appPaths;
_fileSystem = fileSystem; _fileSystem = fileSystem;
_jsonSerializer = jsonSerializer;
_imageEncoder = imageEncoder; _imageEncoder = imageEncoder;
_libraryManager = libraryManager; _libraryManager = libraryManager;
_mediaEncoder = mediaEncoder; _mediaEncoder = mediaEncoder;
_appPaths = appPaths;
ImageEnhancers = new IImageEnhancer[] { }; ImageEnhancers = Array.Empty<IImageEnhancer>();
ImageHelper.ImageProcessor = this; ImageHelper.ImageProcessor = this;
} }
@ -145,21 +142,19 @@ namespace Emby.Drawing
return _imageEncoder.SupportedOutputFormats; return _imageEncoder.SupportedOutputFormats;
} }
private readonly string[] TransparentImageTypes = new string[] { ".png", ".webp", ".gif" }; private static readonly string[] TransparentImageTypes = new string[] { ".png", ".webp", ".gif" };
public bool SupportsTransparency(string path) public bool SupportsTransparency(string path)
{ => TransparentImageTypes.Contains(Path.GetExtension(path).ToLower());
return TransparentImageTypes.Contains(Path.GetExtension(path) ?? string.Empty);
}
public async Task<Tuple<string, string, DateTime>> ProcessImage(ImageProcessingOptions options) public async Task<(string path, string mimeType, DateTime dateModified)> ProcessImage(ImageProcessingOptions options)
{ {
if (options == null) if (options == null)
{ {
throw new ArgumentNullException(nameof(options)); throw new ArgumentNullException(nameof(options));
} }
var originalImage = options.Image; ItemImageInfo originalImage = options.Image;
var item = options.Item; BaseItem item = options.Item;
if (!originalImage.IsLocalFile) if (!originalImage.IsLocalFile)
{ {
@ -170,19 +165,23 @@ namespace Emby.Drawing
originalImage = await _libraryManager().ConvertImageToLocal(item, originalImage, options.ImageIndex).ConfigureAwait(false); originalImage = await _libraryManager().ConvertImageToLocal(item, originalImage, options.ImageIndex).ConfigureAwait(false);
} }
var originalImagePath = originalImage.Path; string originalImagePath = originalImage.Path;
var dateModified = originalImage.DateModified; DateTime dateModified = originalImage.DateModified;
var originalImageSize = originalImage.Width > 0 && originalImage.Height > 0 ? new ImageSize(originalImage.Width, originalImage.Height) : (ImageSize?)null; ImageSize? originalImageSize = null;
if (originalImage.Width > 0 && originalImage.Height > 0)
{
originalImageSize = new ImageSize(originalImage.Width, originalImage.Height);
}
if (!_imageEncoder.SupportsImageEncoding) if (!_imageEncoder.SupportsImageEncoding)
{ {
return new Tuple<string, string, DateTime>(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified); return (originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified);
} }
var supportedImageInfo = await GetSupportedImage(originalImagePath, dateModified).ConfigureAwait(false); var supportedImageInfo = await GetSupportedImage(originalImagePath, dateModified).ConfigureAwait(false);
originalImagePath = supportedImageInfo.Item1; originalImagePath = supportedImageInfo.path;
dateModified = supportedImageInfo.Item2; dateModified = supportedImageInfo.dateModified;
var requiresTransparency = TransparentImageTypes.Contains(Path.GetExtension(originalImagePath) ?? string.Empty); bool requiresTransparency = TransparentImageTypes.Contains(Path.GetExtension(originalImagePath));
if (options.Enhancers.Length > 0) if (options.Enhancers.Length > 0)
{ {
@ -196,20 +195,18 @@ namespace Emby.Drawing
DateModified = dateModified, DateModified = dateModified,
Type = originalImage.Type, Type = originalImage.Type,
Path = originalImagePath Path = originalImagePath
}, requiresTransparency, item, options.ImageIndex, options.Enhancers, CancellationToken.None).ConfigureAwait(false); }, requiresTransparency, item, options.ImageIndex, options.Enhancers, CancellationToken.None).ConfigureAwait(false);
originalImagePath = tuple.Item1; originalImagePath = tuple.path;
dateModified = tuple.Item2; dateModified = tuple.dateModified;
requiresTransparency = tuple.Item3; requiresTransparency = tuple.transparent;
// TODO: Get this info // TODO: Get this info
originalImageSize = null; originalImageSize = null;
} }
var photo = item as Photo; bool autoOrient = false;
var autoOrient = false;
ImageOrientation? orientation = null; ImageOrientation? orientation = null;
if (photo != null) if (item is Photo photo)
{ {
if (photo.Orientation.HasValue) if (photo.Orientation.HasValue)
{ {
@ -230,7 +227,7 @@ namespace Emby.Drawing
if (options.HasDefaultOptions(originalImagePath, originalImageSize) && (!autoOrient || !options.RequiresAutoOrientation)) if (options.HasDefaultOptions(originalImagePath, originalImageSize) && (!autoOrient || !options.RequiresAutoOrientation))
{ {
// Just spit out the original file if all the options are default // Just spit out the original file if all the options are default
return new Tuple<string, string, DateTime>(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified); return (originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified);
} }
//ImageSize? originalImageSize = GetSavedImageSize(originalImagePath, dateModified); //ImageSize? originalImageSize = GetSavedImageSize(originalImagePath, dateModified);
@ -241,15 +238,15 @@ namespace Emby.Drawing
// return new ValueTuple<string, string, DateTime>(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified); // return new ValueTuple<string, string, DateTime>(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified);
//} //}
var newSize = ImageHelper.GetNewImageSize(options, null); ImageSize newSize = ImageHelper.GetNewImageSize(options, null);
var quality = options.Quality; int quality = options.Quality;
var outputFormat = GetOutputFormat(options.SupportedOutputFormats, requiresTransparency); ImageFormat outputFormat = GetOutputFormat(options.SupportedOutputFormats, requiresTransparency);
var cacheFilePath = GetCacheFilePath(originalImagePath, newSize, quality, dateModified, outputFormat, options.AddPlayedIndicator, options.PercentPlayed, options.UnplayedCount, options.Blur, options.BackgroundColor, options.ForegroundLayer); string cacheFilePath = GetCacheFilePath(originalImagePath, newSize, quality, dateModified, outputFormat, options.AddPlayedIndicator, options.PercentPlayed, options.UnplayedCount, options.Blur, options.BackgroundColor, options.ForegroundLayer);
CheckDisposed(); CheckDisposed();
var lockInfo = GetLock(cacheFilePath); LockInfo lockInfo = GetLock(cacheFilePath);
await lockInfo.Lock.WaitAsync().ConfigureAwait(false); await lockInfo.Lock.WaitAsync().ConfigureAwait(false);
@ -262,17 +259,15 @@ namespace Emby.Drawing
options.CropWhiteSpace = false; options.CropWhiteSpace = false;
} }
var resultPath = _imageEncoder.EncodeImage(originalImagePath, dateModified, cacheFilePath, autoOrient, orientation, quality, options, outputFormat); string resultPath = _imageEncoder.EncodeImage(originalImagePath, dateModified, cacheFilePath, autoOrient, orientation, quality, options, outputFormat);
if (string.Equals(resultPath, originalImagePath, StringComparison.OrdinalIgnoreCase)) if (string.Equals(resultPath, originalImagePath, StringComparison.OrdinalIgnoreCase))
{ {
return new Tuple<string, string, DateTime>(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified); return (originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified);
} }
return new Tuple<string, string, DateTime>(cacheFilePath, GetMimeType(outputFormat, cacheFilePath), _fileSystem.GetLastWriteTimeUtc(cacheFilePath));
} }
return new Tuple<string, string, DateTime>(cacheFilePath, GetMimeType(outputFormat, cacheFilePath), _fileSystem.GetLastWriteTimeUtc(cacheFilePath)); return (cacheFilePath, GetMimeType(outputFormat, cacheFilePath), _fileSystem.GetLastWriteTimeUtc(cacheFilePath));
} }
catch (ArgumentOutOfRangeException ex) catch (ArgumentOutOfRangeException ex)
{ {
@ -281,7 +276,7 @@ namespace Emby.Drawing
_logger.LogError(ex, "Error encoding image"); _logger.LogError(ex, "Error encoding image");
#endif #endif
// Just spit out the original file if all the options are default // Just spit out the original file if all the options are default
return new Tuple<string, string, DateTime>(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified); return (originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified);
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -289,7 +284,7 @@ namespace Emby.Drawing
_logger.LogError(ex, "Error encoding image"); _logger.LogError(ex, "Error encoding image");
// Just spit out the original file if all the options are default // Just spit out the original file if all the options are default
return new Tuple<string, string, DateTime>(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified); return (originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified);
} }
finally finally
{ {
@ -325,42 +320,17 @@ namespace Emby.Drawing
return ImageFormat.Jpg; return ImageFormat.Jpg;
} }
private void CopyFile(string src, string destination)
{
try
{
_fileSystem.CopyFile(src, destination, true);
}
catch
{
}
}
private string GetMimeType(ImageFormat format, string path) private string GetMimeType(ImageFormat format, string path)
{ {
if (format == ImageFormat.Bmp) switch(format)
{ {
return MimeTypes.GetMimeType("i.bmp"); case ImageFormat.Bmp: return MimeTypes.GetMimeType("i.bmp");
case ImageFormat.Gif: return MimeTypes.GetMimeType("i.gif");
case ImageFormat.Jpg: return MimeTypes.GetMimeType("i.jpg");
case ImageFormat.Png: return MimeTypes.GetMimeType("i.png");
case ImageFormat.Webp: return MimeTypes.GetMimeType("i.webp");
default: return MimeTypes.GetMimeType(path);
} }
if (format == ImageFormat.Gif)
{
return MimeTypes.GetMimeType("i.gif");
}
if (format == ImageFormat.Jpg)
{
return MimeTypes.GetMimeType("i.jpg");
}
if (format == ImageFormat.Png)
{
return MimeTypes.GetMimeType("i.png");
}
if (format == ImageFormat.Webp)
{
return MimeTypes.GetMimeType("i.webp");
}
return MimeTypes.GetMimeType(path);
} }
/// <summary> /// <summary>
@ -373,17 +343,12 @@ namespace Emby.Drawing
/// </summary> /// </summary>
private string GetCacheFilePath(string originalPath, ImageSize outputSize, int quality, DateTime dateModified, ImageFormat format, bool addPlayedIndicator, double percentPlayed, int? unwatchedCount, int? blur, string backgroundColor, string foregroundLayer) private string GetCacheFilePath(string originalPath, ImageSize outputSize, int quality, DateTime dateModified, ImageFormat format, bool addPlayedIndicator, double percentPlayed, int? unwatchedCount, int? blur, string backgroundColor, string foregroundLayer)
{ {
var filename = originalPath; var filename = originalPath
+ "width=" + outputSize.Width
filename += "width=" + outputSize.Width; + "height=" + outputSize.Height
+ "quality=" + quality
filename += "height=" + outputSize.Height; + "datemodified=" + dateModified.Ticks
+ "f=" + format;
filename += "quality=" + quality;
filename += "datemodified=" + dateModified.Ticks;
filename += "f=" + format;
if (addPlayedIndicator) if (addPlayedIndicator)
{ {
@ -421,26 +386,20 @@ namespace Emby.Drawing
} }
public ImageSize GetImageSize(BaseItem item, ItemImageInfo info) public ImageSize GetImageSize(BaseItem item, ItemImageInfo info)
{ => GetImageSize(item, info, true);
return GetImageSize(item, info, true);
}
public ImageSize GetImageSize(BaseItem item, ItemImageInfo info, bool updateItem) public ImageSize GetImageSize(BaseItem item, ItemImageInfo info, bool updateItem)
{ {
var width = info.Width; int width = info.Width;
var height = info.Height; int height = info.Height;
if (height > 0 && width > 0) if (height > 0 && width > 0)
{ {
return new ImageSize return new ImageSize(width, height);
{
Width = width,
Height = height
};
} }
var path = info.Path; string path = info.Path;
_logger.LogInformation("Getting image size for item {0} {1}", item.GetType().Name, path); _logger.LogInformation("Getting image size for item {ItemType} {Path}", item.GetType().Name, path);
var size = GetImageSize(path); var size = GetImageSize(path);
@ -466,15 +425,11 @@ namespace Emby.Drawing
} }
using (var s = new SKFileStream(path)) using (var s = new SKFileStream(path))
using (var codec = SKCodec.Create(s)) using (var codec = SKCodec.Create(s))
{ {
var info = codec.Info; var info = codec.Info;
return new ImageSize return new ImageSize(info.Width, info.Height);
{ }
Height = info.Height,
Width = info.Width
};
}
} }
/// <summary> /// <summary>
@ -518,9 +473,9 @@ namespace Emby.Drawing
/// <exception cref="ArgumentNullException">item</exception> /// <exception cref="ArgumentNullException">item</exception>
public string GetImageCacheTag(BaseItem item, ItemImageInfo image, IImageEnhancer[] imageEnhancers) public string GetImageCacheTag(BaseItem item, ItemImageInfo image, IImageEnhancer[] imageEnhancers)
{ {
var originalImagePath = image.Path; string originalImagePath = image.Path;
var dateModified = image.DateModified; DateTime dateModified = image.DateModified;
var imageType = image.Type; ImageType imageType = image.Type;
// Optimization // Optimization
if (imageEnhancers.Length == 0) if (imageEnhancers.Length == 0)
@ -532,28 +487,28 @@ namespace Emby.Drawing
var cacheKeys = imageEnhancers.Select(i => i.GetConfigurationCacheKey(item, imageType)).ToList(); var cacheKeys = imageEnhancers.Select(i => i.GetConfigurationCacheKey(item, imageType)).ToList();
cacheKeys.Add(originalImagePath + dateModified.Ticks); cacheKeys.Add(originalImagePath + dateModified.Ticks);
return string.Join("|", cacheKeys.ToArray()).GetMD5().ToString("N"); return string.Join("|", cacheKeys).GetMD5().ToString("N");
} }
private async Task<ValueTuple<string, DateTime>> GetSupportedImage(string originalImagePath, DateTime dateModified) private async Task<(string path, DateTime dateModified)> GetSupportedImage(string originalImagePath, DateTime dateModified)
{ {
var inputFormat = (Path.GetExtension(originalImagePath) ?? string.Empty) var inputFormat = Path.GetExtension(originalImagePath)
.TrimStart('.') .TrimStart('.')
.Replace("jpeg", "jpg", StringComparison.OrdinalIgnoreCase); .Replace("jpeg", "jpg", StringComparison.OrdinalIgnoreCase);
// These are just jpg files renamed as tbn // These are just jpg files renamed as tbn
if (string.Equals(inputFormat, "tbn", StringComparison.OrdinalIgnoreCase)) if (string.Equals(inputFormat, "tbn", StringComparison.OrdinalIgnoreCase))
{ {
return new ValueTuple<string, DateTime>(originalImagePath, dateModified); return (originalImagePath, dateModified);
} }
if (!_imageEncoder.SupportedInputFormats.Contains(inputFormat, StringComparer.OrdinalIgnoreCase)) if (!_imageEncoder.SupportedInputFormats.Contains(inputFormat, StringComparer.OrdinalIgnoreCase))
{ {
try try
{ {
var filename = (originalImagePath + dateModified.Ticks.ToString(UsCulture)).GetMD5().ToString("N"); string filename = (originalImagePath + dateModified.Ticks.ToString(UsCulture)).GetMD5().ToString("N");
var cacheExtension = _mediaEncoder().SupportsEncoder("libwebp") ? ".webp" : ".png"; string cacheExtension = _mediaEncoder().SupportsEncoder("libwebp") ? ".webp" : ".png";
var outputPath = Path.Combine(_appPaths.ImageCachePath, "converted-images", filename + cacheExtension); var outputPath = Path.Combine(_appPaths.ImageCachePath, "converted-images", filename + cacheExtension);
var file = _fileSystem.GetFileInfo(outputPath); var file = _fileSystem.GetFileInfo(outputPath);
@ -571,11 +526,11 @@ namespace Emby.Drawing
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogError(ex, "Image conversion failed for {originalImagePath}", originalImagePath); _logger.LogError(ex, "Image conversion failed for {Path}", originalImagePath);
} }
} }
return new ValueTuple<string, DateTime>(originalImagePath, dateModified); return (originalImagePath, dateModified);
} }
/// <summary> /// <summary>
@ -589,16 +544,17 @@ namespace Emby.Drawing
{ {
var enhancers = GetSupportedEnhancers(item, imageType); var enhancers = GetSupportedEnhancers(item, imageType);
var imageInfo = item.GetImageInfo(imageType, imageIndex); ItemImageInfo imageInfo = item.GetImageInfo(imageType, imageIndex);
var inputImageSupportsTransparency = SupportsTransparency(imageInfo.Path); bool inputImageSupportsTransparency = SupportsTransparency(imageInfo.Path);
var result = await GetEnhancedImage(imageInfo, inputImageSupportsTransparency, item, imageIndex, enhancers, CancellationToken.None); var result = await GetEnhancedImage(imageInfo, inputImageSupportsTransparency, item, imageIndex, enhancers, CancellationToken.None);
return result.Item1; return result.path;
} }
private async Task<ValueTuple<string, DateTime, bool>> GetEnhancedImage(ItemImageInfo image, private async Task<(string path, DateTime dateModified, bool transparent)> GetEnhancedImage(
ItemImageInfo image,
bool inputImageSupportsTransparency, bool inputImageSupportsTransparency,
BaseItem item, BaseItem item,
int imageIndex, int imageIndex,
@ -616,14 +572,14 @@ namespace Emby.Drawing
// Enhance if we have enhancers // Enhance if we have enhancers
var enhancedImageInfo = await GetEnhancedImageInternal(originalImagePath, item, imageType, imageIndex, enhancers, cacheGuid, cancellationToken).ConfigureAwait(false); var enhancedImageInfo = await GetEnhancedImageInternal(originalImagePath, item, imageType, imageIndex, enhancers, cacheGuid, cancellationToken).ConfigureAwait(false);
var enhancedImagePath = enhancedImageInfo.Item1; string enhancedImagePath = enhancedImageInfo.path;
// If the path changed update dateModified // If the path changed update dateModified
if (!string.Equals(enhancedImagePath, originalImagePath, StringComparison.OrdinalIgnoreCase)) if (!string.Equals(enhancedImagePath, originalImagePath, StringComparison.OrdinalIgnoreCase))
{ {
var treatmentRequiresTransparency = enhancedImageInfo.Item2; var treatmentRequiresTransparency = enhancedImageInfo.transparent;
return new ValueTuple<string, DateTime, bool>(enhancedImagePath, _fileSystem.GetLastWriteTimeUtc(enhancedImagePath), treatmentRequiresTransparency); return (enhancedImagePath, _fileSystem.GetLastWriteTimeUtc(enhancedImagePath), treatmentRequiresTransparency);
} }
} }
catch (Exception ex) catch (Exception ex)
@ -631,7 +587,7 @@ namespace Emby.Drawing
_logger.LogError(ex, "Error enhancing image"); _logger.LogError(ex, "Error enhancing image");
} }
return new ValueTuple<string, DateTime, bool>(originalImagePath, dateModified, inputImageSupportsTransparency); return (originalImagePath, dateModified, inputImageSupportsTransparency);
} }
/// <summary> /// <summary>
@ -649,7 +605,8 @@ namespace Emby.Drawing
/// or /// or
/// item /// item
/// </exception> /// </exception>
private async Task<ValueTuple<string, bool>> GetEnhancedImageInternal(string originalImagePath, private async Task<(string path, bool transparent)> GetEnhancedImageInternal(
string originalImagePath,
BaseItem item, BaseItem item,
ImageType imageType, ImageType imageType,
int imageIndex, int imageIndex,
@ -677,13 +634,13 @@ namespace Emby.Drawing
} }
// All enhanced images are saved as png to allow transparency // All enhanced images are saved as png to allow transparency
var cacheExtension = _imageEncoder.SupportedOutputFormats.Contains(ImageFormat.Webp) ? string cacheExtension = _imageEncoder.SupportedOutputFormats.Contains(ImageFormat.Webp) ?
".webp" : ".webp" :
(treatmentRequiresTransparency ? ".png" : ".jpg"); (treatmentRequiresTransparency ? ".png" : ".jpg");
var enhancedImagePath = GetCachePath(EnhancedImageCachePath, cacheGuid + cacheExtension); string enhancedImagePath = GetCachePath(EnhancedImageCachePath, cacheGuid + cacheExtension);
var lockInfo = GetLock(enhancedImagePath); LockInfo lockInfo = GetLock(enhancedImagePath);
await lockInfo.Lock.WaitAsync(cancellationToken).ConfigureAwait(false); await lockInfo.Lock.WaitAsync(cancellationToken).ConfigureAwait(false);
@ -692,14 +649,14 @@ namespace Emby.Drawing
// Check again in case of contention // Check again in case of contention
if (_fileSystem.FileExists(enhancedImagePath)) if (_fileSystem.FileExists(enhancedImagePath))
{ {
return new ValueTuple<string, bool>(enhancedImagePath, treatmentRequiresTransparency); return (enhancedImagePath, treatmentRequiresTransparency);
} }
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(enhancedImagePath)); _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(enhancedImagePath));
await ExecuteImageEnhancers(supportedEnhancers, originalImagePath, enhancedImagePath, item, imageType, imageIndex).ConfigureAwait(false); await ExecuteImageEnhancers(supportedEnhancers, originalImagePath, enhancedImagePath, item, imageType, imageIndex).ConfigureAwait(false);
return new ValueTuple<string, bool>(enhancedImagePath, treatmentRequiresTransparency); return (enhancedImagePath, treatmentRequiresTransparency);
} }
finally finally
{ {
@ -788,18 +745,16 @@ namespace Emby.Drawing
var prefix = filename.Substring(0, 1); var prefix = filename.Substring(0, 1);
path = Path.Combine(path, prefix); return Path.Combine(path, prefix, filename);
return Path.Combine(path, filename);
} }
public void CreateImageCollage(ImageCollageOptions options) public void CreateImageCollage(ImageCollageOptions options)
{ {
_logger.LogInformation("Creating image collage and saving to {0}", options.OutputPath); _logger.LogInformation("Creating image collage and saving to {Path}", options.OutputPath);
_imageEncoder.CreateImageCollage(options); _imageEncoder.CreateImageCollage(options);
_logger.LogInformation("Completed creation of image collage and saved to {0}", options.OutputPath); _logger.LogInformation("Completed creation of image collage and saved to {Path}", options.OutputPath);
} }
public IImageEnhancer[] GetSupportedEnhancers(BaseItem item, ImageType imageType) public IImageEnhancer[] GetSupportedEnhancers(BaseItem item, ImageType imageType)

View file

@ -1050,7 +1050,7 @@ namespace Emby.Server.Implementations
private IImageProcessor GetImageProcessor() private IImageProcessor GetImageProcessor()
{ {
return new ImageProcessor(LoggerFactory.CreateLogger("ImageProcessor"), ServerConfigurationManager.ApplicationPaths, FileSystemManager, JsonSerializer, ImageEncoder, () => LibraryManager, TimerFactory, () => MediaEncoder); return new ImageProcessor(LoggerFactory.CreateLogger("ImageProcessor"), ServerConfigurationManager.ApplicationPaths, FileSystemManager, ImageEncoder, () => LibraryManager, () => MediaEncoder);
} }
protected virtual FFMpegInstallInfo GetFfmpegInstallInfo() protected virtual FFMpegInstallInfo GetFfmpegInstallInfo()

View file

@ -103,7 +103,7 @@ namespace Jellyfin.Server
{ {
appHost.Init(); appHost.Init();
appHost.ImageProcessor.ImageEncoder = getImageEncoder(_logger, fileSystem, options, () => appHost.HttpClient, appPaths, environmentInfo, appHost.LocalizationManager); appHost.ImageProcessor.ImageEncoder = GetImageEncoder(_logger, fileSystem, options, () => appHost.HttpClient, appPaths, environmentInfo, appHost.LocalizationManager);
_logger.LogInformation("Running startup tasks"); _logger.LogInformation("Running startup tasks");
@ -256,13 +256,12 @@ namespace Jellyfin.Server
} }
} }
public static IImageEncoder getImageEncoder( public static IImageEncoder GetImageEncoder(
ILogger logger, ILogger logger,
IFileSystem fileSystem, IFileSystem fileSystem,
StartupOptions startupOptions, StartupOptions startupOptions,
Func<IHttpClient> httpClient, Func<IHttpClient> httpClient,
IApplicationPaths appPaths, IApplicationPaths appPaths,
IEnvironmentInfo environment,
ILocalizationManager localizationManager) ILocalizationManager localizationManager)
{ {
try try

View file

@ -82,7 +82,7 @@ namespace MediaBrowser.Controller.Drawing
/// </summary> /// </summary>
/// <param name="options">The options.</param> /// <param name="options">The options.</param>
/// <returns>Task.</returns> /// <returns>Task.</returns>
Task<Tuple<string, string, DateTime>> ProcessImage(ImageProcessingOptions options); Task<(string path, string mimeType, DateTime dateModified)> ProcessImage(ImageProcessingOptions options);
/// <summary> /// <summary>
/// Gets the enhanced image. /// Gets the enhanced image.