Browse Source

Use backdrop with library name as library thumbnail

David 4 years ago
parent
commit
a3020f2917

+ 3 - 3
Emby.Drawing/ImageProcessor.cs

@@ -36,7 +36,7 @@ namespace Emby.Drawing
         private readonly IImageEncoder _imageEncoder;
         private readonly IMediaEncoder _mediaEncoder;
 
-        private bool _disposed = false;
+        private bool _disposed;
 
         /// <summary>
         /// Initializes a new instance of the <see cref="ImageProcessor"/> class.
@@ -466,11 +466,11 @@ namespace Emby.Drawing
         }
 
         /// <inheritdoc />
-        public void CreateImageCollage(ImageCollageOptions options)
+        public void CreateImageCollage(ImageCollageOptions options, string? libraryName)
         {
             _logger.LogInformation("Creating image collage and saving to {Path}", options.OutputPath);
 
-            _imageEncoder.CreateImageCollage(options);
+            _imageEncoder.CreateImageCollage(options, libraryName);
 
             _logger.LogInformation("Completed creation of image collage and saved to {Path}", options.OutputPath);
         }

+ 1 - 1
Emby.Drawing/NullImageEncoder.cs

@@ -38,7 +38,7 @@ namespace Emby.Drawing
         }
 
         /// <inheritdoc />
-        public void CreateImageCollage(ImageCollageOptions options)
+        public void CreateImageCollage(ImageCollageOptions options, string? libraryName)
         {
             throw new NotImplementedException();
         }

+ 12 - 1
Emby.Server.Implementations/Images/BaseDynamicImageProvider.cs

