diff options
| -rw-r--r-- | Jellyfin.Api/Controllers/SplashscreenController.cs | 15 | ||||
| -rw-r--r-- | Jellyfin.Drawing.Skia/SplashscreenBuilder.cs | 22 | ||||
| -rw-r--r-- | MediaBrowser.Controller/Drawing/SplashscreenOptions.cs | 14 |
3 files changed, 20 insertions, 31 deletions
diff --git a/Jellyfin.Api/Controllers/SplashscreenController.cs b/Jellyfin.Api/Controllers/SplashscreenController.cs index 0fc9af60b..48a559b28 100644 --- a/Jellyfin.Api/Controllers/SplashscreenController.cs +++ b/Jellyfin.Api/Controllers/SplashscreenController.cs @@ -52,8 +52,6 @@ namespace Jellyfin.Api.Controllers /// Generates or gets the splashscreen. /// </summary> /// <param name="darken">Darken the generated image.</param> - /// <param name="width">The image width.</param> - /// <param name="height">The image height.</param> /// <param name="regenerate">Whether to regenerate the image, regardless if one already exists.</param> /// <returns>The splashscreen.</returns> [HttpGet] @@ -62,11 +60,9 @@ namespace Jellyfin.Api.Controllers [ProducesImageFile] public ActionResult GetSplashscreen( [FromQuery] bool? darken = false, - [FromQuery] int? width = 1920, - [FromQuery] int? height = 1080, [FromQuery] bool? regenerate = false) { - var outputPath = Path.Combine(_appPaths.DataPath, $"splashscreen-{width}x{height}-{darken}.jpg"); + var outputPath = Path.Combine(_appPaths.DataPath, $"splashscreen-{darken}.jpg"); if (!System.IO.File.Exists(outputPath) || (regenerate ?? false)) { @@ -74,11 +70,13 @@ namespace Jellyfin.Api.Controllers var landscape = GetItemsWithImageType(ImageType.Thumb).Select(x => x.GetImages(ImageType.Thumb).First().Path).ToList(); if (landscape.Count == 0) { + // Thumb images fit better because they include the title in the image but are not provided with TMDb. + // Using backdrops as a fallback to generate an image at all _logger.LogDebug("No thumb images found. Using backdrops to generate splashscreen."); landscape = GetItemsWithImageType(ImageType.Backdrop).Select(x => x.GetImages(ImageType.Backdrop).First().Path).ToList(); } - _imageEncoder.CreateSplashscreen(new SplashscreenOptions(posters, landscape, outputPath, width!.Value, height!.Value, darken!.Value)); + _imageEncoder.CreateSplashscreen(new SplashscreenOptions(posters, landscape, outputPath, darken!.Value)); } return PhysicalFile(outputPath, MimeTypes.GetMimeType(outputPath)); @@ -86,13 +84,16 @@ namespace Jellyfin.Api.Controllers private IReadOnlyList<BaseItem> GetItemsWithImageType(ImageType imageType) { + // todo make included libraries configurable return _itemRepository.GetItemList(new InternalItemsQuery { CollapseBoxSetItems = false, Recursive = true, DtoOptions = new DtoOptions(false), ImageTypes = new ImageType[] { imageType }, - Limit = 8, + Limit = 30, + // todo max parental rating configurable + MaxParentalRating = 10, OrderBy = new ValueTuple<string, SortOrder>[] { new ValueTuple<string, SortOrder>(ItemSortBy.Random, SortOrder.Ascending) diff --git a/Jellyfin.Drawing.Skia/SplashscreenBuilder.cs b/Jellyfin.Drawing.Skia/SplashscreenBuilder.cs index 8b6942be0..4773464b4 100644 --- a/Jellyfin.Drawing.Skia/SplashscreenBuilder.cs +++ b/Jellyfin.Drawing.Skia/SplashscreenBuilder.cs @@ -10,14 +10,17 @@ namespace Jellyfin.Drawing.Skia /// </summary> public class SplashscreenBuilder { + private const int FinalWidth = 1920; + private const int FinalHeight = 1080; + // generated collage resolution should be higher than the final resolution + private const int WallWidth = FinalWidth * 3; + private const int WallHeight = FinalHeight * 2; private const int Rows = 6; private const int Spacing = 20; private readonly SkiaEncoder _skiaEncoder; private Random? _random; - private int _finalWidth; - private int _finalHeight; /// <summary> /// Initializes a new instance of the <see cref="SplashscreenBuilder"/> class. @@ -34,13 +37,11 @@ namespace Jellyfin.Drawing.Skia /// <param name="options">The options to generate the splashscreen.</param> public void GenerateSplash(SplashscreenOptions options) { - _finalWidth = options.Width; - _finalHeight = options.Height; var wall = GenerateCollage(options.PortraitInputPaths, options.LandscapeInputPaths, options.ApplyFilter); var transformed = Transform3D(wall); using var outputStream = new SKFileWStream(options.OutputPath); - using var pixmap = new SKPixmap(new SKImageInfo(_finalWidth, _finalHeight), transformed.GetPixels()); + using var pixmap = new SKPixmap(new SKImageInfo(FinalWidth, FinalHeight), transformed.GetPixels()); pixmap.Encode(outputStream, StripCollageBuilder.GetEncodedFormat(options.OutputPath), 90); } @@ -58,12 +59,11 @@ namespace Jellyfin.Drawing.Skia var posterIndex = 0; var backdropIndex = 0; - // use higher resolution than final image - var bitmap = new SKBitmap(_finalWidth * 3, _finalHeight * 2); + var bitmap = new SKBitmap(WallWidth, WallHeight); using var canvas = new SKCanvas(bitmap); canvas.Clear(SKColors.Black); - int posterHeight = _finalHeight * 2 / 6; + int posterHeight = WallHeight / 6; for (int i = 0; i < Rows; i++) { @@ -71,7 +71,7 @@ namespace Jellyfin.Drawing.Skia int currentWidthPos = i * 75; int currentHeight = i * (posterHeight + Spacing); - while (currentWidthPos < _finalWidth * 3) + while (currentWidthPos < WallWidth) { SKBitmap? currentImage; @@ -124,7 +124,7 @@ namespace Jellyfin.Drawing.Skia Color = SKColors.Black.WithAlpha(0x50), Style = SKPaintStyle.Fill }; - canvas.DrawRect(0, 0, _finalWidth * 3, _finalHeight * 2, paintColor); + canvas.DrawRect(0, 0, WallWidth, WallHeight, paintColor); } return bitmap; @@ -137,7 +137,7 @@ namespace Jellyfin.Drawing.Skia /// <returns>The transformed image.</returns> private SKBitmap Transform3D(SKBitmap input) { - var bitmap = new SKBitmap(_finalWidth, _finalHeight); + var bitmap = new SKBitmap(FinalWidth, FinalHeight); using var canvas = new SKCanvas(bitmap); canvas.Clear(SKColors.Black); var matrix = new SKMatrix diff --git a/MediaBrowser.Controller/Drawing/SplashscreenOptions.cs b/MediaBrowser.Controller/Drawing/SplashscreenOptions.cs index d70773d8f..0534d60b6 100644 --- a/MediaBrowser.Controller/Drawing/SplashscreenOptions.cs +++ b/MediaBrowser.Controller/Drawing/SplashscreenOptions.cs @@ -16,13 +16,11 @@ namespace MediaBrowser.Controller.Drawing /// <param name="width">Optional. The image width.</param> /// <param name="height">Optional. The image height.</param> /// <param name="applyFilter">Optional. Apply a darkening filter.</param> - public SplashscreenOptions(IReadOnlyList<string> portraitInputPaths, IReadOnlyList<string> landscapeInputPaths, string outputPath, int width = 1920, int height = 1080, bool applyFilter = false) + public SplashscreenOptions(IReadOnlyList<string> portraitInputPaths, IReadOnlyList<string> landscapeInputPaths, string outputPath, bool applyFilter = false) { PortraitInputPaths = portraitInputPaths; LandscapeInputPaths = landscapeInputPaths; OutputPath = outputPath; - Width = width; - Height = height; ApplyFilter = applyFilter; } @@ -42,16 +40,6 @@ namespace MediaBrowser.Controller.Drawing public string OutputPath { get; set; } /// <summary> - /// Gets or sets the width. - /// </summary> - public int Width { get; set; } - - /// <summary> - /// Gets or sets the height. - /// </summary> - public int Height { get; set; } - - /// <summary> /// Gets or sets a value indicating whether to apply a darkening filter at the end. /// </summary> public bool ApplyFilter { get; set; } |
