Browse Source

replace System.Drawing with ImageMagick

Luke Pulverenti 10 years ago
parent
commit
a46d5702f3

+ 3 - 2
MediaBrowser.Controller/Providers/IImageEnhancer.cs

@@ -44,11 +44,12 @@ namespace MediaBrowser.Controller.Providers
         /// Enhances the image async.
         /// </summary>
         /// <param name="item">The item.</param>
-        /// <param name="originalImage">The original image.</param>
+        /// <param name="inputFile">The input file.</param>
+        /// <param name="outputFile">The output file.</param>
         /// <param name="imageType">Type of the image.</param>
         /// <param name="imageIndex">Index of the image.</param>
         /// <returns>Task{Image}.</returns>
         /// <exception cref="System.ArgumentNullException"></exception>
-        Task<ImageStream> EnhanceImageAsync(IHasImages item, ImageStream originalImage, ImageType imageType, int imageIndex);
+        Task EnhanceImageAsync(IHasImages item, string inputFile, string outputFile, ImageType imageType, int imageIndex);
     }
 }

+ 3 - 3
MediaBrowser.Server.Implementations/Collections/CollectionImageProvider.cs

@@ -1,4 +1,5 @@
-using MediaBrowser.Common.IO;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.IO;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Entities.Audio;
 using MediaBrowser.Controller.Entities.Movies;
@@ -15,8 +16,7 @@ namespace MediaBrowser.Server.Implementations.Collections
 {
     public class CollectionImageProvider : BaseDynamicImageProvider<BoxSet>, ICustomMetadataProvider<BoxSet>
     {
-        public CollectionImageProvider(IFileSystem fileSystem, IProviderManager providerManager)
-            : base(fileSystem, providerManager)
+        public CollectionImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths) : base(fileSystem, providerManager, applicationPaths)
         {
         }
 

+ 0 - 1
MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj

@@ -78,7 +78,6 @@
     </Reference>
     <Reference Include="Microsoft.CSharp" />
     <Reference Include="System.Data" />
-    <Reference Include="System.Drawing" />
     <Reference Include="System.Net" />
     <Reference Include="System.Security" />
     <Reference Include="System.Web" />

+ 8 - 4
MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs

@@ -1,4 +1,5 @@
-using MediaBrowser.Common.Extensions;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.Extensions;
 using MediaBrowser.Common.IO;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Library;
@@ -19,9 +20,11 @@ namespace MediaBrowser.Server.Implementations.Photos
     {
         protected IFileSystem FileSystem { get; private set; }
         protected IProviderManager ProviderManager { get; private set; }
+        protected IApplicationPaths ApplicationPaths { get; private set; }
 
-        protected BaseDynamicImageProvider(IFileSystem fileSystem, IProviderManager providerManager)
+        protected BaseDynamicImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths)
         {
+            ApplicationPaths = applicationPaths;
             ProviderManager = providerManager;
             FileSystem = fileSystem;
         }
@@ -108,14 +111,15 @@ namespace MediaBrowser.Server.Implementations.Photos
             return DynamicImageHelpers.GetThumbCollage(items.Select(i => i.GetImagePath(ImageType.Primary) ?? i.GetImagePath(ImageType.Thumb)).ToList(),
                 FileSystem,
                 1600,
-                900);
+                900,
+                ApplicationPaths);
         }
 
         protected Task<Stream> GetSquareCollage(List<BaseItem> items)
         {
             return DynamicImageHelpers.GetSquareCollage(items.Select(i => i.GetImagePath(ImageType.Primary) ?? i.GetImagePath(ImageType.Thumb)).ToList(),
                 FileSystem,
-                800);
+                800, ApplicationPaths);
         }
 
         public string Name

+ 24 - 71
MediaBrowser.Server.Implementations/Photos/DynamicImageHelpers.cs

@@ -1,8 +1,8 @@
-using MediaBrowser.Common.IO;
+using ImageMagickSharp;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.IO;
+using System;
 using System.Collections.Generic;
-using System.Drawing;
-using System.Drawing.Drawing2D;
-using System.Drawing.Imaging;
 using System.IO;
 using System.Threading.Tasks;
 