@@ -133,9 +133,20 @@ namespace Emby.Server.Implementations.Images
 
         protected virtual IEnumerable<string> GetStripCollageImagePaths(BaseItem primaryItem, IEnumerable<BaseItem> items)
         {
+            var useBackdrop = primaryItem is CollectionFolder;
             return items
                 .Select(i =>
                 {
+                    // Use Backdrop instead of Primary image for Library images.
+                    if (useBackdrop)
+                    {
+                        var backdrop = i.GetImageInfo(ImageType.Backdrop, 0);
+                        if (backdrop != null && backdrop.IsLocalFile)
+                        {
+                            return backdrop.Path;
+                        }
+                    }
+
                     var image = i.GetImageInfo(ImageType.Primary, 0);
                     if (image != null && image.IsLocalFile)
                     {
@@ -190,7 +201,7 @@ namespace Emby.Server.Implementations.Images
                 return null;
             }
 
-            ImageProcessor.CreateImageCollage(options);
+            ImageProcessor.CreateImageCollage(options, primaryItem.Name);
             return outputPath;
         }
 

+ 2 - 2
Jellyfin.Drawing.Skia/SkiaEncoder.cs

@@ -553,13 +553,13 @@ namespace Jellyfin.Drawing.Skia
         }
 
         /// <inheritdoc/>
-        public void CreateImageCollage(ImageCollageOptions options)
+        public void CreateImageCollage(ImageCollageOptions options, string? libraryName)
         {
             double ratio = (double)options.Width / options.Height;
 
             if (ratio >= 1.4)
             {
-                new StripCollageBuilder(this).BuildThumbCollage(options.InputPaths, options.OutputPath, options.Width, options.Height);
+                new StripCollageBuilder(this).BuildThumbCollage(options.InputPaths, options.OutputPath, options.Width, options.Height, libraryName);
             }
             else if (ratio >= .9)
             {

+ 32 - 26
Jellyfin.Drawing.Skia/StripCollageBuilder.cs

@@ -82,47 +82,53 @@ namespace Jellyfin.Drawing.Skia
         /// <param name="outputPath">The path at which to place the resulting image.</param>
         /// <param name="width">The desired width of the collage.</param>
         /// <param name="height">The desired height of the collage.</param>
-        public void BuildThumbCollage(string[] paths, string outputPath, int width, int height)
+        /// <param name="libraryName">The name of the library to draw on the collage.</param>
+        public void BuildThumbCollage(string[] paths, string outputPath, int width, int height, string? libraryName)
         {
-            using var bitmap = BuildThumbCollageBitmap(paths, width, height);
+            using var bitmap = BuildThumbCollageBitmap(paths, width, height, libraryName);
             using var outputStream = new SKFileWStream(outputPath);
             using var pixmap = new SKPixmap(new SKImageInfo(width, height), bitmap.GetPixels());
             pixmap.Encode(outputStream, GetEncodedFormat(outputPath), 90);
         }
 
-        private SKBitmap BuildThumbCollageBitmap(string[] paths, int width, int height)
+        private SKBitmap BuildThumbCollageBitmap(string[] paths, int width, int height, string? libraryName)
         {
             var bitmap = new SKBitmap(width, height);
 
             using var canvas = new SKCanvas(bitmap);
             canvas.Clear(SKColors.Black);
 
-            // number of images used in the thumbnail
-            var iCount = 3;
-
-            // determine sizes for each image that will composited into the final image
-            var iSlice = Convert.ToInt32(width / iCount);
-            int iHeight = Convert.ToInt32(height * 1.00);
-            int imageIndex = 0;
-            for (int i = 0; i < iCount; i++)
+            using var backdrop = GetNextValidImage(paths, 0, out _);
+            if (backdrop == null)
             {
-                using var currentBitmap = GetNextValidImage(paths, imageIndex, out int newIndex);
-                imageIndex = newIndex;
-                if (currentBitmap == null)
-                {
-                    continue;
-                }
+                return bitmap;
+            }
 
-                // resize to the same aspect as the original
-                int iWidth = Math.Abs(iHeight * currentBitmap.Width / currentBitmap.Height);
-                using var resizedImage = SkiaEncoder.ResizeImage(currentBitmap, new SKImageInfo(iWidth, iHeight, currentBitmap.ColorType, currentBitmap.AlphaType, currentBitmap.ColorSpace));
+            // resize to the same aspect as the original
+            var backdropHeight = Math.Abs(width * backdrop.Height / backdrop.Width);
+            using var residedBackdrop = SkiaEncoder.ResizeImage(backdrop, new SKImageInfo(width, backdropHeight, backdrop.ColorType, backdrop.AlphaType, backdrop.ColorSpace));
+            // draw the backdrop
+            canvas.DrawImage(residedBackdrop, 0, 0);
 
-                // crop image
-                int ix = Math.Abs((iWidth - iSlice) / 2);
-                using var subset = resizedImage.Subset(SKRectI.Create(ix, 0, iSlice, iHeight));
-                // draw image onto canvas
-                canvas.DrawImage(subset ?? resizedImage, iSlice * i, 0);
-            }
+            // draw shadow rectangle
+            var paintColor = new SKPaint
+            {
+                Color = SKColors.Black.WithAlpha(0x78),
+                Style = SKPaintStyle.Fill
+            };
+            canvas.DrawRect(0, 0, width, height, paintColor);
+
+            // draw library name
+            var textPaint = new SKPaint
+            {
+                Color = SKColors.White,
+                Style = SKPaintStyle.Fill,
+                TextSize = 56,
+                TextAlign = SKTextAlign.Center,
+                Typeface = SKTypeface.FromFamilyName("sans-serif", SKFontStyleWeight.Bold, SKFontStyleWidth.Normal, SKFontStyleSlant.Upright),
+                IsAntialias = true
+            };
+            canvas.DrawText(libraryName, width / 2f, height / 2f, textPaint);
 
             return bitmap;
         }

+ 2 - 1
MediaBrowser.Controller/Drawing/IImageEncoder.cs

@@ -61,6 +61,7 @@ namespace MediaBrowser.Controller.Drawing
         /// Create an image collage.
         /// </summary>
         /// <param name="options">The options to use when creating the collage.</param>
-        void CreateImageCollage(ImageCollageOptions options);
+        /// <param name="libraryName">Optional. </param>
+        void CreateImageCollage(ImageCollageOptions options, string? libraryName);
     }
 }

+ 2 - 1
MediaBrowser.Controller/Drawing/IImageProcessor.cs

@@ -85,7 +85,8 @@ namespace MediaBrowser.Controller.Drawing
         /// Creates the image collage.
         /// </summary>
         /// <param name="options">The options.</param>
-        void CreateImageCollage(ImageCollageOptions options);
+        /// <param name="libraryName">The library name to draw onto the collage.</param>
+        void CreateImageCollage(ImageCollageOptions options, string? libraryName);
 
         bool SupportsTransparency(string path);
     }