Browse Source

move crop whitespace directly to encode image

Luke Pulverenti 8 years ago
parent
commit
f49d20033d

+ 5 - 11
Emby.Drawing.ImageMagick/ImageMagickEncoder.cs

@@ -105,17 +105,6 @@ namespace Emby.Drawing.ImageMagick
             }
             }
         }
         }
 
 
-        public void CropWhiteSpace(string inputPath, string outputPath)
-        {
-            CheckDisposed();
-
-            using (var wand = new MagickWand(inputPath))
-            {
-                wand.CurrentImage.TrimImage(10);
-                wand.SaveImage(outputPath);
-            }
-        }
-
         public ImageSize GetImageSize(string path)
         public ImageSize GetImageSize(string path)
         {
         {
             CheckDisposed();
             CheckDisposed();
@@ -150,6 +139,11 @@ namespace Emby.Drawing.ImageMagick
             {
             {
                 using (var originalImage = new MagickWand(inputPath))
                 using (var originalImage = new MagickWand(inputPath))
                 {
                 {
+                    if (options.CropWhiteSpace)
+                    {
+                        originalImage.CurrentImage.TrimImage(10);
+                    }
+
                     ScaleImage(originalImage, width, height, options.Blur ?? 0);
                     ScaleImage(originalImage, width, height, options.Blur ?? 0);
 
 
                     if (autoOrient)
                     if (autoOrient)

+ 7 - 10
Emby.Drawing.Net/GDIImageEncoder.cs

@@ -75,27 +75,24 @@ namespace Emby.Drawing.Net
             }
             }
         }
         }
 
 
-        public void CropWhiteSpace(string inputPath, string outputPath)
+        private Image GetImage(string path, bool cropWhitespace)
         {
         {
-            using (var image = (Bitmap)Image.FromFile(inputPath))
+            if (cropWhitespace)
             {
             {
-                using (var croppedImage = image.CropWhitespace())
+                using (var originalImage = (Bitmap)Image.FromFile(path))
                 {
                 {
-                    _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(outputPath));
-
-                    using (var outputStream = _fileSystem.GetFileStream(outputPath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, false))
-                    {
-                        croppedImage.Save(System.Drawing.Imaging.ImageFormat.Png, outputStream, 100);
-                    }
+                    return originalImage.CropWhitespace();
                 }
                 }
             }
             }
+
+            return Image.FromFile(path);
         }
         }
 
 
         public void EncodeImage(string inputPath, string cacheFilePath, bool autoOrient, int width, int height, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat)
         public void EncodeImage(string inputPath, string cacheFilePath, bool autoOrient, int width, int height, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat)
         {
         {
             var hasPostProcessing = !string.IsNullOrEmpty(options.BackgroundColor) || options.UnplayedCount.HasValue || options.AddPlayedIndicator || options.PercentPlayed > 0;
             var hasPostProcessing = !string.IsNullOrEmpty(options.BackgroundColor) || options.UnplayedCount.HasValue || options.AddPlayedIndicator || options.PercentPlayed > 0;
 
 
-            using (var originalImage = Image.FromFile(inputPath))
+            using (var originalImage = GetImage(inputPath, options.CropWhiteSpace))
             {
             {
                 var newWidth = Convert.ToInt32(width);
                 var newWidth = Convert.ToInt32(width);
                 var newHeight = Convert.ToInt32(height);
                 var newHeight = Convert.ToInt32(height);

+ 129 - 21
Emby.Drawing.Skia/SkiaEncoder.cs

@@ -66,7 +66,15 @@ namespace Emby.Drawing.Skia
 
 
         public static string GetVersion()
         public static string GetVersion()
         {
         {
-            return typeof(SKCanvas).GetTypeInfo().Assembly.GetName().Version.ToString();
+            using (var bitmap = new SKBitmap())
+            {
+                return typeof(SKBitmap).GetTypeInfo().Assembly.GetName().Version.ToString();
+            }
+        }
+
+        private static bool IsWhiteSpace(SKColor color)
+        {
+            return (color.Red == 255 && color.Green == 255 && color.Blue == 255) || color.Alpha == 0;
         }
         }
 
 
         public static SKEncodedImageFormat GetImageFormat(ImageFormat selectedFormat)
         public static SKEncodedImageFormat GetImageFormat(ImageFormat selectedFormat)
@@ -81,22 +89,88 @@ namespace Emby.Drawing.Skia
                     return SKEncodedImageFormat.Gif;
                     return SKEncodedImageFormat.Gif;
                 case ImageFormat.Webp:
                 case ImageFormat.Webp:
                     return SKEncodedImageFormat.Webp;
                     return SKEncodedImageFormat.Webp;
-                case ImageFormat.Png:
                 default:
                 default:
                     return SKEncodedImageFormat.Png;
                     return SKEncodedImageFormat.Png;
             }
             }
         }
         }
 
 
-        public void CropWhiteSpace(string inputPath, string outputPath)
+        private static bool IsAllWhiteRow(SKBitmap bmp, int row)
+        {
+            for (var i = 0; i < bmp.Width; ++i)
+            {
+                if (!IsWhiteSpace(bmp.GetPixel(i, row)))
+                {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        private static bool IsAllWhiteColumn(SKBitmap bmp, int col)
+        {
+            for (var i = 0; i < bmp.Height; ++i)
+            {
+                if (!IsWhiteSpace(bmp.GetPixel(col, i)))
+                {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        private SKBitmap CropWhiteSpace(SKBitmap bitmap)
         {
         {
             CheckDisposed();
             CheckDisposed();
 
 
-            using (var bitmap = SKBitmap.Decode(inputPath))
+            var topmost = 0;
+            for (int row = 0; row < bitmap.Height; ++row)
+            {
+                if (IsAllWhiteRow(bitmap, row))
+                    topmost = row;
+                else break;
+            }
+
+            int bottommost = 0;
+            for (int row = bitmap.Height - 1; row >= 0; --row)
+            {
+                if (IsAllWhiteRow(bitmap, row))
+                    bottommost = row;
+                else break;
+            }
+
+            int leftmost = 0, rightmost = 0;
+            for (int col = 0; col < bitmap.Width; ++col)
+            {
+                if (IsAllWhiteColumn(bitmap, col))
+                    leftmost = col;
+                else
+                    break;
+            }
+
+            for (int col = bitmap.Width - 1; col >= 0; --col)
             {
             {
-                // @todo
+                if (IsAllWhiteColumn(bitmap, col))
+                    rightmost = col;
+                else
+                    break;
             }
             }
 
 
-            _fileSystem.CopyFile(inputPath, outputPath, true);
+            var newRect = SKRectI.Create(leftmost, topmost, rightmost - leftmost, bottommost - topmost);
+
+            using (var image = SKImage.FromBitmap(bitmap))
+            {
+                using (var subset = image.Subset(newRect))
+                {
+                    return SKBitmap.FromImage(subset);
+                    //using (var data = subset.Encode(StripCollageBuilder.GetEncodedFormat(outputPath), 90))
+                    //{
+                    //    using (var fileStream = _fileSystem.GetFileStream(outputPath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read))
+                    //    {
+                    //        data.AsStream().CopyTo(fileStream);
+                    //    }
+                    //}
+                }
+            }
         }
         }
 
 
         public ImageSize GetImageSize(string path)
         public ImageSize GetImageSize(string path)
@@ -118,6 +192,19 @@ namespace Emby.Drawing.Skia
             }
             }
         }
         }
 
 
+        private SKBitmap GetBitmap(string path, bool cropWhitespace)
+        {
+            if (cropWhitespace)
+            {
+                using (var bitmap = SKBitmap.Decode(path))
+                {
+                    return CropWhiteSpace(bitmap);
+                }
+            } 
+
+            return SKBitmap.Decode(path);
+        }
+
         public void EncodeImage(string inputPath, string outputPath, bool autoOrient, int width, int height, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat)
         public void EncodeImage(string inputPath, string outputPath, bool autoOrient, int width, int height, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat)
         {
         {
             if (string.IsNullOrWhiteSpace(inputPath))
             if (string.IsNullOrWhiteSpace(inputPath))
@@ -129,12 +216,34 @@ namespace Emby.Drawing.Skia
                 throw new ArgumentNullException("outputPath");
                 throw new ArgumentNullException("outputPath");
             }
             }
 
 
-            using (var bitmap = SKBitmap.Decode(inputPath))
+            var skiaOutputFormat = GetImageFormat(selectedOutputFormat);
+
+            var hasBackgroundColor = !string.IsNullOrWhiteSpace(options.BackgroundColor);
+            var hasForegroundColor = !string.IsNullOrWhiteSpace(options.ForegroundLayer);
+            var blur = options.Blur ?? 0;
+            var hasIndicator = !options.AddPlayedIndicator && !options.UnplayedCount.HasValue && options.PercentPlayed.Equals(0);
+
+            using (var bitmap = GetBitmap(inputPath, options.CropWhiteSpace))
             {
             {
                 using (var resizedBitmap = new SKBitmap(width, height, bitmap.ColorType, bitmap.AlphaType))
                 using (var resizedBitmap = new SKBitmap(width, height, bitmap.ColorType, bitmap.AlphaType))
                 {
                 {
                     // scale image
                     // scale image
-                    bitmap.Resize(resizedBitmap, SKBitmapResizeMethod.Lanczos3);
+                    var resizeMethod = options.Image.Type == MediaBrowser.Model.Entities.ImageType.Logo ||
+                                       options.Image.Type == MediaBrowser.Model.Entities.ImageType.Art
+                        ? SKBitmapResizeMethod.Lanczos3
+                        : SKBitmapResizeMethod.Lanczos3;
+
+                    bitmap.Resize(resizedBitmap, resizeMethod);
+
+                    // If all we're doing is resizing then we can stop now
+                    if (!hasBackgroundColor && !hasForegroundColor && blur == 0 && !hasIndicator)
+                    {
+                        using (var outputStream = new SKFileWStream(outputPath))
+                        {
+                            resizedBitmap.Encode(outputStream, skiaOutputFormat, quality);
+                            return;
+                        }
+                    }
 
 
                     // create bitmap to use for canvas drawing
                     // create bitmap to use for canvas drawing
                     using (var saveBitmap = new SKBitmap(width, height, bitmap.ColorType, bitmap.AlphaType))
                     using (var saveBitmap = new SKBitmap(width, height, bitmap.ColorType, bitmap.AlphaType))
@@ -143,13 +252,13 @@ namespace Emby.Drawing.Skia
                         using (var canvas = new SKCanvas(saveBitmap))
                         using (var canvas = new SKCanvas(saveBitmap))
                         {
                         {
                             // set background color if present
                             // set background color if present
-                            if (!string.IsNullOrWhiteSpace(options.BackgroundColor))
+                            if (hasBackgroundColor)
                             {
                             {
                                 canvas.Clear(SKColor.Parse(options.BackgroundColor));
                                 canvas.Clear(SKColor.Parse(options.BackgroundColor));
                             }
                             }
 
 
                             // Add blur if option is present
                             // Add blur if option is present
-                            if (options.Blur > 0)
+                            if (blur > 0)
                             {
                             {
                                 using (var paint = new SKPaint())
                                 using (var paint = new SKPaint())
                                 {
                                 {
@@ -168,20 +277,23 @@ namespace Emby.Drawing.Skia
                             }
                             }
 
 
                             // If foreground layer present then draw
                             // If foreground layer present then draw
-                            if (!string.IsNullOrWhiteSpace(options.ForegroundLayer))
+                            if (hasForegroundColor)
                             {
                             {
                                 Double opacity;
                                 Double opacity;
                                 if (!Double.TryParse(options.ForegroundLayer, out opacity)) opacity = .4;
                                 if (!Double.TryParse(options.ForegroundLayer, out opacity)) opacity = .4;
 
 
-                                var foregroundColor = String.Format("#{0:X2}000000", (Byte)((1-opacity) * 0xFF));
+                                var foregroundColor = String.Format("#{0:X2}000000", (Byte)((1 - opacity) * 0xFF));
                                 canvas.DrawColor(SKColor.Parse(foregroundColor), SKBlendMode.SrcOver);
                                 canvas.DrawColor(SKColor.Parse(foregroundColor), SKBlendMode.SrcOver);
                             }
                             }
 
 
-                            DrawIndicator(canvas, width, height, options);
+                            if (hasIndicator)
+                            {
+                                DrawIndicator(canvas, width, height, options);
+                            }
 
 
                             using (var outputStream = new SKFileWStream(outputPath))
                             using (var outputStream = new SKFileWStream(outputPath))
                             {
                             {
-                                saveBitmap.Encode(outputStream, GetImageFormat(selectedOutputFormat), quality);
+                                saveBitmap.Encode(outputStream, skiaOutputFormat, quality);
                             }
                             }
                         }
                         }
                     }
                     }
@@ -204,17 +316,13 @@ namespace Emby.Drawing.Skia
             }
             }
             else
             else
             {
             {
-                new StripCollageBuilder(_appPaths, _fileSystem).BuildPosterCollage(options.InputPaths, options.OutputPath, options.Width, options.Height);
+                // @todo create Poster collage capability
+                new StripCollageBuilder(_appPaths, _fileSystem).BuildSquareCollage(options.InputPaths, options.OutputPath, options.Width, options.Height);
             }
             }
         }
         }
 
 
         private void DrawIndicator(SKCanvas canvas, int imageWidth, int imageHeight, ImageProcessingOptions options)
         private void DrawIndicator(SKCanvas canvas, int imageWidth, int imageHeight, ImageProcessingOptions options)
         {
         {
-            if (!options.AddPlayedIndicator && !options.UnplayedCount.HasValue && options.PercentPlayed.Equals(0))
-            {
-                return;
-            }
-
             try
             try
             {
             {
                 var currentImageSize = new ImageSize(imageWidth, imageHeight);
                 var currentImageSize = new ImageSize(imageWidth, imageHeight);
@@ -269,4 +377,4 @@ namespace Emby.Drawing.Skia
             get { return true; }
             get { return true; }
         }
         }
     }
     }
-}
+}

+ 43 - 124
Emby.Drawing.Skia/StripCollageBuilder.cs

@@ -2,9 +2,6 @@
 using MediaBrowser.Common.Configuration;
 using MediaBrowser.Common.Configuration;
 using System;
 using System;
 using System.IO;
 using System.IO;
-using System.Collections.Generic;
-using MediaBrowser.Common.IO;
-using MediaBrowser.Controller.IO;
 using MediaBrowser.Model.IO;
 using MediaBrowser.Model.IO;
 
 
 namespace Emby.Drawing.Skia
 namespace Emby.Drawing.Skia
@@ -20,7 +17,7 @@ namespace Emby.Drawing.Skia
             _fileSystem = fileSystem;
             _fileSystem = fileSystem;
         }
         }
 
 
