mirror of
https://github.com/jellyfin/jellyfin.git
synced 2024-09-06 11:34:57 +02:00
commit
5bcb6ec675
12 changed files with 124 additions and 102 deletions
|
@ -130,7 +130,7 @@ namespace Emby.Drawing.ImageMagick
|
|||
string.Equals(ext, ".webp", StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
public void EncodeImage(string inputPath, string outputPath, bool autoOrient, int width, int height, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat)
|
||||
public void EncodeImage(string inputPath, ImageSize? originalImageSize, string outputPath, bool autoOrient, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat)
|
||||
{
|
||||
// Even if the caller specified 100, don't use it because it takes forever
|
||||
quality = Math.Min(quality, 99);
|
||||
|
@ -144,6 +144,16 @@ namespace Emby.Drawing.ImageMagick
|
|||
originalImage.CurrentImage.TrimImage(10);
|
||||
}
|
||||
|
||||
if (options.CropWhiteSpace || !originalImageSize.HasValue)
|
||||
{
|
||||
originalImageSize = new ImageSize(originalImage.CurrentImage.Width, originalImage.CurrentImage.Height);
|
||||
}
|
||||
|
||||
var newImageSize = ImageHelper.GetNewImageSize(options, originalImageSize);
|
||||
|
||||
var width = Convert.ToInt32(Math.Round(newImageSize.Width));
|
||||
var height = Convert.ToInt32(Math.Round(newImageSize.Height));
|
||||
|
||||
ScaleImage(originalImage, width, height, options.Blur ?? 0);
|
||||
|
||||
if (autoOrient)
|
||||
|
@ -162,9 +172,19 @@ namespace Emby.Drawing.ImageMagick
|
|||
}
|
||||
else
|
||||
{
|
||||
using (var wand = new MagickWand(width, height, options.BackgroundColor))
|
||||
using (var originalImage = new MagickWand(inputPath))
|
||||
{
|
||||
using (var originalImage = new MagickWand(inputPath))
|
||||
if (options.CropWhiteSpace || !originalImageSize.HasValue)
|
||||
{
|
||||
originalImageSize = new ImageSize(originalImage.CurrentImage.Width, originalImage.CurrentImage.Height);
|
||||
}
|
||||
|
||||
var newImageSize = ImageHelper.GetNewImageSize(options, originalImageSize);
|
||||
|
||||
var width = Convert.ToInt32(Math.Round(newImageSize.Width));
|
||||
var height = Convert.ToInt32(Math.Round(newImageSize.Height));
|
||||
|
||||
using (var wand = new MagickWand(width, height, options.BackgroundColor))
|
||||
{
|
||||
ScaleImage(originalImage, width, height, options.Blur ?? 0);
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ using MediaBrowser.Common.IO;
|
|||
using MediaBrowser.Controller.IO;
|
||||
using MediaBrowser.Model.IO;
|
||||
using ImageFormat = MediaBrowser.Model.Drawing.ImageFormat;
|
||||
using Emby.Drawing;
|
||||
|
||||
namespace Emby.Drawing.Net
|
||||
{
|
||||
|
@ -88,14 +89,19 @@ namespace Emby.Drawing.Net
|
|||
return Image.FromFile(path);
|
||||
}
|
||||
|
||||
public void EncodeImage(string inputPath, string cacheFilePath, bool autoOrient, int width, int height, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat)
|
||||
public void EncodeImage(string inputPath, ImageSize? originalImageSize, string outputPath, bool autoOrient, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat)
|
||||
{
|
||||
var hasPostProcessing = !string.IsNullOrEmpty(options.BackgroundColor) || options.UnplayedCount.HasValue || options.AddPlayedIndicator || options.PercentPlayed > 0;
|
||||
|
||||
using (var originalImage = GetImage(inputPath, options.CropWhiteSpace))
|
||||
{
|
||||
var newWidth = Convert.ToInt32(width);
|
||||
var newHeight = Convert.ToInt32(height);
|
||||
if (options.CropWhiteSpace || !originalImageSize.HasValue)
|
||||
{
|
||||
originalImageSize = new ImageSize(originalImage.Width, originalImage.Height);
|
||||
}
|
||||
|
||||
var newImageSize = ImageHelper.GetNewImageSize(options, originalImageSize);
|
||||
|
||||
var newWidth = Convert.ToInt32(Math.Round(newImageSize.Width));
|
||||
var newHeight = Convert.ToInt32(Math.Round(newImageSize.Height));
|
||||
|
||||
// Graphics.FromImage will throw an exception if the PixelFormat is Indexed, so we need to handle that here
|
||||
// Also, Webp only supports Format32bppArgb and Format32bppRgb
|
||||
|
@ -132,10 +138,8 @@ namespace Emby.Drawing.Net
|
|||
|
||||
var outputFormat = GetOutputFormat(originalImage, selectedOutputFormat);
|
||||
|
||||
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(cacheFilePath));
|
||||
|
||||
// Save to the cache location
|
||||
using (var cacheFileStream = _fileSystem.GetFileStream(cacheFilePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, false))
|
||||
using (var cacheFileStream = _fileSystem.GetFileStream(outputPath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, false))
|
||||
{
|
||||
// Save to the memory stream
|
||||
thumbnail.Save(outputFormat, cacheFileStream, quality);
|
||||
|
|
|
@ -226,7 +226,7 @@ namespace Emby.Drawing.Skia
|
|||
return Decode(path);
|
||||
}
|
||||
|
||||
public void EncodeImage(string inputPath, string outputPath, bool autoOrient, int width, int height, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat)
|
||||
public void EncodeImage(string inputPath, ImageSize? originalImageSize, string outputPath, bool autoOrient, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(inputPath))
|
||||
{
|
||||
|
@ -246,6 +246,16 @@ namespace Emby.Drawing.Skia
|
|||
|
||||
using (var bitmap = GetBitmap(inputPath, options.CropWhiteSpace))
|
||||
{
|
||||
if (options.CropWhiteSpace || !originalImageSize.HasValue)
|
||||
{
|
||||
originalImageSize = new ImageSize(bitmap.Width, bitmap.Height);
|
||||
}
|
||||
|
||||
var newImageSize = ImageHelper.GetNewImageSize(options, originalImageSize);
|
||||
|
||||
var width = Convert.ToInt32(Math.Round(newImageSize.Width));
|
||||
var height = Convert.ToInt32(Math.Round(newImageSize.Height));
|
||||
|
||||
using (var resizedBitmap = new SKBitmap(width, height))//, bitmap.ColorType, bitmap.AlphaType))
|
||||
{
|
||||
// scale image
|
||||
|
|
|
@ -227,7 +227,7 @@ namespace Emby.Drawing
|
|||
originalImageSize = null;
|
||||
}
|
||||
|
||||
var newSize = GetNewImageSize(options, originalImageSize);
|
||||
var newSize = ImageHelper.GetNewImageSize(options, originalImageSize);
|
||||
var quality = options.Quality;
|
||||
|
||||
var outputFormat = GetOutputFormat(options.SupportedOutputFormats[0]);
|
||||
|
@ -239,14 +239,11 @@ namespace Emby.Drawing
|
|||
|
||||
if (!_fileSystem.FileExists(cacheFilePath))
|
||||
{
|
||||
var newWidth = Convert.ToInt32(Math.Round(newSize.Width));
|
||||
var newHeight = Convert.ToInt32(Math.Round(newSize.Height));
|
||||
|
||||
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(cacheFilePath));
|
||||
var tmpPath = Path.ChangeExtension(Path.Combine(_appPaths.TempDirectory, Guid.NewGuid().ToString("N")), Path.GetExtension(cacheFilePath));
|
||||
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(tmpPath));
|
||||
|
||||
_imageEncoder.EncodeImage(originalImagePath, tmpPath, AutoOrient(options.Item), newWidth, newHeight, quality, options, outputFormat);
|
||||
_imageEncoder.EncodeImage(originalImagePath, originalImageSize, tmpPath, AutoOrient(options.Item), quality, options, outputFormat);
|
||||
CopyFile(tmpPath, cacheFilePath);
|
||||
|
||||
return new Tuple<string, string, DateTime>(tmpPath, GetMimeType(outputFormat, cacheFilePath), _fileSystem.GetLastWriteTimeUtc(tmpPath));
|
||||
|
@ -328,66 +325,6 @@ namespace Emby.Drawing
|
|||
return MimeTypes.GetMimeType(path);
|
||||
}
|
||||
|
||||
private ImageSize GetNewImageSize(ImageProcessingOptions options, ImageSize? originalImageSize)
|
||||
{
|
||||
if (originalImageSize.HasValue)
|
||||
{
|
||||
// Determine the output size based on incoming parameters
|
||||
var newSize = DrawingUtils.Resize(originalImageSize.Value, options.Width, options.Height, options.MaxWidth, options.MaxHeight);
|
||||
|
||||
return newSize;
|
||||
}
|
||||
return GetSizeEstimate(options);
|
||||
}
|
||||
|
||||
private ImageSize GetSizeEstimate(ImageProcessingOptions options)
|
||||
{
|
||||
if (options.Width.HasValue && options.Height.HasValue)
|
||||
{
|
||||
return new ImageSize(options.Width.Value, options.Height.Value);
|
||||
}
|
||||
|
||||
var aspect = GetEstimatedAspectRatio(options.Image.Type, options.Item);
|
||||
|
||||
var width = options.Width ?? options.MaxWidth;
|
||||
|
||||
if (width.HasValue)
|
||||
{
|
||||
var heightValue = width.Value / aspect;
|
||||
return new ImageSize(width.Value, heightValue);
|
||||
}
|
||||
|
||||
var height = options.Height ?? options.MaxHeight ?? 200;
|
||||
var widthValue = aspect * height;
|
||||
return new ImageSize(widthValue, height);
|
||||
}
|
||||
|
||||
private double GetEstimatedAspectRatio(ImageType type, IHasImages item)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case ImageType.Art:
|
||||
case ImageType.Backdrop:
|
||||
case ImageType.Chapter:
|
||||
case ImageType.Screenshot:
|
||||
case ImageType.Thumb:
|
||||
return 1.78;
|
||||
case ImageType.Banner:
|
||||
return 5.4;
|
||||
case ImageType.Box:
|
||||
case ImageType.BoxRear:
|
||||
case ImageType.Disc:
|
||||
case ImageType.Menu:
|
||||
return 1;
|
||||
case ImageType.Logo:
|
||||
return 2.58;
|
||||
case ImageType.Primary:
|
||||
return item.GetDefaultPrimaryImageAspectRatio() ?? .667;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
private ImageFormat GetOutputFormat(ImageFormat requestedFormat)
|
||||
{
|
||||
if (requestedFormat == ImageFormat.Webp && !_imageEncoder.SupportedOutputFormats.Contains(ImageFormat.Webp))
|
||||
|
|
|
@ -32,7 +32,7 @@ namespace Emby.Drawing
|
|||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void EncodeImage(string inputPath, string outputPath, bool autoOrient, int width, int height, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat)
|
||||
public void EncodeImage(string inputPath, ImageSize? originalImageSize, string outputPath, bool autoOrient, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
|
|
@ -2854,7 +2854,7 @@ namespace Emby.Server.Implementations.Data
|
|||
}
|
||||
if (string.Equals(name, ItemSortBy.SeriesSortName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return new Tuple<string, bool>("(Select SortName from TypedBaseItems where B.Guid=A.SeriesId)", false);
|
||||
return new Tuple<string, bool>("SeriesName", false);
|
||||
}
|
||||
|
||||
return new Tuple<string, bool>(name, false);
|
||||
|
|
|
@ -15,18 +15,11 @@ namespace MediaBrowser.Controller.Drawing
|
|||
/// </summary>
|
||||
/// <value>The supported output formats.</value>
|
||||
ImageFormat[] SupportedOutputFormats { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Encodes the image.
|
||||
/// </summary>
|
||||
/// <param name="inputPath">The input path.</param>
|
||||
/// <param name="outputPath">The output path.</param>
|
||||
/// <param name="autoOrient">if set to <c>true</c> [automatic orient].</param>
|
||||
/// <param name="width">The width.</param>
|
||||
/// <param name="height">The height.</param>
|
||||
/// <param name="quality">The quality.</param>
|
||||
/// <param name="options">The options.</param>
|
||||
/// <param name="outputFormat">The output format.</param>
|
||||
void EncodeImage(string inputPath, string outputPath, bool autoOrient, int width, int height, int quality, ImageProcessingOptions options, ImageFormat outputFormat);
|
||||
void EncodeImage(string inputPath, ImageSize? originalImageSize, string outputPath, bool autoOrient, int quality, ImageProcessingOptions options, ImageFormat outputFormat);
|
||||
|
||||
/// <summary>
|
||||
/// Creates the image collage.
|
||||
|
|
69
MediaBrowser.Controller/Drawing/ImageHelper.cs
Normal file
69
MediaBrowser.Controller/Drawing/ImageHelper.cs
Normal file
|
@ -0,0 +1,69 @@
|
|||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Model.Drawing;
|
||||
using MediaBrowser.Model.Entities;
|
||||
|
||||
namespace MediaBrowser.Controller.Drawing
|
||||
{
|
||||
public static class ImageHelper
|
||||
{
|
||||
public static ImageSize GetNewImageSize(ImageProcessingOptions options, ImageSize? originalImageSize)
|
||||
{
|
||||
if (originalImageSize.HasValue)
|
||||
{
|
||||
// Determine the output size based on incoming parameters
|
||||
var newSize = DrawingUtils.Resize(originalImageSize.Value, options.Width, options.Height, options.MaxWidth, options.MaxHeight);
|
||||
|
||||
return newSize;
|
||||
}
|
||||
return GetSizeEstimate(options);
|
||||
}
|
||||
|
||||
private static ImageSize GetSizeEstimate(ImageProcessingOptions options)
|
||||
{
|
||||
if (options.Width.HasValue && options.Height.HasValue)
|
||||
{
|
||||
return new ImageSize(options.Width.Value, options.Height.Value);
|
||||
}
|
||||
|
||||
var aspect = GetEstimatedAspectRatio(options.Image.Type, options.Item);
|
||||
|
||||
var width = options.Width ?? options.MaxWidth;
|
||||
|
||||
if (width.HasValue)
|
||||
{
|
||||
var heightValue = width.Value / aspect;
|
||||
return new ImageSize(width.Value, heightValue);
|
||||
}
|
||||
|
||||
var height = options.Height ?? options.MaxHeight ?? 200;
|
||||
var widthValue = aspect * height;
|
||||
return new ImageSize(widthValue, height);
|
||||
}
|
||||
|
||||
private static double GetEstimatedAspectRatio(ImageType type, IHasImages item)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case ImageType.Art:
|
||||
case ImageType.Backdrop:
|
||||
case ImageType.Chapter:
|
||||
case ImageType.Screenshot:
|
||||
case ImageType.Thumb:
|
||||
return 1.78;
|
||||
case ImageType.Banner:
|
||||
return 5.4;
|
||||
case ImageType.Box:
|
||||
case ImageType.BoxRear:
|
||||
case ImageType.Disc:
|
||||
case ImageType.Menu:
|
||||
return 1;
|
||||
case ImageType.Logo:
|
||||
return 2.58;
|
||||
case ImageType.Primary:
|
||||
return item.GetDefaultPrimaryImageAspectRatio() ?? .667;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -251,7 +251,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
|
||||
if (policy.MaxParentalRating.HasValue)
|
||||
{
|
||||
BlockUnratedItems = policy.BlockUnratedItems;
|
||||
BlockUnratedItems = policy.BlockUnratedItems.Where(i => i != UnratedItem.Other).ToArray();
|
||||
}
|
||||
|
||||
ExcludeInheritedTags = policy.BlockedTags;
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
using MediaBrowser.Model.Configuration;
|
||||
using MediaBrowser.Model.Users;
|
||||
using System.Linq;
|
||||
using MediaBrowser.Model.Serialization;
|
||||
using MediaBrowser.Model.Serialization;
|
||||
|
||||
namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
|
@ -24,10 +21,5 @@ namespace MediaBrowser.Controller.Entities
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool GetBlockUnratedValue(UserPolicy config)
|
||||
{
|
||||
return config.BlockUnratedItems.Contains(UnratedItem.Other);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -91,6 +91,7 @@
|
|||
<Compile Include="Drawing\IImageEncoder.cs" />
|
||||
<Compile Include="Drawing\IImageProcessor.cs" />
|
||||
<Compile Include="Drawing\ImageCollageOptions.cs" />
|
||||
<Compile Include="Drawing\ImageHelper.cs" />
|
||||
<Compile Include="Drawing\ImageProcessingOptions.cs" />
|
||||
<Compile Include="Drawing\ImageProcessorExtensions.cs" />
|
||||
<Compile Include="Drawing\ImageStream.cs" />
|
||||
|
|
|
@ -775,8 +775,6 @@ namespace MediaBrowser.ServerApplication
|
|||
return;
|
||||
}
|
||||
|
||||
MessageBox.Show("The Visual C++ 2013 Runtime will now be installed.", "Install Visual C++ Runtime", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
|
||||
try
|
||||
{
|
||||
await InstallVcredist(GetVcredist2013Url()).ConfigureAwait(false);
|
||||
|
@ -829,8 +827,6 @@ namespace MediaBrowser.ServerApplication
|
|||
return;
|
||||
}
|
||||
|
||||
MessageBox.Show("The Visual C++ 2015 Runtime will now be installed.", "Install Visual C++ Runtime", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
|
||||
try
|
||||
{
|
||||
await InstallVcredist(GetVcredist2015Url()).ConfigureAwait(false);
|
||||
|
|
Loading…
Reference in a new issue