update image encoding
This commit is contained in:
parent
1be515ddf7
commit
9cd2d793be
|
@ -130,7 +130,7 @@ namespace Emby.Drawing.ImageMagick
|
|||
string.Equals(ext, ".webp", StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
public void EncodeImage(string inputPath, ImageSize? originalImageSize, string outputPath, bool autoOrient, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat)
|
||||
public string EncodeImage(string inputPath, DateTime dateModified, 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,9 +144,13 @@ namespace Emby.Drawing.ImageMagick
|
|||
originalImage.CurrentImage.TrimImage(10);
|
||||
}
|
||||
|
||||
if (options.CropWhiteSpace || !originalImageSize.HasValue)
|
||||
var originalImageSize = new ImageSize(originalImage.CurrentImage.Width, originalImage.CurrentImage.Height);
|
||||
ImageHelper.SaveImageSize(inputPath, dateModified, originalImageSize);
|
||||
|
||||
if (!options.CropWhiteSpace && options.HasDefaultOptions(inputPath, originalImageSize))
|
||||
{
|
||||
originalImageSize = new ImageSize(originalImage.CurrentImage.Width, originalImage.CurrentImage.Height);
|
||||
// Just spit out the original file if all the options are default
|
||||
return inputPath;
|
||||
}
|
||||
|
||||
var newImageSize = ImageHelper.GetNewImageSize(options, originalImageSize);
|
||||
|
@ -174,10 +178,8 @@ namespace Emby.Drawing.ImageMagick
|
|||
{
|
||||
using (var originalImage = new MagickWand(inputPath))
|
||||
{
|
||||
if (options.CropWhiteSpace || !originalImageSize.HasValue)
|
||||
{
|
||||
originalImageSize = new ImageSize(originalImage.CurrentImage.Width, originalImage.CurrentImage.Height);
|
||||
}
|
||||
var originalImageSize = new ImageSize(originalImage.CurrentImage.Width, originalImage.CurrentImage.Height);
|
||||
ImageHelper.SaveImageSize(inputPath, dateModified, originalImageSize);
|
||||
|
||||
var newImageSize = ImageHelper.GetNewImageSize(options, originalImageSize);
|
||||
|
||||
|
@ -205,6 +207,8 @@ namespace Emby.Drawing.ImageMagick
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return outputPath;
|
||||
}
|
||||
|
||||
private void AddForegroundLayer(MagickWand wand, ImageProcessingOptions options)
|
||||
|
|
|
@ -191,18 +191,18 @@ namespace Emby.Drawing.Skia
|
|||
}
|
||||
|
||||
private string[] TransparentImageTypes = new string[] { ".png", ".gif", ".webp" };
|
||||
private SKBitmap Decode(string path)
|
||||
private SKBitmap Decode(string path, bool forceCleanBitmap = false)
|
||||
{
|
||||
var requiresTransparencyHack = TransparentImageTypes.Contains(Path.GetExtension(path) ?? string.Empty);
|
||||
|
||||
if (requiresTransparencyHack)
|
||||
if (requiresTransparencyHack || forceCleanBitmap)
|
||||
{
|
||||
using (var stream = new SKFileStream(path))
|
||||
{
|
||||
var codec = SKCodec.Create(stream);
|
||||
|
||||
// create the bitmap
|
||||
var bitmap = new SKBitmap(codec.Info.Width, codec.Info.Height);
|
||||
var bitmap = new SKBitmap(codec.Info.Width, codec.Info.Height, !requiresTransparencyHack);
|
||||
// decode
|
||||
codec.GetPixels(bitmap.Info, bitmap.GetPixels());
|
||||
|
||||
|
@ -210,7 +210,18 @@ namespace Emby.Drawing.Skia
|
|||
}
|
||||
}
|
||||
|
||||
return SKBitmap.Decode(path);
|
||||
var resultBitmap = SKBitmap.Decode(path);
|
||||
|
||||
// If we have to resize these they often end up distorted
|
||||
if (resultBitmap.ColorType == SKColorType.Gray8)
|
||||
{
|
||||
using (resultBitmap)
|
||||
{
|
||||
return Decode(path, true);
|
||||
}
|
||||
}
|
||||
|
||||
return resultBitmap;
|
||||
}
|
||||
|
||||
private SKBitmap GetBitmap(string path, bool cropWhitespace)
|
||||
|
@ -226,7 +237,7 @@ namespace Emby.Drawing.Skia
|
|||
return Decode(path);
|
||||
}
|
||||
|
||||
public void EncodeImage(string inputPath, ImageSize? originalImageSize, string outputPath, bool autoOrient, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat)
|
||||
public string EncodeImage(string inputPath, DateTime dateModified, string outputPath, bool autoOrient, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(inputPath))
|
||||
{
|
||||
|
@ -246,9 +257,20 @@ namespace Emby.Drawing.Skia
|
|||
|
||||
using (var bitmap = GetBitmap(inputPath, options.CropWhiteSpace))
|
||||
{
|
||||
if (options.CropWhiteSpace || !originalImageSize.HasValue)
|
||||
if (bitmap == null)
|
||||
{
|
||||
originalImageSize = new ImageSize(bitmap.Width, bitmap.Height);
|
||||
throw new Exception(string.Format("Skia unable to read image {0}", inputPath));
|
||||
}
|
||||
|
||||
//_logger.Info("Color type {0}", bitmap.Info.ColorType);
|
||||
|
||||
var originalImageSize = new ImageSize(bitmap.Width, bitmap.Height);
|
||||
ImageHelper.SaveImageSize(inputPath, dateModified, originalImageSize);
|
||||
|
||||
if (!options.CropWhiteSpace && options.HasDefaultOptions(inputPath, originalImageSize))
|
||||
{
|
||||
// Just spit out the original file if all the options are default
|
||||
return inputPath;
|
||||
}
|
||||
|
||||
var newImageSize = ImageHelper.GetNewImageSize(options, originalImageSize);
|
||||
|
@ -269,7 +291,7 @@ namespace Emby.Drawing.Skia
|
|||
using (var outputStream = new SKFileWStream(outputPath))
|
||||
{
|
||||
resizedBitmap.Encode(outputStream, skiaOutputFormat, quality);
|
||||
return;
|
||||
return outputPath;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -326,6 +348,7 @@ namespace Emby.Drawing.Skia
|
|||
}
|
||||
}
|
||||
}
|
||||
return outputPath;
|
||||
}
|
||||
|
||||
public void CreateImageCollage(ImageCollageOptions options)
|
||||
|
|
|
@ -75,6 +75,7 @@ namespace Emby.Drawing
|
|||
|
||||
ImageEnhancers = new List<IImageEnhancer>();
|
||||
_saveImageSizeTimer = timerFactory.Create(SaveImageSizeCallback, null, Timeout.Infinite, Timeout.Infinite);
|
||||
ImageHelper.ImageProcessor = this;
|
||||
|
||||
Dictionary<Guid, ImageSize> sizeDictionary;
|
||||
|
||||
|
@ -212,19 +213,12 @@ namespace Emby.Drawing
|
|||
return new Tuple<string, string, DateTime>(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified);
|
||||
}
|
||||
|
||||
ImageSize? originalImageSize = null;
|
||||
try
|
||||
ImageSize? originalImageSize = GetSavedImageSize(originalImagePath, dateModified);
|
||||
if (originalImageSize.HasValue && options.HasDefaultOptions(originalImagePath, originalImageSize.Value))
|
||||
{
|
||||
originalImageSize = GetImageSize(originalImagePath, dateModified, true);
|
||||
if (options.HasDefaultOptions(originalImagePath, originalImageSize.Value))
|
||||
{
|
||||
// Just spit out the original file if all the options are default
|
||||
return new Tuple<string, string, DateTime>(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
originalImageSize = null;
|
||||
// Just spit out the original file if all the options are default
|
||||
_logger.Info("Returning original image {0}", originalImagePath);
|
||||
return new Tuple<string, string, DateTime>(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified);
|
||||
}
|
||||
|
||||
var newSize = ImageHelper.GetNewImageSize(options, originalImageSize);
|
||||
|
@ -243,7 +237,13 @@ namespace Emby.Drawing
|
|||
var tmpPath = Path.ChangeExtension(Path.Combine(_appPaths.TempDirectory, Guid.NewGuid().ToString("N")), Path.GetExtension(cacheFilePath));
|
||||
_fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(tmpPath));
|
||||
|
||||
_imageEncoder.EncodeImage(originalImagePath, originalImageSize, tmpPath, AutoOrient(options.Item), quality, options, outputFormat);
|
||||
var resultPath =_imageEncoder.EncodeImage(originalImagePath, dateModified, tmpPath, AutoOrient(options.Item), quality, options, outputFormat);
|
||||
|
||||
if (string.Equals(resultPath, originalImagePath, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return new Tuple<string, string, DateTime>(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified);
|
||||
}
|
||||
|
||||
CopyFile(tmpPath, cacheFilePath);
|
||||
|
||||
return new Tuple<string, string, DateTime>(tmpPath, GetMimeType(outputFormat, cacheFilePath), _fileSystem.GetLastWriteTimeUtc(tmpPath));
|
||||
|
@ -422,26 +422,72 @@ namespace Emby.Drawing
|
|||
throw new ArgumentNullException("path");
|
||||
}
|
||||
|
||||
var name = path + "datemodified=" + imageDateModified.Ticks;
|
||||
|
||||
ImageSize size;
|
||||
|
||||
var cacheHash = name.GetMD5();
|
||||
var cacheHash = GetImageSizeKey(path, imageDateModified);
|
||||
|
||||
if (!_cachedImagedSizes.TryGetValue(cacheHash, out size))
|
||||
{
|
||||
size = GetImageSizeInternal(path, allowSlowMethod);
|
||||
|
||||
if (size.Width > 0 && size.Height > 0)
|
||||
{
|
||||
StartSaveImageSizeTimer();
|
||||
_cachedImagedSizes.AddOrUpdate(cacheHash, size, (keyName, oldValue) => size);
|
||||
}
|
||||
SaveImageSize(size, cacheHash, false);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
public void SaveImageSize(string path, DateTime imageDateModified, ImageSize size)
|
||||
{
|
||||
var cacheHash = GetImageSizeKey(path, imageDateModified);
|
||||
SaveImageSize(size, cacheHash, true);
|
||||
}
|
||||
|
||||
private void SaveImageSize(ImageSize size, Guid cacheHash, bool checkExists)
|
||||
{
|
||||
if (size.Width <= 0 || size.Height <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (checkExists && _cachedImagedSizes.ContainsKey(cacheHash))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (checkExists)
|
||||
{
|
||||
if (_cachedImagedSizes.TryAdd(cacheHash, size))
|
||||
{
|
||||
StartSaveImageSizeTimer();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
StartSaveImageSizeTimer();
|
||||
_cachedImagedSizes.AddOrUpdate(cacheHash, size, (keyName, oldValue) => size);
|
||||
}
|
||||
}
|
||||
|
||||
private Guid GetImageSizeKey(string path, DateTime imageDateModified)
|
||||
{
|
||||
var name = path + "datemodified=" + imageDateModified.Ticks;
|
||||
return name.GetMD5();
|
||||
}
|
||||
|
||||
public ImageSize? GetSavedImageSize(string path, DateTime imageDateModified)
|
||||
{
|
||||
ImageSize size;
|
||||
|
||||
var cacheHash = GetImageSizeKey(path, imageDateModified);
|
||||
|
||||
if (_cachedImagedSizes.TryGetValue(cacheHash, out size))
|
||||
{
|
||||
return size;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the image size internal.
|
||||
/// </summary>
|
||||
|
|
|
@ -32,7 +32,7 @@ namespace Emby.Drawing
|
|||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void EncodeImage(string inputPath, ImageSize? originalImageSize, string outputPath, bool autoOrient, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat)
|
||||
public string EncodeImage(string inputPath, DateTime dateModified, string outputPath, bool autoOrient, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
|
|
@ -167,10 +167,12 @@ namespace Emby.Server.Implementations.LiveTv.Listings
|
|||
{
|
||||
var programEntry = programDict[schedule.programID];
|
||||
|
||||
var data = images[imageIndex].data ?? new List<ScheduleDirect.ImageData>();
|
||||
data = data.OrderByDescending(GetSizeOrder).ToList();
|
||||
var allImages = (images[imageIndex].data ?? new List<ScheduleDirect.ImageData>()).OrderByDescending(GetSizeOrder).ToList();
|
||||
var imagesWithText = allImages.Where(i => string.Equals(i.text, "yes", StringComparison.OrdinalIgnoreCase)).ToList();
|
||||
|
||||
programEntry.primaryImage = GetProgramImage(ApiUrl, imagesWithText, "Logo", true, 600) ??
|
||||
GetProgramImage(ApiUrl, allImages, "Logo", true, 600);
|
||||
|
||||
programEntry.primaryImage = GetProgramImage(ApiUrl, data, "Logo", true, 600);
|
||||
//programEntry.thumbImage = GetProgramImage(ApiUrl, data, "Iconic", false);
|
||||
//programEntry.bannerImage = GetProgramImage(ApiUrl, data, "Banner", false) ??
|
||||
// GetProgramImage(ApiUrl, data, "Banner-L1", false) ??
|
||||
|
|
|
@ -19,7 +19,7 @@ namespace MediaBrowser.Controller.Drawing
|
|||
/// <summary>
|
||||
/// Encodes the image.
|
||||
/// </summary>
|
||||
void EncodeImage(string inputPath, ImageSize? originalImageSize, string outputPath, bool autoOrient, int quality, ImageProcessingOptions options, ImageFormat outputFormat);
|
||||
string EncodeImage(string inputPath, DateTime dateModified, string outputPath, bool autoOrient, int quality, ImageProcessingOptions options, ImageFormat outputFormat);
|
||||
|
||||
/// <summary>
|
||||
/// Creates the image collage.
|
||||
|
|
|
@ -114,5 +114,7 @@ namespace MediaBrowser.Controller.Drawing
|
|||
bool SupportsImageCollageCreation { get; }
|
||||
|
||||
IImageEncoder ImageEncoder { get; set; }
|
||||
|
||||
void SaveImageSize(string path, DateTime imageDateModified, ImageSize size);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using MediaBrowser.Controller.Entities;
|
||||
using System;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Model.Drawing;
|
||||
using MediaBrowser.Model.Entities;
|
||||
|
||||
|
@ -18,6 +19,13 @@ namespace MediaBrowser.Controller.Drawing
|
|||
return GetSizeEstimate(options);
|
||||
}
|
||||
|
||||
public static IImageProcessor ImageProcessor { get; set; }
|
||||
|
||||
public static void SaveImageSize(string path, DateTime dateModified, ImageSize size)
|
||||
{
|
||||
ImageProcessor.SaveImageSize(path, dateModified, size);
|
||||
}
|
||||
|
||||
private static ImageSize GetSizeEstimate(ImageProcessingOptions options)
|
||||
{
|
||||
if (options.Width.HasValue && options.Height.HasValue)
|
||||
|
|
|
@ -968,7 +968,7 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||
{
|
||||
if (bitrate.HasValue && videoStream.BitRate.HasValue)
|
||||
{
|
||||
bitrate = Math.Min(bitrate.Value, videoStream.BitRate.Value);
|
||||
bitrate = GetMinBitrate(bitrate.Value, videoStream.BitRate.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -981,13 +981,25 @@ namespace MediaBrowser.Controller.MediaEncoding
|
|||
// If a max bitrate was requested, don't let the scaled bitrate exceed it
|
||||
if (request.VideoBitRate.HasValue)
|
||||
{
|
||||
bitrate = Math.Min(bitrate.Value, request.VideoBitRate.Value);
|
||||
bitrate = GetMinBitrate(bitrate.Value, request.VideoBitRate.Value);
|
||||
}
|
||||
}
|
||||
|
||||
return bitrate;
|
||||
}
|
||||
|
||||
private int GetMinBitrate(int sourceBitrate, int requestedBitrate)
|
||||
{
|
||||
if (sourceBitrate <= 2000000)
|
||||
{
|
||||
sourceBitrate *= 2;
|
||||
}
|
||||
|
||||
var bitrate = Math.Min(sourceBitrate, requestedBitrate);
|
||||
|
||||
return bitrate;
|
||||
}
|
||||
|
||||
public int? GetAudioBitrateParam(BaseEncodingJobOptions request, MediaStream audioStream)
|
||||
{
|
||||
if (request.AudioBitRate.HasValue)
|
||||
|
|
Loading…
Reference in New Issue
Block a user