-        private SKEncodedImageFormat GetEncodedFormat(string outputPath)
+        public static SKEncodedImageFormat GetEncodedFormat(string outputPath)
         {
         {
             var ext = Path.GetExtension(outputPath).ToLower();
             var ext = Path.GetExtension(outputPath).ToLower();
 
 
@@ -42,13 +39,7 @@ namespace Emby.Drawing.Skia
 
 
         public void BuildPosterCollage(string[] paths, string outputPath, int width, int height)
         public void BuildPosterCollage(string[] paths, string outputPath, int width, int height)
         {
         {
-            using (var bitmap = BuildPosterCollageBitmap(paths, width, height))
-            {
-                using (var outputStream = new SKFileWStream(outputPath))
-                {
-                    bitmap.Encode(outputStream, GetEncodedFormat(outputPath), 90);
-                }
-            }
+            // @todo
         }
         }
 
 
         public void BuildSquareCollage(string[] paths, string outputPath, int width, int height)
         public void BuildSquareCollage(string[] paths, string outputPath, int width, int height)
@@ -73,136 +64,64 @@ namespace Emby.Drawing.Skia
             }
             }
         }
         }
 
 
-        private SKBitmap BuildPosterCollageBitmap(string[] paths, int width, int height)
+        private SKBitmap BuildThumbCollageBitmap(string[] paths, int width, int height)
         {
         {
-            return null;
-           /* var inputPaths = ImageHelpers.ProjectPaths(paths, 3);
-            using (var wandImages = new MagickWand(inputPaths.ToArray()))
-            {
-                var wand = new MagickWand(width, height);
-                wand.OpenImage("gradient:#111111-#111111");
-                using (var draw = new DrawingWand())
-                {
-                    var iSlice = Convert.ToInt32(width * 0.3);
-                    int iTrans = Convert.ToInt32(height * .25);
-                    int iHeight = Convert.ToInt32(height * .65);
-                    var horizontalImagePadding = Convert.ToInt32(width * 0.0366);
-
-                    foreach (var element in wandImages.ImageList)
-                    {
-                        using (var blackPixelWand = new PixelWand(ColorName.Black))
-                        {
-                            int iWidth = (int)Math.Abs(iHeight * element.Width / element.Height);
-                            element.Gravity = GravityType.CenterGravity;
-                            element.BackgroundColor = blackPixelWand;
-                            element.ResizeImage(iWidth, iHeight, FilterTypes.LanczosFilter);
-                            int ix = (int)Math.Abs((iWidth - iSlice) / 2);
-                            element.CropImage(iSlice, iHeight, ix, 0);
-
-                            element.ExtentImage(iSlice, iHeight, 0 - horizontalImagePadding, 0);
-                        }
-                    }
-
-                    wandImages.SetFirstIterator();
-                    using (var wandList = wandImages.AppendImages())
-                    {
-                        wandList.CurrentImage.TrimImage(1);
-                        using (var mwr = wandList.CloneMagickWand())
-                        {
-                            using (var blackPixelWand = new PixelWand(ColorName.Black))
-                            {
-                                using (var greyPixelWand = new PixelWand(ColorName.Grey70))
-                                {
-                                    mwr.CurrentImage.ResizeImage(wandList.CurrentImage.Width, (wandList.CurrentImage.Height / 2), FilterTypes.LanczosFilter, 1);
-                                    mwr.CurrentImage.FlipImage();
-
-                                    mwr.CurrentImage.AlphaChannel = AlphaChannelType.DeactivateAlphaChannel;
-                                    mwr.CurrentImage.ColorizeImage(blackPixelWand, greyPixelWand);
-
-                                    using (var mwg = new MagickWand(wandList.CurrentImage.Width, iTrans))
-                                    {
-                                        mwg.OpenImage("gradient:black-none");
-                                        var verticalSpacing = Convert.ToInt32(height * 0.01111111111111111111111111111111);
-                                        mwr.CurrentImage.CompositeImage(mwg, CompositeOperator.CopyOpacityCompositeOp, 0, verticalSpacing);
+            var bitmap = new SKBitmap(width, height);
 
 
-                                        wandList.AddImage(mwr);
-                                        int ex = (int)(wand.CurrentImage.Width - mwg.CurrentImage.Width) / 2;
-                                        wand.CurrentImage.CompositeImage(wandList.AppendImages(true), CompositeOperator.AtopCompositeOp, ex, Convert.ToInt32(height * .05));
-                                    }
-                                }
-                            }
-                        }
-                    }
-                }
+            using (var canvas = new SKCanvas(bitmap))
+            {
+                canvas.Clear(SKColors.Black);
 
 
-                return wand;
-            }*/
-        }
+                var iSlice = Convert.ToInt32(width * 0.24125);
+                int iTrans = Convert.ToInt32(height * .25);
+                int iHeight = Convert.ToInt32(height * .70);
+                var horizontalImagePadding = Convert.ToInt32(width * 0.0125);
+                var verticalSpacing = Convert.ToInt32(height * 0.01111111111111111111111111111111);
+                int imageIndex = 0;
 
 
-        private SKBitmap BuildThumbCollageBitmap(string[] paths, int width, int height)
-        {
-            return null;
-            /*var inputPaths = ImageHelpers.ProjectPaths(paths, 4);
-            using (var wandImages = new MagickWand(inputPaths.ToArray()))
-            {
-                var wand = new MagickWand(width, height);
-                wand.OpenImage("gradient:#111111-#111111");
-                using (var draw = new DrawingWand())
+                for (int i = 0; i < 4; i++)
                 {
                 {
-                    var iSlice = Convert.ToInt32(width * 0.24125);
-                    int iTrans = Convert.ToInt32(height * .25);
-                    int iHeight = Convert.ToInt32(height * .70);
-                    var horizontalImagePadding = Convert.ToInt32(width * 0.0125);
-
-                    foreach (var element in wandImages.ImageList)
+                    using (var currentBitmap = SKBitmap.Decode(paths[imageIndex]))
                     {
                     {
-                        using (var blackPixelWand = new PixelWand(ColorName.Black))
+                        int iWidth = (int)Math.Abs(iHeight * currentBitmap.Width / currentBitmap.Height);
+                        using (var resizeBitmap = new SKBitmap(iWidth, iHeight, currentBitmap.ColorType, currentBitmap.AlphaType))
                         {
                         {
-                            int iWidth = (int)Math.Abs(iHeight * element.Width / element.Height);
-                            element.Gravity = GravityType.CenterGravity;
-                            element.BackgroundColor = blackPixelWand;
-                            element.ResizeImage(iWidth, iHeight, FilterTypes.LanczosFilter);
+                            currentBitmap.Resize(resizeBitmap, SKBitmapResizeMethod.Lanczos3);
                             int ix = (int)Math.Abs((iWidth - iSlice) / 2);
                             int ix = (int)Math.Abs((iWidth - iSlice) / 2);
-                            element.CropImage(iSlice, iHeight, ix, 0);
-
-                            element.ExtentImage(iSlice, iHeight, 0 - horizontalImagePadding, 0);
-                        }
-                    }
-
-                    wandImages.SetFirstIterator();
-                    using (var wandList = wandImages.AppendImages())
-                    {
-                        wandList.CurrentImage.TrimImage(1);
-                        using (var mwr = wandList.CloneMagickWand())
-                        {
-                            using (var blackPixelWand = new PixelWand(ColorName.Black))
+                            using (var image = SKImage.FromBitmap(resizeBitmap))
                             {
                             {
-                                using (var greyPixelWand = new PixelWand(ColorName.Grey70))
+                                using (var subset = image.Subset(SKRectI.Create(ix, 0, iSlice, iHeight)))
                                 {
                                 {
-                                    mwr.CurrentImage.ResizeImage(wandList.CurrentImage.Width, (wandList.CurrentImage.Height / 2), FilterTypes.LanczosFilter, 1);
-                                    mwr.CurrentImage.FlipImage();
-
-                                    mwr.CurrentImage.AlphaChannel = AlphaChannelType.DeactivateAlphaChannel;
-                                    mwr.CurrentImage.ColorizeImage(blackPixelWand, greyPixelWand);
+                                    canvas.DrawImage(subset, (horizontalImagePadding * (i + 1)) + (iSlice * i), 0);
 
 
-                                    using (var mwg = new MagickWand(wandList.CurrentImage.Width, iTrans))
+                                    using (var croppedBitmap = SKBitmap.FromImage(subset))
                                     {
                                     {
-                                        mwg.OpenImage("gradient:black-none");
-                                        var verticalSpacing = Convert.ToInt32(height * 0.01111111111111111111111111111111);
-                                        mwr.CurrentImage.CompositeImage(mwg, CompositeOperator.CopyOpacityCompositeOp, 0, verticalSpacing);
-
-                                        wandList.AddImage(mwr);
-                                        int ex = (int)(wand.CurrentImage.Width - mwg.CurrentImage.Width) / 2;
-                                        wand.CurrentImage.CompositeImage(wandList.AppendImages(true), CompositeOperator.AtopCompositeOp, ex, Convert.ToInt32(height * .045));
+                                        using (var flipped = new SKBitmap(croppedBitmap.Width, croppedBitmap.Height / 2, croppedBitmap.ColorType, croppedBitmap.AlphaType))
+                                        {
+                                            croppedBitmap.Resize(flipped, SKBitmapResizeMethod.Lanczos3);
+
+                                            using (var gradient = new SKPaint())
+                                            {
+                                                var matrix = SKMatrix.MakeScale(1, -1);
+                                                matrix.SetScaleTranslate(1, -1, 0, flipped.Height);
+                                                gradient.Shader = SKShader.CreateLinearGradient(new SKPoint(0, 0), new SKPoint(0, flipped.Height), new[] { new SKColor(0, 0, 0, 0), SKColors.Black }, null, SKShaderTileMode.Clamp, matrix);
+                                                canvas.DrawBitmap(flipped, (horizontalImagePadding * (i + 1)) + (iSlice * i), iHeight + verticalSpacing, gradient);
+                                            }
+                                        }
                                     }
                                     }
                                 }
                                 }
                             }
                             }
                         }
                         }
                     }
                     }
+
+                    imageIndex++;
+
+                    if (imageIndex >= paths.Length)
+                        imageIndex = 0;
                 }
                 }
+            }
 
 
-                return wand;
-            }*/
+            return bitmap;
         }
         }
 
 
         private SKBitmap BuildSquareCollageBitmap(string[] paths, int width, int height)
         private SKBitmap BuildSquareCollageBitmap(string[] paths, int width, int height)
