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.cs144
1 files changed, 115 insertions, 29 deletions
diff --git a/Emby.Drawing/ImageProcessor.cs b/Emby.Drawing/ImageProcessor.cs
index 88ead3a5f..1d3f4a8e3 100644
--- a/Emby.Drawing/ImageProcessor.cs
+++ b/Emby.Drawing/ImageProcessor.cs
@@ -17,12 +17,11 @@ using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Model.IO;
using Emby.Drawing.Common;
-
-using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Model.Net;
using MediaBrowser.Model.Threading;
-using TagLib;
+using MediaBrowser.Model.Extensions;
namespace Emby.Drawing
{
@@ -46,7 +45,7 @@ namespace Emby.Drawing
/// Image processors are specialized metadata providers that run after the normal ones
/// </summary>
/// <value>The image enhancers.</value>
- public IEnumerable<IImageEnhancer> ImageEnhancers { get; private set; }
+ public IImageEnhancer[] ImageEnhancers { get; private set; }
/// <summary>
/// The _logger
@@ -58,22 +57,24 @@ namespace Emby.Drawing
private readonly IServerApplicationPaths _appPaths;
private IImageEncoder _imageEncoder;
private readonly Func<ILibraryManager> _libraryManager;
+ private readonly Func<IMediaEncoder> _mediaEncoder;
public ImageProcessor(ILogger logger,
IServerApplicationPaths appPaths,
IFileSystem fileSystem,
IJsonSerializer jsonSerializer,
IImageEncoder imageEncoder,
- Func<ILibraryManager> libraryManager, ITimerFactory timerFactory)
+ Func<ILibraryManager> libraryManager, ITimerFactory timerFactory, Func<IMediaEncoder> mediaEncoder)
{
_logger = logger;
_fileSystem = fileSystem;
_jsonSerializer = jsonSerializer;
_imageEncoder = imageEncoder;
_libraryManager = libraryManager;
+ _mediaEncoder = mediaEncoder;
_appPaths = appPaths;
- ImageEnhancers = new List<IImageEnhancer>();
+ ImageEnhancers = new IImageEnhancer[] { };
_saveImageSizeTimer = timerFactory.Create(SaveImageSizeCallback, null, Timeout.Infinite, Timeout.Infinite);
ImageHelper.ImageProcessor = this;
@@ -122,7 +123,37 @@ namespace Emby.Drawing
{
get
{
- return _imageEncoder.SupportedInputFormats;
+ return new string[]
+ {
+ "tiff",
+ "tif",
+ "jpeg",
+ "jpg",
+ "png",
+ "aiff",
+ "cr2",
+ "crw",
+ "dng",
+
+ // Remove until supported
+ //"nef",
+ "orf",
+ "pef",
+ "arw",
+ "webp",
+ "gif",
+ "bmp",
+ "erf",
+ "raf",
+ "rw2",
+ "nrw",
+ "dng",
+ "ico",
+ "astc",
+ "ktx",
+ "pkm",
+ "wbmp"
+ };
}
}
@@ -186,7 +217,7 @@ namespace Emby.Drawing
}
var originalImage = options.Image;
- IHasImages item = options.Item;
+ IHasMetadata item = options.Item;
if (!originalImage.IsLocalFile)
{
@@ -205,6 +236,10 @@ namespace Emby.Drawing
return new Tuple<string, string, DateTime>(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified);
}
+ var supportedImageInfo = await GetSupportedImage(originalImagePath, dateModified).ConfigureAwait(false);
+ originalImagePath = supportedImageInfo.Item1;
+ dateModified = supportedImageInfo.Item2;
+
if (options.Enhancers.Count > 0)
{
if (item == null)
@@ -262,11 +297,6 @@ namespace Emby.Drawing
var tmpPath = Path.ChangeExtension(Path.Combine(_appPaths.TempDirectory, Guid.NewGuid().ToString("N")), Path.GetExtension(cacheFilePath));
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(tmpPath));
- if (item == null && string.Equals(options.ItemType, typeof(Photo).Name, StringComparison.OrdinalIgnoreCase))
- {
- item = _libraryManager().GetItemById(options.ItemId);
- }
-
if (options.CropWhiteSpace && !SupportsTransparency(originalImagePath))
{
options.CropWhiteSpace = false;
@@ -287,6 +317,15 @@ namespace Emby.Drawing
return new Tuple<string, string, DateTime>(cacheFilePath, GetMimeType(outputFormat, cacheFilePath), _fileSystem.GetLastWriteTimeUtc(cacheFilePath));
}
+ catch (ArgumentOutOfRangeException ex)
+ {
+ // Decoder failed to decode it
+#if DEBUG
+ _logger.ErrorException("Error encoding image", ex);
+#endif
+ // Just spit out the original file if all the options are default
+ return new Tuple<string, string, DateTime>(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified);
+ }
catch (Exception ex)
{
// If it fails for whatever reason, return the original image
@@ -606,7 +645,7 @@ namespace Emby.Drawing
/// <param name="image">The image.</param>
/// <returns>Guid.</returns>
/// <exception cref="System.ArgumentNullException">item</exception>
- public string GetImageCacheTag(IHasImages item, ItemImageInfo image)
+ public string GetImageCacheTag(IHasMetadata item, ItemImageInfo image)
{
if (item == null)
{
@@ -620,7 +659,7 @@ namespace Emby.Drawing
var supportedEnhancers = GetSupportedEnhancers(item, image.Type);
- return GetImageCacheTag(item, image, supportedEnhancers.ToList());
+ return GetImageCacheTag(item, image, supportedEnhancers);
}
/// <summary>
@@ -631,7 +670,7 @@ namespace Emby.Drawing
/// <param name="imageEnhancers">The image enhancers.</param>
/// <returns>Guid.</returns>
/// <exception cref="System.ArgumentNullException">item</exception>
- public string GetImageCacheTag(IHasImages item, ItemImageInfo image, List<IImageEnhancer> imageEnhancers)
+ public string GetImageCacheTag(IHasMetadata item, ItemImageInfo image, List<IImageEnhancer> imageEnhancers)
{
if (item == null)
{
@@ -662,7 +701,43 @@ namespace Emby.Drawing
var cacheKeys = imageEnhancers.Select(i => i.GetConfigurationCacheKey(item, imageType)).ToList();
cacheKeys.Add(originalImagePath + dateModified.Ticks);
- return string.Join("|", cacheKeys.ToArray()).GetMD5().ToString("N");
+ return string.Join("|", cacheKeys.ToArray(cacheKeys.Count)).GetMD5().ToString("N");
+ }
+
+ private async Task<Tuple<string, DateTime>> GetSupportedImage(string originalImagePath, DateTime dateModified)
+ {
+ var inputFormat = (Path.GetExtension(originalImagePath) ?? string.Empty)
+ .TrimStart('.')
+ .Replace("jpeg", "jpg", StringComparison.OrdinalIgnoreCase);
+
+ if (!_imageEncoder.SupportedInputFormats.Contains(inputFormat, StringComparer.OrdinalIgnoreCase))
+ {
+ try
+ {
+ var filename = (originalImagePath + dateModified.Ticks.ToString(UsCulture)).GetMD5().ToString("N");
+
+ var outputPath = Path.Combine(_appPaths.ImageCachePath, "converted-images", filename + ".webp");
+
+ var file = _fileSystem.GetFileInfo(outputPath);
+ if (!file.Exists)
+ {
+ await _mediaEncoder().ConvertImage(originalImagePath, outputPath).ConfigureAwait(false);
+ dateModified = _fileSystem.GetLastWriteTimeUtc(outputPath);
+ }
+ else
+ {
+ dateModified = file.LastWriteTimeUtc;
+ }
+
+ originalImagePath = outputPath;
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Image conversion failed for {0}", ex, originalImagePath);
+ }
+ }
+
+ return new Tuple<string, DateTime>(originalImagePath, dateModified);
}
/// <summary>
@@ -672,9 +747,9 @@ namespace Emby.Drawing
/// <param name="imageType">Type of the image.</param>
/// <param name="imageIndex">Index of the image.</param>
/// <returns>Task{System.String}.</returns>
- public async Task<string> GetEnhancedImage(IHasImages item, ImageType imageType, int imageIndex)
+ public async Task<string> GetEnhancedImage(IHasMetadata item, ImageType imageType, int imageIndex)
{
- var enhancers = GetSupportedEnhancers(item, imageType).ToList();
+ var enhancers = GetSupportedEnhancers(item, imageType);
var imageInfo = item.GetImageInfo(imageType, imageIndex);
@@ -684,7 +759,7 @@ namespace Emby.Drawing
}
private async Task<Tuple<string, DateTime>> GetEnhancedImage(ItemImageInfo image,
- IHasImages item,
+ IHasMetadata item,
int imageIndex,
List<IImageEnhancer> enhancers)
{
@@ -729,7 +804,7 @@ namespace Emby.Drawing
/// item
/// </exception>
private async Task<string> GetEnhancedImageInternal(string originalImagePath,
- IHasImages item,
+ IHasMetadata item,
ImageType imageType,
int imageIndex,
IEnumerable<IImageEnhancer> supportedEnhancers,
@@ -783,7 +858,7 @@ namespace Emby.Drawing
/// <param name="imageType">Type of the image.</param>
/// <param name="imageIndex">Index of the image.</param>
/// <returns>Task{EnhancedImage}.</returns>
- private async Task ExecuteImageEnhancers(IEnumerable<IImageEnhancer> imageEnhancers, string inputPath, string outputPath, IHasImages item, ImageType imageType, int imageIndex)
+ private async Task ExecuteImageEnhancers(IEnumerable<IImageEnhancer> imageEnhancers, string inputPath, string outputPath, IHasMetadata item, ImageType imageType, int imageIndex)
{
// Run the enhancers sequentially in order of priority
foreach (var enhancer in imageEnhancers)
@@ -868,29 +943,40 @@ namespace Emby.Drawing
_logger.Info("Completed creation of image collage and saved to {0}", options.OutputPath);
}
- public IEnumerable<IImageEnhancer> GetSupportedEnhancers(IHasImages item, ImageType imageType)
+ public List<IImageEnhancer> GetSupportedEnhancers(IHasMetadata item, ImageType imageType)
{
- return ImageEnhancers.Where(i =>
+ var list = new List<IImageEnhancer>();
+
+ foreach (var i in ImageEnhancers)
{
try
{
- return i.Supports(item, imageType);
+ if (i.Supports(item, imageType))
+ {
+ list.Add(i);
+ }
}
catch (Exception ex)
{
_logger.ErrorException("Error in image enhancer: {0}", ex, i.GetType().Name);
-
- return false;
}
- });
+ }
+ return list;
}
private bool _disposed;
public void Dispose()
{
_disposed = true;
- _imageEncoder.Dispose();
+
+ var disposable = _imageEncoder as IDisposable;
+ if (disposable != null)
+ {
+ disposable.Dispose();
+ }
+
_saveImageSizeTimer.Dispose();
+ GC.SuppressFinalize(this);
}
private void CheckDisposed()