|
@@ -203,10 +203,9 @@ namespace Emby.Drawing
|
|
|
}
|
|
|
|
|
|
private static readonly string[] TransparentImageTypes = new string[] { ".png", ".webp" };
|
|
|
- private bool SupportsTransparency(string path)
|
|
|
+ public bool SupportsTransparency(string path)
|
|
|
{
|
|
|
return TransparentImageTypes.Contains(Path.GetExtension(path) ?? string.Empty);
|
|
|
- ;
|
|
|
}
|
|
|
|
|
|
public async Task<Tuple<string, string, DateTime>> ProcessImage(ImageProcessingOptions options)
|
|
@@ -239,6 +238,7 @@ namespace Emby.Drawing
|
|
|
var supportedImageInfo = await GetSupportedImage(originalImagePath, dateModified).ConfigureAwait(false);
|
|
|
originalImagePath = supportedImageInfo.Item1;
|
|
|
dateModified = supportedImageInfo.Item2;
|
|
|
+ var requiresTransparency = TransparentImageTypes.Contains(Path.GetExtension(originalImagePath) ?? string.Empty);
|
|
|
|
|
|
if (options.Enhancers.Count > 0)
|
|
|
{
|
|
@@ -253,10 +253,11 @@ namespace Emby.Drawing
|
|
|
Type = originalImage.Type,
|
|
|
Path = originalImagePath
|
|
|
|
|
|
- }, item, options.ImageIndex, options.Enhancers).ConfigureAwait(false);
|
|
|
+ }, requiresTransparency, item, options.ImageIndex, options.Enhancers).ConfigureAwait(false);
|
|
|
|
|
|
originalImagePath = tuple.Item1;
|
|
|
dateModified = tuple.Item2;
|
|
|
+ requiresTransparency = tuple.Item3;
|
|
|
}
|
|
|
|
|
|
var photo = item as Photo;
|
|
@@ -268,7 +269,7 @@ namespace Emby.Drawing
|
|
|
orientation = photo.Orientation;
|
|
|
}
|
|
|
|
|
|
- if (options.HasDefaultOptions(originalImagePath) && !autoOrient)
|
|
|
+ if (options.HasDefaultOptions(originalImagePath) && (!autoOrient || !options.RequiresAutoOrientation))
|
|
|
{
|
|
|
// Just spit out the original file if all the options are default
|
|
|
return new Tuple<string, string, DateTime>(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified);
|
|
@@ -285,7 +286,7 @@ namespace Emby.Drawing
|
|
|
var newSize = ImageHelper.GetNewImageSize(options, originalImageSize);
|
|
|
var quality = options.Quality;
|
|
|
|
|
|
- var outputFormat = GetOutputFormat(options.SupportedOutputFormats[0]);
|
|
|
+ var 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);
|
|
|
|
|
|
try
|
|
@@ -336,6 +337,34 @@ namespace Emby.Drawing
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ private ImageFormat GetOutputFormat(ImageFormat[] clientSupportedFormats, bool requiresTransparency)
|
|
|
+ {
|
|
|
+ var serverFormats = GetSupportedImageOutputFormats();
|
|
|
+
|
|
|
+ // Client doesn't care about format, so start with webp if supported
|
|
|
+ if (serverFormats.Contains(ImageFormat.Webp) && clientSupportedFormats.Contains(ImageFormat.Webp))
|
|
|
+ {
|
|
|
+ return ImageFormat.Webp;
|
|
|
+ }
|
|
|
+
|
|
|
+ // If transparency is needed and webp isn't supported, than png is the only option
|
|
|
+ if (requiresTransparency)
|
|
|
+ {
|
|
|
+ return ImageFormat.Png;
|
|
|
+ }
|
|
|
+
|
|
|
+ foreach (var format in clientSupportedFormats)
|
|
|
+ {
|
|
|
+ if (serverFormats.Contains(format))
|
|
|
+ {
|
|
|
+ return format;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // We should never actually get here
|
|
|
+ return ImageFormat.Jpg;
|
|
|
+ }
|
|
|
+
|
|
|
private void CopyFile(string src, string destination)
|
|
|
{
|
|
|
try
|
|
@@ -389,21 +418,6 @@ namespace Emby.Drawing
|
|
|
return MimeTypes.GetMimeType(path);
|
|
|
}
|
|
|
|
|
|
- private ImageFormat GetOutputFormat(ImageFormat requestedFormat)
|
|
|
- {
|
|
|
- if (requestedFormat == ImageFormat.Webp && !_imageEncoder.SupportedOutputFormats.Contains(ImageFormat.Webp))
|
|
|
- {
|
|
|
- return ImageFormat.Png;
|
|
|
- }
|
|
|
-
|
|
|
- return requestedFormat;
|
|
|
- }
|
|
|
-
|
|
|
- private Tuple<string, DateTime> GetResult(string path)
|
|
|
- {
|
|
|
- return new Tuple<string, DateTime>(path, _fileSystem.GetLastWriteTimeUtc(path));
|
|
|
- }
|
|
|
-
|
|
|
/// <summary>
|
|
|
/// Increment this when there's a change requiring caches to be invalidated
|
|
|
/// </summary>
|
|
@@ -753,12 +767,15 @@ namespace Emby.Drawing
|
|
|
|
|
|
var imageInfo = item.GetImageInfo(imageType, imageIndex);
|
|
|
|
|
|
- var result = await GetEnhancedImage(imageInfo, item, imageIndex, enhancers);
|
|
|
+ var inputImageSupportsTransparency = SupportsTransparency(imageInfo.Path);
|
|
|
+
|
|
|
+ var result = await GetEnhancedImage(imageInfo, inputImageSupportsTransparency, item, imageIndex, enhancers);
|
|
|
|
|
|
return result.Item1;
|
|
|
}
|
|
|
|
|
|
- private async Task<Tuple<string, DateTime>> GetEnhancedImage(ItemImageInfo image,
|
|
|
+ private async Task<Tuple<string, DateTime, bool>> GetEnhancedImage(ItemImageInfo image,
|
|
|
+ bool inputImageSupportsTransparency,
|
|
|
IHasMetadata item,
|
|
|
int imageIndex,
|
|
|
List<IImageEnhancer> enhancers)
|
|
@@ -772,12 +789,16 @@ namespace Emby.Drawing
|
|
|
var cacheGuid = GetImageCacheTag(item, image, enhancers);
|
|
|
|
|
|
// Enhance if we have enhancers
|
|
|
- var ehnancedImagePath = await GetEnhancedImageInternal(originalImagePath, item, imageType, imageIndex, enhancers, cacheGuid).ConfigureAwait(false);
|
|
|
+ var ehnancedImageInfo = await GetEnhancedImageInternal(originalImagePath, item, imageType, imageIndex, enhancers, cacheGuid).ConfigureAwait(false);
|
|
|
+
|
|
|
+ var ehnancedImagePath = ehnancedImageInfo.Item1;
|
|
|
|
|
|
// If the path changed update dateModified
|
|
|
if (!string.Equals(ehnancedImagePath, originalImagePath, StringComparison.OrdinalIgnoreCase))
|
|
|
{
|
|
|
- return GetResult(ehnancedImagePath);
|
|
|
+ var treatmentRequiresTransparency = ehnancedImageInfo.Item2;
|
|
|
+
|
|
|
+ return new Tuple<string, DateTime, bool>(ehnancedImagePath, _fileSystem.GetLastWriteTimeUtc(ehnancedImagePath), treatmentRequiresTransparency);
|
|
|
}
|
|
|
}
|
|
|
catch (Exception ex)
|
|
@@ -785,7 +806,7 @@ namespace Emby.Drawing
|
|
|
_logger.Error("Error enhancing image", ex);
|
|
|
}
|
|
|
|
|
|
- return new Tuple<string, DateTime>(originalImagePath, dateModified);
|
|
|
+ return new Tuple<string, DateTime, bool>(originalImagePath, dateModified, inputImageSupportsTransparency);
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
@@ -803,11 +824,11 @@ namespace Emby.Drawing
|
|
|
/// or
|
|
|
/// item
|
|
|
/// </exception>
|
|
|
- private async Task<string> GetEnhancedImageInternal(string originalImagePath,
|
|
|
+ private async Task<Tuple<string, bool>> GetEnhancedImageInternal(string originalImagePath,
|
|
|
IHasMetadata item,
|
|
|
ImageType imageType,
|
|
|
int imageIndex,
|
|
|
- IEnumerable<IImageEnhancer> supportedEnhancers,
|
|
|
+ List<IImageEnhancer> supportedEnhancers,
|
|
|
string cacheGuid)
|
|
|
{
|
|
|
if (string.IsNullOrEmpty(originalImagePath))
|
|
@@ -820,13 +841,26 @@ namespace Emby.Drawing
|
|
|
throw new ArgumentNullException("item");
|
|
|
}
|
|
|
|
|
|
+ var treatmentRequiresTransparency = false;
|
|
|
+ foreach (var enhancer in supportedEnhancers)
|
|
|
+ {
|
|
|
+ if (!treatmentRequiresTransparency)
|
|
|
+ {
|
|
|
+ treatmentRequiresTransparency = enhancer.GetEnhancedImageInfo(item, originalImagePath, imageType, imageIndex).RequiresTransparency;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
// All enhanced images are saved as png to allow transparency
|
|
|
- var enhancedImagePath = GetCachePath(EnhancedImageCachePath, cacheGuid + ".png");
|
|
|
+ var cacheExtension = _imageEncoder.SupportedOutputFormats.Contains(ImageFormat.Webp) ?
|
|
|
+ ".webp" :
|
|
|
+ (treatmentRequiresTransparency ? ".png" : ".jpg");
|
|
|
+
|
|
|
+ var enhancedImagePath = GetCachePath(EnhancedImageCachePath, cacheGuid + cacheExtension);
|
|
|
|
|
|
// Check again in case of contention
|
|
|
if (_fileSystem.FileExists(enhancedImagePath))
|
|
|
{
|
|
|
- return enhancedImagePath;
|
|
|
+ return new Tuple<string, bool>(enhancedImagePath, treatmentRequiresTransparency);
|
|
|
}
|
|
|
|
|
|
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(enhancedImagePath));
|
|
@@ -845,7 +879,7 @@ namespace Emby.Drawing
|
|
|
|
|
|
}
|
|
|
|
|
|
- return tmpPath;
|
|
|
+ return new Tuple<string, bool>(tmpPath, treatmentRequiresTransparency);
|
|
|
}
|
|
|
|
|
|
/// <summary>
|