@@ -224,7 +143,7 @@ namespace Emby.Drawing.Skia
                             {
                             {
                                 // scale image
                                 // scale image
                                 currentBitmap.Resize(resizedBitmap, SKBitmapResizeMethod.Lanczos3);
                                 currentBitmap.Resize(resizedBitmap, SKBitmapResizeMethod.Lanczos3);
-                        
+
                                 // draw this image into the strip at the next position
                                 // draw this image into the strip at the next position
                                 var xPos = x * cellWidth;
                                 var xPos = x * cellWidth;
                                 var yPos = y * cellHeight;
                                 var yPos = y * cellHeight;
@@ -242,4 +161,4 @@ namespace Emby.Drawing.Skia
             return bitmap;
             return bitmap;
         }
         }
     }
     }
-}
+}

+ 0 - 56
Emby.Drawing/ImageProcessor.cs

@@ -136,14 +136,6 @@ namespace Emby.Drawing
             }
             }
         }
         }
 
 
-        private string CroppedWhitespaceImageCachePath
-        {
-            get
-            {
-                return Path.Combine(_appPaths.ImageCachePath, "cropped-images");
-            }
-        }
-
         public void AddParts(IEnumerable<IImageEnhancer> enhancers)
         public void AddParts(IEnumerable<IImageEnhancer> enhancers)
         {
         {
             ImageEnhancers = enhancers.ToArray();
             ImageEnhancers = enhancers.ToArray();
@@ -186,14 +178,6 @@ namespace Emby.Drawing
                 return new Tuple<string, string, DateTime>(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified);
                 return new Tuple<string, string, DateTime>(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified);
             }
             }
 
 
