|
|
|
@ -1,7 +1,11 @@
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Diagnostics.CodeAnalysis;
|
|
|
|
|
using System.Globalization;
|
|
|
|
|
using System.IO;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using Blurhash.Core;
|
|
|
|
|
using MediaBrowser.Common.Configuration;
|
|
|
|
|
using MediaBrowser.Controller.Drawing;
|
|
|
|
|
using MediaBrowser.Controller.Extensions;
|
|
|
|
@ -15,7 +19,7 @@ namespace Jellyfin.Drawing.Skia
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Image encoder that uses <see cref="SkiaSharp"/> to manipulate images.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public class SkiaEncoder : IImageEncoder
|
|
|
|
|
public class SkiaEncoder : CoreEncoder, IImageEncoder
|
|
|
|
|
{
|
|
|
|
|
private static readonly HashSet<string> _transparentImageTypes
|
|
|
|
|
= new HashSet<string>(StringComparer.OrdinalIgnoreCase) { ".png", ".gif", ".webp" };
|
|
|
|
@ -229,6 +233,48 @@ namespace Jellyfin.Drawing.Skia
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <inheritdoc />
|
|
|
|
|
/// <exception cref="ArgumentNullException">The path is null.</exception>
|
|
|
|
|
/// <exception cref="FileNotFoundException">The path is not valid.</exception>
|
|
|
|
|
/// <exception cref="SkiaCodecException">The file at the specified path could not be used to generate a codec.</exception>
|
|
|
|
|
[SuppressMessage("Microsoft.Performance", "CA1814:PreferJaggedArraysOverMultidimensional")]
|
|
|
|
|
public string GetImageHash(string path)
|
|
|
|
|
{
|
|
|
|
|
if (path == null)
|
|
|
|
|
{
|
|
|
|
|
throw new ArgumentNullException(nameof(path));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!File.Exists(path))
|
|
|
|
|
{
|
|
|
|
|
throw new FileNotFoundException("File not found", path);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
using (var bitmap = GetBitmap(path, false, false, null))
|
|
|
|
|
{
|
|
|
|
|
if (bitmap == null)
|
|
|
|
|
{
|
|
|
|
|
throw new ArgumentOutOfRangeException($"Skia unable to read image {path}");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var width = bitmap.Width;
|
|
|
|
|
var height = bitmap.Height;
|
|
|
|
|
var pixels = new Pixel[width, height];
|
|
|
|
|
Parallel.ForEach(Enumerable.Range(0, height), y =>
|
|
|
|
|
{
|
|
|
|
|
for (var x = 0; x < width; x++)
|
|
|
|
|
{
|
|
|
|
|
var color = bitmap.GetPixel(x, y);
|
|
|
|
|
pixels[x, y].Red = MathUtils.SRgbToLinear(color.Red);
|
|
|
|
|
pixels[x, y].Green = MathUtils.SRgbToLinear(color.Green);
|
|
|
|
|
pixels[x, y].Blue = MathUtils.SRgbToLinear(color.Blue);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return CoreEncode(pixels, 4, 4);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static bool HasDiacritics(string text)
|
|
|
|
|
=> !string.Equals(text, text.RemoveDiacritics(), StringComparison.Ordinal);
|
|
|
|
|
|
|
|
|
|