123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148 |
- using System;
- using System.Collections.Generic;
- using SkiaSharp;
- namespace Jellyfin.Drawing.Skia
- {
- /// <summary>
- /// Used to build the splashscreen.
- /// </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;
- /// <summary>
- /// Initializes a new instance of the <see cref="SplashscreenBuilder"/> class.
- /// </summary>
- /// <param name="skiaEncoder">The SkiaEncoder.</param>
- public SplashscreenBuilder(SkiaEncoder skiaEncoder)
- {
- _skiaEncoder = skiaEncoder;
- }
- /// <summary>
- /// Generate a splashscreen.
- /// </summary>
- /// <param name="posters">The poster paths.</param>
- /// <param name="backdrops">The landscape paths.</param>
- /// <param name="outputPath">The output path.</param>
- public void GenerateSplash(IReadOnlyList<string> posters, IReadOnlyList<string> backdrops, string outputPath)
- {
- using var wall = GenerateCollage(posters, backdrops);
- using var transformed = Transform3D(wall);
- using var outputStream = new SKFileWStream(outputPath);
- using var pixmap = new SKPixmap(new SKImageInfo(FinalWidth, FinalHeight), transformed.GetPixels());
- pixmap.Encode(outputStream, StripCollageBuilder.GetEncodedFormat(outputPath), 90);
- }
- /// <summary>
- /// Generates a collage of posters and landscape pictures.
- /// </summary>
- /// <param name="posters">The poster paths.</param>
- /// <param name="backdrops">The landscape paths.</param>
- /// <returns>The created collage as a bitmap.</returns>
- private SKBitmap GenerateCollage(IReadOnlyList<string> posters, IReadOnlyList<string> backdrops)
- {
- var posterIndex = 0;
- var backdropIndex = 0;
- var bitmap = new SKBitmap(WallWidth, WallHeight);
- using var canvas = new SKCanvas(bitmap);
- canvas.Clear(SKColors.Black);
- int posterHeight = WallHeight / 6;
- for (int i = 0; i < Rows; i++)
- {
- int imageCounter = Random.Shared.Next(0, 5);
- int currentWidthPos = i * 75;
- int currentHeight = i * (posterHeight + Spacing);
- while (currentWidthPos < WallWidth)
- {
- SKBitmap? currentImage;
- switch (imageCounter)
- {
- case 0:
- case 2:
- case 3:
- currentImage = SkiaHelper.GetNextValidImage(_skiaEncoder, posters, posterIndex, out int newPosterIndex);
- posterIndex = newPosterIndex;
- break;
- default:
- currentImage = SkiaHelper.GetNextValidImage(_skiaEncoder, backdrops, backdropIndex, out int newBackdropIndex);
- backdropIndex = newBackdropIndex;
- break;
- }
- if (currentImage == null)
- {
- throw new ArgumentException("Not enough valid pictures provided to create a splashscreen!");
- }
- // resize to the same aspect as the original
- var imageWidth = Math.Abs(posterHeight * currentImage.Width / currentImage.Height);
- using var resizedBitmap = new SKBitmap(imageWidth, posterHeight);
- currentImage.ScalePixels(resizedBitmap, SKFilterQuality.High);
- // draw on canvas
- canvas.DrawBitmap(resizedBitmap, currentWidthPos, currentHeight);
- currentWidthPos += imageWidth + Spacing;
- currentImage.Dispose();
- if (imageCounter >= 4)
- {
- imageCounter = 0;
- }
- else
- {
- imageCounter++;
- }
- }
- }
- return bitmap;
- }
- /// <summary>
- /// Transform the collage in 3D space.
- /// </summary>
- /// <param name="input">The bitmap to transform.</param>
- /// <returns>The transformed image.</returns>
- private SKBitmap Transform3D(SKBitmap input)
- {
- var bitmap = new SKBitmap(FinalWidth, FinalHeight);
- using var canvas = new SKCanvas(bitmap);
- canvas.Clear(SKColors.Black);
- var matrix = new SKMatrix
- {
- ScaleX = 0.324108899f,
- ScaleY = 0.563934922f,
- SkewX = -0.244337708f,
- SkewY = 0.0377609022f,
- TransX = 42.0407715f,
- TransY = -198.104706f,
- Persp0 = -9.08959337E-05f,
- Persp1 = 6.85242048E-05f,
- Persp2 = 0.988209724f
- };
- canvas.SetMatrix(matrix);
- canvas.DrawBitmap(input, 0, 0);
- return bitmap;
- }
- }
- }
|