-            if (options.CropWhiteSpace && _imageEncoder.SupportsImageEncoding)
-            {
-                var tuple = await GetWhitespaceCroppedImage(originalImagePath, dateModified).ConfigureAwait(false);
-
-                originalImagePath = tuple.Item1;
-                dateModified = tuple.Item2;
-            }
-
             if (options.Enhancers.Count > 0)
             if (options.Enhancers.Count > 0)
             {
             {
                 var tuple = await GetEnhancedImage(new ItemImageInfo
                 var tuple = await GetEnhancedImage(new ItemImageInfo
@@ -400,46 +384,6 @@ namespace Emby.Drawing
             return requestedFormat;
             return requestedFormat;
         }
         }
 
 
-        /// <summary>
-        /// Crops whitespace from an image, caches the result, and returns the cached path
-        /// </summary>
-        private async Task<Tuple<string, DateTime>> GetWhitespaceCroppedImage(string originalImagePath, DateTime dateModified)
-        {
-            var name = originalImagePath;
-            name += "datemodified=" + dateModified.Ticks;
-
-            var croppedImagePath = GetCachePath(CroppedWhitespaceImageCachePath, name, Path.GetExtension(originalImagePath));
-
-            // Check again in case of contention
-            if (_fileSystem.FileExists(croppedImagePath))
-            {
-                return GetResult(croppedImagePath);
-            }
-
-            try
-            {
-                _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(croppedImagePath));
-                var tmpPath = Path.ChangeExtension(Path.Combine(_appPaths.TempDirectory, Guid.NewGuid().ToString("N")), Path.GetExtension(croppedImagePath));
-                _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(tmpPath));
-
-                _imageEncoder.CropWhiteSpace(originalImagePath, tmpPath);
-                CopyFile(tmpPath, croppedImagePath);
-                return GetResult(tmpPath);
-            }
-            catch (NotImplementedException)
-            {
-                // No need to spam the log with an error message
-                return new Tuple<string, DateTime>(originalImagePath, dateModified);
-            }
-            catch (Exception ex)
-            {
-                // We have to have a catch-all here because some of the .net image methods throw a plain old Exception
-                _logger.ErrorException("Error cropping image {0}", ex, originalImagePath);
-
-                return new Tuple<string, DateTime>(originalImagePath, dateModified);
-            }
-        }
-
         private Tuple<string, DateTime> GetResult(string path)
         private Tuple<string, DateTime> GetResult(string path)
         {
         {
             return new Tuple<string, DateTime>(path, _fileSystem.GetLastWriteTimeUtc(path));
             return new Tuple<string, DateTime>(path, _fileSystem.GetLastWriteTimeUtc(path));

+ 0 - 6
MediaBrowser.Controller/Drawing/IImageEncoder.cs

@@ -16,12 +16,6 @@ namespace MediaBrowser.Controller.Drawing
         /// <value>The supported output formats.</value>
         /// <value>The supported output formats.</value>
         ImageFormat[] SupportedOutputFormats { get; }
         ImageFormat[] SupportedOutputFormats { get; }
         /// <summary>
         /// <summary>
-        /// Crops the white space.
-        /// </summary>
-        /// <param name="inputPath">The input path.</param>
-        /// <param name="outputPath">The output path.</param>
-        void CropWhiteSpace(string inputPath, string outputPath);
-        /// <summary>
         /// Encodes the image.
         /// Encodes the image.
         /// </summary>
         /// </summary>
         /// <param name="inputPath">The input path.</param>
         /// <param name="inputPath">The input path.</param>

+ 1 - 0
MediaBrowser.Controller/Drawing/ImageProcessingOptions.cs

@@ -86,6 +86,7 @@ namespace MediaBrowser.Controller.Drawing
                 PercentPlayed.Equals(0) &&
                 PercentPlayed.Equals(0) &&
                 !UnplayedCount.HasValue &&
                 !UnplayedCount.HasValue &&
                 !Blur.HasValue &&
                 !Blur.HasValue &&
+                !CropWhiteSpace &&
                 string.IsNullOrEmpty(BackgroundColor) &&
                 string.IsNullOrEmpty(BackgroundColor) &&
                 string.IsNullOrEmpty(ForegroundLayer);
                 string.IsNullOrEmpty(ForegroundLayer);
         }
         }

+ 1 - 1
MediaBrowser.ServerApplication/ImageEncoderHelper.cs

@@ -26,7 +26,7 @@ namespace MediaBrowser.Server.Startup.Common
             {
             {
                 try
                 try
                 {
                 {
-                    return new SkiaEncoder(logManager.GetLogger("ImageMagick"), appPaths, httpClient, fileSystem);
+                    //return new SkiaEncoder(logManager.GetLogger("ImageMagick"), appPaths, httpClient, fileSystem);
                 }
                 }
                 catch
                 catch
                 {
                 {