@@ -13,7 +13,7 @@ namespace MediaBrowser.Server.Implementations.Photos
         public static async Task<Stream> GetThumbCollage(List<string> files,
             IFileSystem fileSystem,
             int width,
-            int height)
+            int height, IApplicationPaths appPaths)
         {
             if (files.Count < 3)
             {
@@ -27,16 +27,8 @@ namespace MediaBrowser.Server.Implementations.Photos
             int cellHeight = height;
             var index = 0;
 
-            var img = new Bitmap(width, height, PixelFormat.Format32bppPArgb);
-
-            using (var graphics = Graphics.FromImage(img))
+            using (var wand = new MagickWand(width, height, "transparent"))
             {
-                graphics.CompositingQuality = CompositingQuality.HighQuality;
-                graphics.SmoothingMode = SmoothingMode.HighQuality;
-                graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
-                graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
-                graphics.CompositingMode = CompositingMode.SourceCopy;
-
                 for (var row = 0; row < rows; row++)
                 {
                     for (var col = 0; col < cols; col++)
@@ -46,33 +38,24 @@ namespace MediaBrowser.Server.Implementations.Photos
 
                         if (files.Count > index)
                         {
-                            using (var fileStream = fileSystem.GetFileStream(files[index], FileMode.Open, FileAccess.Read, FileShare.Read, true))
+                            using (var innerWand = new MagickWand(files[index]))
                             {
-                                using (var memoryStream = new MemoryStream())
-                                {
-                                    await fileStream.CopyToAsync(memoryStream).ConfigureAwait(false);
-
-                                    memoryStream.Position = 0;
-
-                                    using (var imgtemp = Image.FromStream(memoryStream, true, false))
-                                    {
-                                        graphics.DrawImage(imgtemp, x, y, cellWidth, cellHeight);
-                                    }
-                                }
+                                innerWand.CurrentImage.ResizeImage(cellWidth, cellHeight);
+                                wand.CurrentImage.CompositeImage(innerWand, CompositeOperator.OverCompositeOp, x, y);
                             }
                         }
 
                         index++;
                     }
                 }
-            }
 
-            return GetStream(img);
+                return GetStream(wand, appPaths);
+            }
         }
 
         public static async Task<Stream> GetSquareCollage(List<string> files,
             IFileSystem fileSystem,
-            int size)
+            int size, IApplicationPaths appPaths)
         {
             if (files.Count < 4)
             {
@@ -85,16 +68,8 @@ namespace MediaBrowser.Server.Implementations.Photos
             int singleSize = size / 2;
             var index = 0;
 
-            var img = new Bitmap(size, size, PixelFormat.Format32bppPArgb);
-
-            using (var graphics = Graphics.FromImage(img))
+            using (var wand = new MagickWand(size, size, "transparent"))
             {
-                graphics.CompositingQuality = CompositingQuality.HighQuality;
-                graphics.SmoothingMode = SmoothingMode.HighQuality;
-                graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
-                graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
-                graphics.CompositingMode = CompositingMode.SourceCopy;
-
                 for (var row = 0; row < rows; row++)
                 {
                     for (var col = 0; col < cols; col++)
@@ -102,27 +77,18 @@ namespace MediaBrowser.Server.Implementations.Photos
                         var x = col * singleSize;
                         var y = row * singleSize;
 
-                        using (var fileStream = fileSystem.GetFileStream(files[index], FileMode.Open, FileAccess.Read, FileShare.Read, true))
+                        using (var innerWand = new MagickWand(files[index]))
                         {
-                            using (var memoryStream = new MemoryStream())
-                            {
-                                await fileStream.CopyToAsync(memoryStream).ConfigureAwait(false);
-
-                                memoryStream.Position = 0;
-
-                                using (var imgtemp = Image.FromStream(memoryStream, true, false))
-                                {
-                                    graphics.DrawImage(imgtemp, x, y, singleSize, singleSize);
-                                }
-                            }
+                            innerWand.CurrentImage.ResizeImage(singleSize, singleSize);
+                            wand.CurrentImage.CompositeImage(innerWand, CompositeOperator.OverCompositeOp, x, y);
                         }
 
                         index++;
                     }
                 }
-            }
 
-            return GetStream(img);
+                return GetStream(wand, appPaths);
+            }
         }
 
         private static Task<Stream> GetSingleImage(List<string> files, IFileSystem fileSystem)
