mirror of
https://github.com/jellyfin/jellyfin.git
synced 2024-09-07 11:57:55 +02:00
commit
e06563831e
6 changed files with 81 additions and 34 deletions
|
@ -6,6 +6,8 @@ using MediaBrowser.Model.IO;
|
||||||
using MediaBrowser.Model.Logging;
|
using MediaBrowser.Model.Logging;
|
||||||
using SkiaSharp;
|
using SkiaSharp;
|
||||||
using System;
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
@ -120,8 +122,6 @@ namespace Emby.Drawing.Skia
|
||||||
|
|
||||||
private SKBitmap CropWhiteSpace(SKBitmap bitmap)
|
private SKBitmap CropWhiteSpace(SKBitmap bitmap)
|
||||||
{
|
{
|
||||||
CheckDisposed();
|
|
||||||
|
|
||||||
var topmost = 0;
|
var topmost = 0;
|
||||||
for (int row = 0; row < bitmap.Height; ++row)
|
for (int row = 0; row < bitmap.Height; ++row)
|
||||||
{
|
{
|
||||||
|
@ -175,8 +175,6 @@ namespace Emby.Drawing.Skia
|
||||||
|
|
||||||
public ImageSize GetImageSize(string path)
|
public ImageSize GetImageSize(string path)
|
||||||
{
|
{
|
||||||
CheckDisposed();
|
|
||||||
|
|
||||||
using (var s = new SKFileStream(path))
|
using (var s = new SKFileStream(path))
|
||||||
{
|
{
|
||||||
using (var codec = SKCodec.Create(s))
|
using (var codec = SKCodec.Create(s))
|
||||||
|
@ -192,17 +190,40 @@ namespace Emby.Drawing.Skia
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string[] TransparentImageTypes = new string[] { ".png", ".gif", ".webp" };
|
||||||
|
private SKBitmap Decode(string path)
|
||||||
|
{
|
||||||
|
var requiresTransparencyHack = TransparentImageTypes.Contains(Path.GetExtension(path) ?? string.Empty);
|
||||||
|
|
||||||
|
if (requiresTransparencyHack)
|
||||||
|
{
|
||||||
|
using (var stream = new SKFileStream(path))
|
||||||
|
{
|
||||||
|
var codec = SKCodec.Create(stream);
|
||||||
|
|
||||||
|
// create the bitmap
|
||||||
|
var bitmap = new SKBitmap(codec.Info.Width, codec.Info.Height);
|
||||||
|
// decode
|
||||||
|
codec.GetPixels(bitmap.Info, bitmap.GetPixels());
|
||||||
|
|
||||||
|
return bitmap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return SKBitmap.Decode(path);
|
||||||
|
}
|
||||||
|
|
||||||
private SKBitmap GetBitmap(string path, bool cropWhitespace)
|
private SKBitmap GetBitmap(string path, bool cropWhitespace)
|
||||||
{
|
{
|
||||||
if (cropWhitespace)
|
if (cropWhitespace)
|
||||||
{
|
{
|
||||||
using (var bitmap = SKBitmap.Decode(path))
|
using (var bitmap = Decode(path))
|
||||||
{
|
{
|
||||||
return CropWhiteSpace(bitmap);
|
return CropWhiteSpace(bitmap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return SKBitmap.Decode(path);
|
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, string outputPath, bool autoOrient, int width, int height, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat)
|
||||||
|
@ -221,17 +242,14 @@ namespace Emby.Drawing.Skia
|
||||||
var hasBackgroundColor = !string.IsNullOrWhiteSpace(options.BackgroundColor);
|
var hasBackgroundColor = !string.IsNullOrWhiteSpace(options.BackgroundColor);
|
||||||
var hasForegroundColor = !string.IsNullOrWhiteSpace(options.ForegroundLayer);
|
var hasForegroundColor = !string.IsNullOrWhiteSpace(options.ForegroundLayer);
|
||||||
var blur = options.Blur ?? 0;
|
var blur = options.Blur ?? 0;
|
||||||
var hasIndicator = !options.AddPlayedIndicator && !options.UnplayedCount.HasValue && options.PercentPlayed.Equals(0);
|
var hasIndicator = options.AddPlayedIndicator || options.UnplayedCount.HasValue || !options.PercentPlayed.Equals(0);
|
||||||
|
|
||||||
using (var bitmap = GetBitmap(inputPath, options.CropWhiteSpace))
|
using (var bitmap = GetBitmap(inputPath, options.CropWhiteSpace))
|
||||||
{
|
{
|
||||||
using (var resizedBitmap = new SKBitmap(width, height, bitmap.ColorType, bitmap.AlphaType))
|
using (var resizedBitmap = new SKBitmap(width, height))//, bitmap.ColorType, bitmap.AlphaType))
|
||||||
{
|
{
|
||||||
// scale image
|
// scale image
|
||||||
var resizeMethod = options.Image.Type == MediaBrowser.Model.Entities.ImageType.Logo ||
|
var resizeMethod = SKBitmapResizeMethod.Lanczos3;
|
||||||
options.Image.Type == MediaBrowser.Model.Entities.ImageType.Art
|
|
||||||
? SKBitmapResizeMethod.Lanczos3
|
|
||||||
: SKBitmapResizeMethod.Lanczos3;
|
|
||||||
|
|
||||||
bitmap.Resize(resizedBitmap, resizeMethod);
|
bitmap.Resize(resizedBitmap, resizeMethod);
|
||||||
|
|
||||||
|
@ -246,7 +264,7 @@ namespace Emby.Drawing.Skia
|
||||||
}
|
}
|
||||||
|
|
||||||
// create bitmap to use for canvas drawing
|
// create bitmap to use for canvas drawing
|
||||||
using (var saveBitmap = new SKBitmap(width, height, bitmap.ColorType, bitmap.AlphaType))
|
using (var saveBitmap = new SKBitmap(width, height))//, bitmap.ColorType, bitmap.AlphaType))
|
||||||
{
|
{
|
||||||
// create canvas used to draw into bitmap
|
// create canvas used to draw into bitmap
|
||||||
using (var canvas = new SKCanvas(saveBitmap))
|
using (var canvas = new SKCanvas(saveBitmap))
|
||||||
|
@ -263,7 +281,7 @@ namespace Emby.Drawing.Skia
|
||||||
using (var paint = new SKPaint())
|
using (var paint = new SKPaint())
|
||||||
{
|
{
|
||||||
// create image from resized bitmap to apply blur
|
// create image from resized bitmap to apply blur
|
||||||
using (var filter = SKImageFilter.CreateBlur(5, 5))
|
using (var filter = SKImageFilter.CreateBlur(blur, blur))
|
||||||
{
|
{
|
||||||
paint.ImageFilter = filter;
|
paint.ImageFilter = filter;
|
||||||
canvas.DrawBitmap(resizedBitmap, SKRect.Create(width, height), paint);
|
canvas.DrawBitmap(resizedBitmap, SKRect.Create(width, height), paint);
|
||||||
|
@ -282,8 +300,7 @@ namespace Emby.Drawing.Skia
|
||||||
Double opacity;
|
Double opacity;
|
||||||
if (!Double.TryParse(options.ForegroundLayer, out opacity)) opacity = .4;
|
if (!Double.TryParse(options.ForegroundLayer, out opacity)) opacity = .4;
|
||||||
|
|
||||||
var foregroundColor = String.Format("#{0:X2}000000", (Byte)((1 - opacity) * 0xFF));
|
canvas.DrawColor(new SKColor(0, 0, 0, (Byte)((1 - opacity) * 0xFF)), SKBlendMode.SrcOver);
|
||||||
canvas.DrawColor(SKColor.Parse(foregroundColor), SKBlendMode.SrcOver);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasIndicator)
|
if (hasIndicator)
|
||||||
|
@ -353,18 +370,8 @@ namespace Emby.Drawing.Skia
|
||||||
get { return "Skia"; }
|
get { return "Skia"; }
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool _disposed;
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
_disposed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CheckDisposed()
|
|
||||||
{
|
|
||||||
if (_disposed)
|
|
||||||
{
|
|
||||||
throw new ObjectDisposedException(GetType().Name);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool SupportsImageCollageCreation
|
public bool SupportsImageCollageCreation
|
||||||
|
|
|
@ -225,8 +225,8 @@ namespace Emby.Drawing
|
||||||
|
|
||||||
if (!_fileSystem.FileExists(cacheFilePath))
|
if (!_fileSystem.FileExists(cacheFilePath))
|
||||||
{
|
{
|
||||||
var newWidth = Convert.ToInt32(newSize.Width);
|
var newWidth = Convert.ToInt32(Math.Round(newSize.Width));
|
||||||
var newHeight = Convert.ToInt32(newSize.Height);
|
var newHeight = Convert.ToInt32(Math.Round(newSize.Height));
|
||||||
|
|
||||||
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(cacheFilePath));
|
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(cacheFilePath));
|
||||||
var tmpPath = Path.ChangeExtension(Path.Combine(_appPaths.TempDirectory, Guid.NewGuid().ToString("N")), Path.GetExtension(cacheFilePath));
|
var tmpPath = Path.ChangeExtension(Path.Combine(_appPaths.TempDirectory, Guid.NewGuid().ToString("N")), Path.GetExtension(cacheFilePath));
|
||||||
|
@ -339,13 +339,13 @@ namespace Emby.Drawing
|
||||||
|
|
||||||
if (width.HasValue)
|
if (width.HasValue)
|
||||||
{
|
{
|
||||||
var heightValue = aspect / width.Value;
|
var heightValue = width.Value / aspect;
|
||||||
return new ImageSize(width.Value, Convert.ToInt32(heightValue));
|
return new ImageSize(width.Value, heightValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
var height = options.Height ?? options.MaxHeight ?? 200;
|
var height = options.Height ?? options.MaxHeight ?? 200;
|
||||||
var widthValue = aspect * height;
|
var widthValue = aspect * height;
|
||||||
return new ImageSize(Convert.ToInt32(widthValue), height);
|
return new ImageSize(widthValue, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
private double GetEstimatedAspectRatio(ImageType type)
|
private double GetEstimatedAspectRatio(ImageType type)
|
||||||
|
|
|
@ -176,6 +176,14 @@ namespace MediaBrowser.MediaEncoding.Probing
|
||||||
info.Video3DFormat = Video3DFormat.FullSideBySide;
|
info.Video3DFormat = Video3DFormat.FullSideBySide;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach (var mediaStream in info.MediaStreams)
|
||||||
|
{
|
||||||
|
if (mediaStream.Type == MediaStreamType.Audio && !mediaStream.BitRate.HasValue)
|
||||||
|
{
|
||||||
|
mediaStream.BitRate = GetEstimatedAudioBitrate(mediaStream.Codec, mediaStream.Channels);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var videoStreamsBitrate = info.MediaStreams.Where(i => i.Type == MediaStreamType.Video).Select(i => i.BitRate ?? 0).Sum();
|
var videoStreamsBitrate = info.MediaStreams.Where(i => i.Type == MediaStreamType.Video).Select(i => i.BitRate ?? 0).Sum();
|
||||||
// If ffprobe reported the container bitrate as being the same as the video stream bitrate, then it's wrong
|
// If ffprobe reported the container bitrate as being the same as the video stream bitrate, then it's wrong
|
||||||
if (videoStreamsBitrate == (info.Bitrate ?? 0))
|
if (videoStreamsBitrate == (info.Bitrate ?? 0))
|
||||||
|
@ -187,6 +195,32 @@ namespace MediaBrowser.MediaEncoding.Probing
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int? GetEstimatedAudioBitrate(string codec, int? channels)
|
||||||
|
{
|
||||||
|
if (!channels.HasValue)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var channelsValue = channels.Value;
|
||||||
|
|
||||||
|
if (string.Equals(codec, "aac", StringComparison.OrdinalIgnoreCase) ||
|
||||||
|
string.Equals(codec, "mp3", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
if (channelsValue <= 2)
|
||||||
|
{
|
||||||
|
return 192000;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (channelsValue >= 5)
|
||||||
|
{
|
||||||
|
return 320000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private void FetchFromItunesInfo(string xml, MediaInfo info)
|
private void FetchFromItunesInfo(string xml, MediaInfo info)
|
||||||
{
|
{
|
||||||
// Make things simpler and strip out the dtd
|
// Make things simpler and strip out the dtd
|
||||||
|
|
|
@ -61,6 +61,12 @@ namespace MediaBrowser.Model.Drawing
|
||||||
_height = height;
|
_height = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ImageSize(double width, double height)
|
||||||
|
{
|
||||||
|
_width = width;
|
||||||
|
_height = height;
|
||||||
|
}
|
||||||
|
|
||||||
private void ParseValue(string value)
|
private void ParseValue(string value)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(value))
|
if (!string.IsNullOrEmpty(value))
|
||||||
|
|
|
@ -26,7 +26,7 @@ namespace MediaBrowser.Server.Startup.Common
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
//return new SkiaEncoder(logManager.GetLogger("ImageMagick"), appPaths, httpClient, fileSystem);
|
return new SkiaEncoder(logManager.GetLogger("ImageMagick"), appPaths, httpClient, fileSystem);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
[assembly: AssemblyVersion("3.2.15.3")]
|
[assembly: AssemblyVersion("3.2.15.4")]
|
||||||
|
|
Loading…
Reference in a new issue