diff --git a/Emby.Drawing.Skia/SkiaEncoder.cs b/Emby.Drawing.Skia/SkiaEncoder.cs index 7469d167e1..a89e1f2db8 100644 --- a/Emby.Drawing.Skia/SkiaEncoder.cs +++ b/Emby.Drawing.Skia/SkiaEncoder.cs @@ -10,22 +10,27 @@ using System.IO; using System.Linq; using System.Reflection; using System.Threading.Tasks; +using MediaBrowser.Controller.Extensions; +using System.Globalization; +using MediaBrowser.Model.Globalization; namespace Emby.Drawing.Skia { public class SkiaEncoder : IImageEncoder { private readonly ILogger _logger; - private readonly IApplicationPaths _appPaths; + private static IApplicationPaths _appPaths; private readonly Func _httpClientFactory; private readonly IFileSystem _fileSystem; + private static ILocalizationManager _localizationManager; - public SkiaEncoder(ILogger logger, IApplicationPaths appPaths, Func httpClientFactory, IFileSystem fileSystem) + public SkiaEncoder(ILogger logger, IApplicationPaths appPaths, Func httpClientFactory, IFileSystem fileSystem, ILocalizationManager localizationManager) { _logger = logger; _appPaths = appPaths; _httpClientFactory = httpClientFactory; _fileSystem = fileSystem; + _localizationManager = localizationManager; LogVersion(); } @@ -190,14 +195,53 @@ namespace Emby.Drawing.Skia } } + private static bool HasDiacritics(string text) + { + return !String.Equals(text, text.RemoveDiacritics(), StringComparison.Ordinal); + } + + private static bool RequiresSpecialCharacterHack(string path) + { + if (_localizationManager.HasUnicodeCategory(path, UnicodeCategory.OtherLetter)) + { + return true; + } + + if (HasDiacritics(path)) + { + return true; + } + + return false; + } + + private static string NormalizePath(string path, IFileSystem fileSystem) + { + if (!RequiresSpecialCharacterHack(path)) + { + return path; + } + + var tempPath = Path.Combine(_appPaths.TempDirectory, Guid.NewGuid() + Path.GetExtension(path) ?? string.Empty); + + fileSystem.CopyFile(path, tempPath, true); + + return tempPath; + } + private static string[] TransparentImageTypes = new string[] { ".png", ".gif", ".webp" }; - internal static SKBitmap Decode(string path, bool forceCleanBitmap, out SKCodecOrigin origin) + internal static SKBitmap Decode(string path, bool forceCleanBitmap, IFileSystem fileSystem, out SKCodecOrigin origin) { + if (!fileSystem.FileExists(path)) + { + throw new FileNotFoundException("File not found", path); + } + var requiresTransparencyHack = TransparentImageTypes.Contains(Path.GetExtension(path) ?? string.Empty); if (requiresTransparencyHack || forceCleanBitmap) { - using (var stream = new SKFileStream(path)) + using (var stream = new SKFileStream(NormalizePath(path, fileSystem))) { using (var codec = SKCodec.Create(stream)) { @@ -227,11 +271,11 @@ namespace Emby.Drawing.Skia } } - var resultBitmap = SKBitmap.Decode(path); + var resultBitmap = SKBitmap.Decode(NormalizePath(path, fileSystem)); if (resultBitmap == null) { - return Decode(path, true, out origin); + return Decode(path, true, fileSystem, out origin); } // If we have to resize these they often end up distorted @@ -239,7 +283,7 @@ namespace Emby.Drawing.Skia { using (resultBitmap) { - return Decode(path, true, out origin); + return Decode(path, true, fileSystem, out origin); } } @@ -251,13 +295,13 @@ namespace Emby.Drawing.Skia { if (cropWhitespace) { - using (var bitmap = Decode(path, forceAnalyzeBitmap, out origin)) + using (var bitmap = Decode(path, forceAnalyzeBitmap, _fileSystem, out origin)) { return CropWhiteSpace(bitmap); } } - return Decode(path, forceAnalyzeBitmap, out origin); + return Decode(path, forceAnalyzeBitmap, _fileSystem, out origin); } private SKBitmap GetBitmap(string path, bool cropWhitespace, bool autoOrient) diff --git a/Emby.Drawing.Skia/StripCollageBuilder.cs b/Emby.Drawing.Skia/StripCollageBuilder.cs index 624245ee79..d562bb4be3 100644 --- a/Emby.Drawing.Skia/StripCollageBuilder.cs +++ b/Emby.Drawing.Skia/StripCollageBuilder.cs @@ -83,7 +83,7 @@ namespace Emby.Drawing.Skia for (int i = 0; i < 4; i++) { SKCodecOrigin origin; - using (var currentBitmap = SkiaEncoder.Decode(paths[imageIndex], false, out origin)) + using (var currentBitmap = SkiaEncoder.Decode(paths[imageIndex], false, _fileSystem, out origin)) { // resize to the same aspect as the original int iWidth = (int)Math.Abs(iHeight * currentBitmap.Width / currentBitmap.Height); @@ -165,7 +165,7 @@ namespace Emby.Drawing.Skia for (var y = 0; y < 2; y++) { SKCodecOrigin origin; - using (var currentBitmap = SkiaEncoder.Decode(paths[imageIndex], false, out origin)) + using (var currentBitmap = SkiaEncoder.Decode(paths[imageIndex], false, _fileSystem, out origin)) { using (var resizedBitmap = new SKBitmap(cellWidth, cellHeight, currentBitmap.ColorType, currentBitmap.AlphaType)) { diff --git a/MediaBrowser.Server.Mono/ImageEncoderHelper.cs b/MediaBrowser.Server.Mono/ImageEncoderHelper.cs index 5112c64eda..4f8451c0d1 100644 --- a/MediaBrowser.Server.Mono/ImageEncoderHelper.cs +++ b/MediaBrowser.Server.Mono/ImageEncoderHelper.cs @@ -9,6 +9,7 @@ using MediaBrowser.Model.IO; using MediaBrowser.Model.Logging; using Emby.Drawing.Skia; using MediaBrowser.Model.System; +using MediaBrowser.Model.Globalization; namespace MediaBrowser.Server.Startup.Common { @@ -20,13 +21,14 @@ namespace MediaBrowser.Server.Startup.Common StartupOptions startupOptions, Func httpClient, IApplicationPaths appPaths, - IEnvironmentInfo environment) + IEnvironmentInfo environment, + ILocalizationManager localizationManager) { if (!startupOptions.ContainsOption("-enablegdi")) { try { - return new SkiaEncoder(logManager.GetLogger("Skia"), appPaths, httpClient, fileSystem); + return new SkiaEncoder(logManager.GetLogger("Skia"), appPaths, httpClient, fileSystem, localizationManager); } catch (Exception ex) { diff --git a/MediaBrowser.Server.Mono/Program.cs b/MediaBrowser.Server.Mono/Program.cs index 3267a77b95..7a3a968ade 100644 --- a/MediaBrowser.Server.Mono/Program.cs +++ b/MediaBrowser.Server.Mono/Program.cs @@ -127,7 +127,7 @@ namespace MediaBrowser.Server.Mono Task.WaitAll(task); - appHost.ImageProcessor.ImageEncoder = ImageEncoderHelper.GetImageEncoder(_logger, logManager, fileSystem, options, () => appHost.HttpClient, appPaths, environmentInfo); + appHost.ImageProcessor.ImageEncoder = ImageEncoderHelper.GetImageEncoder(_logger, logManager, fileSystem, options, () => appHost.HttpClient, appPaths, environmentInfo, appHost.LocalizationManager); Console.WriteLine("Running startup tasks"); diff --git a/MediaBrowser.ServerApplication/ImageEncoderHelper.cs b/MediaBrowser.ServerApplication/ImageEncoderHelper.cs index c86e85785b..7c95a25ded 100644 --- a/MediaBrowser.ServerApplication/ImageEncoderHelper.cs +++ b/MediaBrowser.ServerApplication/ImageEncoderHelper.cs @@ -7,6 +7,7 @@ using MediaBrowser.Common.Net; using MediaBrowser.Controller.Drawing; using MediaBrowser.Model.IO; using MediaBrowser.Model.Logging; +using MediaBrowser.Model.Globalization; namespace MediaBrowser.Server.Startup.Common { @@ -17,11 +18,12 @@ namespace MediaBrowser.Server.Startup.Common IFileSystem fileSystem, StartupOptions startupOptions, Func httpClient, - IApplicationPaths appPaths) + IApplicationPaths appPaths, + ILocalizationManager localizationManager) { try { - return new SkiaEncoder(logManager.GetLogger("Skia"), appPaths, httpClient, fileSystem); + return new SkiaEncoder(logManager.GetLogger("Skia"), appPaths, httpClient, fileSystem, localizationManager); } catch { diff --git a/MediaBrowser.ServerApplication/MainStartup.cs b/MediaBrowser.ServerApplication/MainStartup.cs index 70b03aa44b..91a949921e 100644 --- a/MediaBrowser.ServerApplication/MainStartup.cs +++ b/MediaBrowser.ServerApplication/MainStartup.cs @@ -304,6 +304,19 @@ namespace MediaBrowser.ServerApplication } } + private static string UpdatePackageFileName + { + get + { + if (Environment.Is64BitOperatingSystem) + { + return "embyserver-win-x64-{version}.zip"; + } + + return "embyserver-win-x86-{version}.zip"; + } + } + /// /// Runs the application. /// @@ -324,7 +337,7 @@ namespace MediaBrowser.ServerApplication options, fileSystem, new PowerManagement(), - "emby.windows.zip", + UpdatePackageFileName, environmentInfo, new NullImageEncoder(), new SystemEvents(logManager.GetLogger("SystemEvents")), @@ -355,7 +368,7 @@ namespace MediaBrowser.ServerApplication } // set image encoder here - appHost.ImageProcessor.ImageEncoder = ImageEncoderHelper.GetImageEncoder(_logger, logManager, fileSystem, options, () => appHost.HttpClient, appPaths); + appHost.ImageProcessor.ImageEncoder = ImageEncoderHelper.GetImageEncoder(_logger, logManager, fileSystem, options, () => appHost.HttpClient, appPaths, appHost.LocalizationManager); task = task.ContinueWith(new Action(a => appHost.RunStartupTasks()), TaskContinuationOptions.OnlyOnRanToCompletion | TaskContinuationOptions.AttachedToParent);