@@ -130,29 +96,16 @@ namespace MediaBrowser.Server.Implementations.Photos
             return Task.FromResult<Stream>(fileSystem.GetFileStream(files[0], FileMode.Open, FileAccess.Read, FileShare.Read));
         }
 
-        private static Stream GetStream(Image image)
+        private static Stream GetStream(MagickWand image, IApplicationPaths appPaths)
         {
-            var ms = new MemoryStream();
+            var tempFile = Path.Combine(appPaths.TempDirectory, Guid.NewGuid().ToString("N") + ".png");
 
-            image.Save(ms, ImageFormat.Png);
+            Directory.CreateDirectory(Path.GetDirectoryName(tempFile));
 
-            ms.Position = 0;
+            image.CurrentImage.CompressionQuality = 100;
+            image.SaveImage(tempFile);
 
-            return ms;
-        }
-
-        private static async Task<Image> GetImage(string file, IFileSystem fileSystem)
-        {
-            using (var fileStream = fileSystem.GetFileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read, true))
-            {
-                var memoryStream = new MemoryStream();
-
-                await fileStream.CopyToAsync(memoryStream).ConfigureAwait(false);
-
-                memoryStream.Position = 0;
-
-                return Image.FromStream(memoryStream, true, false);
-            }
+            return File.OpenRead(tempFile);
         }
     }
 }

+ 3 - 5
MediaBrowser.Server.Implementations/Photos/DynamicImageProvider.cs

@@ -1,4 +1,5 @@
-using MediaBrowser.Common.IO;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.IO;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Entities.TV;
 using MediaBrowser.Controller.Library;
@@ -17,11 +18,8 @@ namespace MediaBrowser.Server.Implementations.Photos
         private readonly IUserManager _userManager;
         private readonly ILibraryManager _libraryManager;
 
-        public MusicDynamicImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IUserManager userManager, ILibraryManager libraryManager)
-            : base(fileSystem, providerManager)
+        public MusicDynamicImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths) : base(fileSystem, providerManager, applicationPaths)
         {
-            _userManager = userManager;
-            _libraryManager = libraryManager;
         }
 
         protected override async Task<List<BaseItem>> GetItemsWithImages(IHasImages item)

+ 3 - 3
MediaBrowser.Server.Implementations/Photos/PhotoAlbumImageProvider.cs

@@ -1,4 +1,5 @@
-using MediaBrowser.Common.IO;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.IO;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Providers;
 using System.Collections.Generic;
