@ -203,10 +203,9 @@ namespace Emby.Drawing
}
private static readonly string [ ] TransparentImageTypes = new string [ ] { ".png" , ".webp" } ;
p rivate bool SupportsTransparency ( string path )
p ublic 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>