@@ -9,8 +10,7 @@ namespace MediaBrowser.Server.Implementations.Photos
 {
     public class PhotoAlbumImageProvider : BaseDynamicImageProvider<PhotoAlbum>, ICustomMetadataProvider<PhotoAlbum>
     {
-        public PhotoAlbumImageProvider(IFileSystem fileSystem, IProviderManager providerManager)
-            : base(fileSystem, providerManager)
+        public PhotoAlbumImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths) : base(fileSystem, providerManager, applicationPaths)
         {
         }
 

+ 3 - 2
MediaBrowser.Server.Implementations/Playlists/PlaylistImageProvider.cs

@@ -1,4 +1,5 @@
-using MediaBrowser.Common.IO;
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.IO;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Entities.Audio;
 using MediaBrowser.Controller.Entities.TV;
@@ -15,7 +16,7 @@ namespace MediaBrowser.Server.Implementations.Playlists
 {
     public class PlaylistImageProvider : BaseDynamicImageProvider<Playlist>, ICustomMetadataProvider<Playlist>
     {
-        public PlaylistImageProvider(IFileSystem fileSystem, IProviderManager providerManager) : base(fileSystem, providerManager)
+        public PlaylistImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths) : base(fileSystem, providerManager, applicationPaths)
         {
         }
 

+ 0 - 4
MediaBrowser.Server.Mono/Imazen.WebP.dll.config

@@ -1,4 +0,0 @@
-<configuration>
-  <dllmap dll="libwebp" target="./libwebp/osx/libwebp.5.dylib" os="osx"/>
-  <dllmap dll="libwebp" target="libwebp.so.5" os="linux"/>
-</configuration>

+ 0 - 7
MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj

@@ -137,10 +137,6 @@
     </ProjectReference>
   </ItemGroup>
   <ItemGroup>
-    <None Include="..\ThirdParty\libwebp\osx\libwebp.5.dylib">
-      <Link>libwebp\osx\libwebp.5.dylib</Link>
-      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
-    </None>
     <None Include="..\ThirdParty\MediaInfo\osx\libmediainfo.dylib">
       <Link>MediaInfo\osx\libmediainfo.dylib</Link>
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
@@ -154,9 +150,6 @@
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
     </None>
     <None Include="app.config" />
-    <None Include="Imazen.WebP.dll.config">
-      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
-    </None>
     <None Include="MediaBrowser.MediaInfo.dll.config">
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
     </None>

+ 1 - 1
MediaBrowser.Server.Startup.Common/ApplicationHost.cs

@@ -439,7 +439,7 @@ namespace MediaBrowser.Server.Startup.Common
             var innerProgress = new ActionableProgress<double>();
             innerProgress.RegisterAction(p => progress.Report((.75 * p) + 15));
 
-            ImageProcessor = new ImageProcessor(LogManager.GetLogger("ImageProcessor"), ServerConfigurationManager.ApplicationPaths, FileSystemManager, JsonSerializer, MediaEncoder);
+            ImageProcessor = new ImageProcessor(LogManager.GetLogger("ImageProcessor"), ServerConfigurationManager.ApplicationPaths, FileSystemManager, JsonSerializer);
             RegisterSingleInstance(ImageProcessor);
 
             TVSeriesManager = new TVSeriesManager(UserManager, UserDataManager, LibraryManager);

+ 60 - 4
MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj

@@ -167,14 +167,70 @@
       <Link>x86\SQLite.Interop.dll</Link>
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
     </Content>
-    <Content Include="..\ThirdParty\libwebp\windows\x86\libwebp.dll">
-      <Link>libwebp.dll</Link>
-      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
-    </Content>
     <Content Include="..\ThirdParty\MediaInfo\windows\x86\MediaInfo.dll">
       <Link>MediaInfo.dll</Link>
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
     </Content>
+    <Content Include="CORE_RL_bzlib_.dll">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </Content>
+    <Content Include="CORE_RL_exr_.dll">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </Content>
+    <Content Include="CORE_RL_glib_.dll">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </Content>
+    <Content Include="CORE_RL_jbig_.dll">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </Content>
+    <Content Include="CORE_RL_jp2_.dll">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </Content>
+    <Content Include="CORE_RL_jpeg_.dll">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </Content>
+    <Content Include="CORE_RL_lcms_.dll">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </Content>
+    <Content Include="CORE_RL_librsvg_.dll">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </Content>
+    <Content Include="CORE_RL_libxml_.dll">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </Content>
+    <Content Include="CORE_RL_lqr_.dll">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </Content>
+    <Content Include="CORE_RL_Magick++_.dll">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </Content>
+    <Content Include="CORE_RL_magick_.dll">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </Content>
+    <Content Include="CORE_RL_openjpeg_.dll">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </Content>
+    <Content Include="CORE_RL_pango_.dll">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </Content>
+    <Content Include="CORE_RL_png_.dll">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </Content>
+    <Content Include="CORE_RL_tiff_.dll">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </Content>
+    <Content Include="CORE_RL_ttf_.dll">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </Content>
+    <Content Include="CORE_RL_wand_.dll">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </Content>
+    <Content Include="CORE_RL_webp_.dll">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </Content>
+    <Content Include="CORE_RL_zlib_.dll">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </Content>
     <Content Include="Resources\Images\Icon.ico" />
     <Content Include="Resources\Images\mb3logo800.png" />
   </ItemGroup>