diff options
| author | Luke Pulverenti <luke.pulverenti@gmail.com> | 2015-04-08 10:38:02 -0400 |
|---|---|---|
| committer | Luke Pulverenti <luke.pulverenti@gmail.com> | 2015-04-08 10:38:02 -0400 |
| commit | 4820fe80971c83cde97a445e45b9e0b1952b0d90 (patch) | |
| tree | 4009bb413065f08471a9c7546e4330fe1d8713c9 /MediaBrowser.Server.Implementations | |
| parent | 78e96917e12abb963301957607da4a738f27df58 (diff) | |
added drawing project
Diffstat (limited to 'MediaBrowser.Server.Implementations')
10 files changed, 80 insertions, 689 deletions
diff --git a/MediaBrowser.Server.Implementations/Collections/CollectionImageProvider.cs b/MediaBrowser.Server.Implementations/Collections/CollectionImageProvider.cs index 80a7c50d1..f5ddbdb78 100644 --- a/MediaBrowser.Server.Implementations/Collections/CollectionImageProvider.cs +++ b/MediaBrowser.Server.Implementations/Collections/CollectionImageProvider.cs @@ -1,5 +1,6 @@ using MediaBrowser.Common.Configuration; using MediaBrowser.Common.IO; +using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Entities.Movies; @@ -16,7 +17,7 @@ namespace MediaBrowser.Server.Implementations.Collections { public class CollectionImageProvider : BaseDynamicImageProvider<BoxSet> { - public CollectionImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths) : base(fileSystem, providerManager, applicationPaths) + public CollectionImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths, IImageProcessor imageProcessor) : base(fileSystem, providerManager, applicationPaths, imageProcessor) { } diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/PhotoAlbumResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/PhotoAlbumResolver.cs index acae5b801..e7f239780 100644 --- a/MediaBrowser.Server.Implementations/Library/Resolvers/PhotoAlbumResolver.cs +++ b/MediaBrowser.Server.Implementations/Library/Resolvers/PhotoAlbumResolver.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Drawing; +using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Resolvers; using MediaBrowser.Model.Entities; @@ -10,6 +11,12 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers { public class PhotoAlbumResolver : FolderResolver<PhotoAlbum> { + private readonly IImageProcessor _imageProcessor; + public PhotoAlbumResolver(IImageProcessor imageProcessor) + { + _imageProcessor = imageProcessor; + } + /// <summary> /// Resolves the specified args. /// </summary> @@ -32,9 +39,9 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers return null; } - private static bool HasPhotos(ItemResolveArgs args) + private bool HasPhotos(ItemResolveArgs args) { - return args.FileSystemChildren.Any(i => ((i.Attributes & FileAttributes.Directory) != FileAttributes.Directory) && PhotoResolver.IsImageFile(i.FullName)); + return args.FileSystemChildren.Any(i => ((i.Attributes & FileAttributes.Directory) != FileAttributes.Directory) && PhotoResolver.IsImageFile(i.FullName, _imageProcessor)); } public override ResolverPriority Priority diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/PhotoResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/PhotoResolver.cs index b714e968b..407aac53d 100644 --- a/MediaBrowser.Server.Implementations/Library/Resolvers/PhotoResolver.cs +++ b/MediaBrowser.Server.Implementations/Library/Resolvers/PhotoResolver.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Drawing; +using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Model.Entities; using System; @@ -9,6 +10,12 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers { public class PhotoResolver : ItemResolver<Photo> { + private readonly IImageProcessor _imageProcessor; + public PhotoResolver(IImageProcessor imageProcessor) + { + _imageProcessor = imageProcessor; + } + /// <summary> /// Resolves the specified args. /// </summary> @@ -19,7 +26,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers // Must be an image file within a photo collection if (string.Equals(args.GetCollectionType(), CollectionType.Photos, StringComparison.OrdinalIgnoreCase) && !args.IsDirectory && - IsImageFile(args.Path)) + IsImageFile(args.Path, _imageProcessor)) { return new Photo { @@ -30,9 +37,6 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers return null; } - // Some common file name extensions for RAW picture files include: .cr2, .crw, .dng, .nef, .orf, .rw2, .pef, .arw, .sr2, .srf, and .tif. - protected static string[] ImageExtensions = { ".tiff", ".jpeg", ".jpg", ".png", ".aiff", ".cr2", ".crw", ".dng", ".nef", ".orf", ".pef", ".arw", ".webp" }; - private static readonly string[] IgnoreFiles = { "folder", @@ -43,12 +47,12 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers "poster" }; - internal static bool IsImageFile(string path) + internal static bool IsImageFile(string path, IImageProcessor imageProcessor) { var filename = Path.GetFileNameWithoutExtension(path) ?? string.Empty; return !IgnoreFiles.Contains(filename, StringComparer.OrdinalIgnoreCase) - && ImageExtensions.Contains(Path.GetExtension(path) ?? string.Empty, StringComparer.OrdinalIgnoreCase); + && imageProcessor.SupportedInputFormats.Contains((Path.GetExtension(path) ?? string.Empty).TrimStart('.'), StringComparer.OrdinalIgnoreCase); } } diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index c09ce8663..6f95686e1 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -242,8 +242,6 @@ <Compile Include="Persistence\SqliteShrinkMemoryTimer.cs" /> <Compile Include="Persistence\TypeMapper.cs" /> <Compile Include="Photos\BaseDynamicImageProvider.cs" /> - <Compile Include="Photos\DynamicImageHelpers.cs" /> - <Compile Include="UserViews\StripCollageBuilder.cs" /> <Compile Include="Playlists\ManualPlaylistsFolder.cs" /> <Compile Include="Photos\PhotoAlbumImageProvider.cs" /> <Compile Include="Playlists\PlaylistImageProvider.cs" /> diff --git a/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs b/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs index 3101897d2..1e6189beb 100644 --- a/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs +++ b/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs @@ -1,13 +1,13 @@ using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Extensions; using MediaBrowser.Common.IO; +using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Playlists; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Drawing; using MediaBrowser.Model.Entities; -using MediaBrowser.Server.Implementations.UserViews; using System; using System.Collections.Generic; using System.IO; @@ -23,12 +23,14 @@ namespace MediaBrowser.Server.Implementations.Photos protected IFileSystem FileSystem { get; private set; } protected IProviderManager ProviderManager { get; private set; } protected IApplicationPaths ApplicationPaths { get; private set; } + protected IImageProcessor ImageProcessor { get; set; } - protected BaseDynamicImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths) + protected BaseDynamicImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths, IImageProcessor imageProcessor) { ApplicationPaths = applicationPaths; ProviderManager = providerManager; FileSystem = fileSystem; + ImageProcessor = imageProcessor; } public virtual bool Supports(IHasImages item) @@ -77,7 +79,7 @@ namespace MediaBrowser.Server.Implementations.Photos string cacheKey, CancellationToken cancellationToken) { - var stream = await CreateImageAsync(item, itemsWithImages, imageType, 0).ConfigureAwait(false); + var stream = CreateImageAsync(item, itemsWithImages, imageType, 0); if (stream == null) { @@ -113,7 +115,7 @@ namespace MediaBrowser.Server.Implementations.Photos var items = await GetItemsWithImages(item).ConfigureAwait(false); var cacheKey = GetConfigurationCacheKey(items, item.Name); - var result = await CreateImageAsync(item, items, type, 0).ConfigureAwait(false); + var result = CreateImageAsync(item, items, type, 0); return new DynamicImageResponse { @@ -126,7 +128,7 @@ namespace MediaBrowser.Server.Implementations.Photos protected abstract Task<List<BaseItem>> GetItemsWithImages(IHasImages item); - private const string Version = "19"; + private const string Version = "20"; protected string GetConfigurationCacheKey(List<BaseItem> items, string itemName) { var parts = Version + "_" + (itemName ?? string.Empty) + "_" + @@ -135,32 +137,53 @@ namespace MediaBrowser.Server.Implementations.Photos return parts.GetMD5().ToString("N"); } - protected Task<Stream> GetThumbCollage(IHasImages primaryItem, List<BaseItem> items) + protected Stream GetThumbCollage(IHasImages primaryItem, List<BaseItem> items) { - var stream = new StripCollageBuilder(ApplicationPaths).BuildThumbCollage(GetStripCollageImagePaths(items), 960, 540, true, primaryItem.Name); - - return Task.FromResult(stream); + return GetThumbCollage(primaryItem, items, 960, 540, true, primaryItem.Name); } - private IEnumerable<String> GetStripCollageImagePaths(IEnumerable<BaseItem> items) + protected virtual IEnumerable<String> GetStripCollageImagePaths(IHasImages primaryItem, IEnumerable<BaseItem> items) { return items .Select(i => i.GetImagePath(ImageType.Primary) ?? i.GetImagePath(ImageType.Thumb)) .Where(i => !string.IsNullOrWhiteSpace(i)); } - protected Task<Stream> GetPosterCollage(IHasImages primaryItem, List<BaseItem> items) + protected Stream GetPosterCollage(IHasImages primaryItem, List<BaseItem> items) { - var stream = new StripCollageBuilder(ApplicationPaths).BuildPosterCollage(GetStripCollageImagePaths(items), 600, 900, true, primaryItem.Name); + var path = CreateCollage(primaryItem, items, 600, 900, true, primaryItem.Name); + return FileSystem.GetFileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read); + } + + protected Stream GetSquareCollage(IHasImages primaryItem, List<BaseItem> items) + { + var path = CreateCollage(primaryItem, items, 800, 800, true, primaryItem.Name); + return FileSystem.GetFileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read); + } - return Task.FromResult(stream); + protected Stream GetThumbCollage(IHasImages primaryItem, List<BaseItem> items, int width, int height, bool drawText, string text) + { + var path = CreateCollage(primaryItem, items, width, height, drawText, text); + return FileSystem.GetFileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read); } - protected Task<Stream> GetSquareCollage(IHasImages primaryItem, List<BaseItem> items) + private string CreateCollage(IHasImages primaryItem, List<BaseItem> items, int width, int height, bool drawText, string text) { - var stream = new StripCollageBuilder(ApplicationPaths).BuildSquareCollage(GetStripCollageImagePaths(items), 800, 800, true, primaryItem.Name); + var outputPath = Path.Combine(ApplicationPaths.TempDirectory, Guid.NewGuid() + ".png"); + Directory.CreateDirectory(Path.GetDirectoryName(outputPath)); + + var options = new ImageCollageOptions + { + Height = height, + Width = width, + OutputPath = outputPath, + Text = drawText ? text : null, + InputPaths = GetStripCollageImagePaths(primaryItem, items).ToArray() + }; + + ImageProcessor.CreateImageCollage(options); - return Task.FromResult(stream); + return outputPath; } public string Name @@ -168,7 +191,7 @@ namespace MediaBrowser.Server.Implementations.Photos get { return "Dynamic Image Provider"; } } - protected virtual async Task<Stream> CreateImageAsync(IHasImages item, + protected virtual Stream CreateImageAsync(IHasImages item, List<BaseItem> itemsWithImages, ImageType imageType, int imageIndex) @@ -180,14 +203,14 @@ namespace MediaBrowser.Server.Implementations.Photos if (imageType == ImageType.Thumb) { - return await GetThumbCollage(item, itemsWithImages).ConfigureAwait(false); + return GetThumbCollage(item, itemsWithImages); } if (imageType == ImageType.Primary) { return item is PhotoAlbum || item is Playlist ? - await GetSquareCollage(item, itemsWithImages).ConfigureAwait(false) : - await GetPosterCollage(item, itemsWithImages).ConfigureAwait(false); + GetSquareCollage(item, itemsWithImages) : + GetPosterCollage(item, itemsWithImages); } throw new ArgumentException("Unexpected image type"); diff --git a/MediaBrowser.Server.Implementations/Photos/DynamicImageHelpers.cs b/MediaBrowser.Server.Implementations/Photos/DynamicImageHelpers.cs deleted file mode 100644 index 7f8435097..000000000 --- a/MediaBrowser.Server.Implementations/Photos/DynamicImageHelpers.cs +++ /dev/null @@ -1,132 +0,0 @@ -using ImageMagickSharp; -using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.IO; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading.Tasks; - -namespace MediaBrowser.Server.Implementations.Photos -{ - public static class DynamicImageHelpers - { - public static async Task<Stream> GetThumbCollage(List<string> files, - IFileSystem fileSystem, - int width, - int height, IApplicationPaths appPaths) - { - if (files.Any(string.IsNullOrWhiteSpace)) - { - throw new ArgumentException("Empty file found in files list"); - } - - if (files.Count == 0) - { - return null; - } - - if (files.Count < 3) - { - return await GetSingleImage(files, fileSystem).ConfigureAwait(false); - } - - const int rows = 1; - const int cols = 3; - - int cellWidth = 2 * (width / 3); - int cellHeight = height; - var index = 0; - - using (var wand = new MagickWand(width, height, new PixelWand(ColorName.None, 1))) - { - for (var row = 0; row < rows; row++) - { - for (var col = 0; col < cols; col++) - { - var x = col * (cellWidth / 2); - var y = row * cellHeight; - - if (files.Count > index) - { - using (var innerWand = new MagickWand(files[index])) - { - innerWand.CurrentImage.ResizeImage(cellWidth, cellHeight); - wand.CurrentImage.CompositeImage(innerWand, CompositeOperator.OverCompositeOp, x, y); - } - } - - index++; - } - } - - return GetStream(wand, appPaths); - } - } - - public static async Task<Stream> GetSquareCollage(List<string> files, - IFileSystem fileSystem, - int size, IApplicationPaths appPaths) - { - if (files.Any(string.IsNullOrWhiteSpace)) - { - throw new ArgumentException("Empty file found in files list"); - } - - if (files.Count == 0) - { - return null; - } - - if (files.Count < 4) - { - return await GetSingleImage(files, fileSystem).ConfigureAwait(false); - } - - const int rows = 2; - const int cols = 2; - - int singleSize = size / 2; - var index = 0; - - using (var wand = new MagickWand(size, size, new PixelWand(ColorName.None, 1))) - { - for (var row = 0; row < rows; row++) - { - for (var col = 0; col < cols; col++) - { - var x = col * singleSize; - var y = row * singleSize; - - using (var innerWand = new MagickWand(files[index])) - { - innerWand.CurrentImage.ResizeImage(singleSize, singleSize); - wand.CurrentImage.CompositeImage(innerWand, CompositeOperator.OverCompositeOp, x, y); - } - - index++; - } - } - - return GetStream(wand, appPaths); - } - } - - private static Task<Stream> GetSingleImage(List<string> files, IFileSystem fileSystem) - { - return Task.FromResult<Stream>(fileSystem.GetFileStream(files[0], FileMode.Open, FileAccess.Read, FileShare.Read)); - } - - internal static Stream GetStream(MagickWand image, IApplicationPaths appPaths) - { - var tempFile = Path.Combine(appPaths.TempDirectory, Guid.NewGuid().ToString("N") + ".png"); - - Directory.CreateDirectory(Path.GetDirectoryName(tempFile)); - - image.CurrentImage.CompressionQuality = 100; - image.SaveImage(tempFile); - - return File.OpenRead(tempFile); - } - } -} diff --git a/MediaBrowser.Server.Implementations/Photos/PhotoAlbumImageProvider.cs b/MediaBrowser.Server.Implementations/Photos/PhotoAlbumImageProvider.cs index ea0a93a55..eda4d8cc1 100644 --- a/MediaBrowser.Server.Implementations/Photos/PhotoAlbumImageProvider.cs +++ b/MediaBrowser.Server.Implementations/Photos/PhotoAlbumImageProvider.cs @@ -1,5 +1,6 @@ using MediaBrowser.Common.Configuration; using MediaBrowser.Common.IO; +using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Providers; using System.Collections.Generic; @@ -10,7 +11,7 @@ namespace MediaBrowser.Server.Implementations.Photos { public class PhotoAlbumImageProvider : BaseDynamicImageProvider<PhotoAlbum> { - public PhotoAlbumImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths) : base(fileSystem, providerManager, applicationPaths) + public PhotoAlbumImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths, IImageProcessor imageProcessor) : base(fileSystem, providerManager, applicationPaths, imageProcessor) { } diff --git a/MediaBrowser.Server.Implementations/Playlists/PlaylistImageProvider.cs b/MediaBrowser.Server.Implementations/Playlists/PlaylistImageProvider.cs index 81f9438b9..dcd9d21ea 100644 --- a/MediaBrowser.Server.Implementations/Playlists/PlaylistImageProvider.cs +++ b/MediaBrowser.Server.Implementations/Playlists/PlaylistImageProvider.cs @@ -1,5 +1,6 @@ using MediaBrowser.Common.Configuration; using MediaBrowser.Common.IO; +using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Entities.TV; @@ -16,7 +17,7 @@ namespace MediaBrowser.Server.Implementations.Playlists { public class PlaylistImageProvider : BaseDynamicImageProvider<Playlist> { - public PlaylistImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths) : base(fileSystem, providerManager, applicationPaths) + public PlaylistImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths, IImageProcessor imageProcessor) : base(fileSystem, providerManager, applicationPaths, imageProcessor) { } diff --git a/MediaBrowser.Server.Implementations/UserViews/DynamicImageProvider.cs b/MediaBrowser.Server.Implementations/UserViews/DynamicImageProvider.cs index 7bcbbd6a8..fc05f3169 100644 --- a/MediaBrowser.Server.Implementations/UserViews/DynamicImageProvider.cs +++ b/MediaBrowser.Server.Implementations/UserViews/DynamicImageProvider.cs @@ -1,5 +1,6 @@ using MediaBrowser.Common.Configuration; using MediaBrowser.Common.IO; +using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Entities.TV; @@ -22,8 +23,7 @@ namespace MediaBrowser.Server.Implementations.UserViews private readonly IUserManager _userManager; private readonly ILibraryManager _libraryManager; - public DynamicImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths, IUserManager userManager, ILibraryManager libraryManager) - : base(fileSystem, providerManager, applicationPaths) + public DynamicImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths, IImageProcessor imageProcessor, IUserManager userManager, ILibraryManager libraryManager) : base(fileSystem, providerManager, applicationPaths, imageProcessor) { _userManager = userManager; _libraryManager = libraryManager; @@ -238,7 +238,7 @@ namespace MediaBrowser.Server.Implementations.UserViews return collectionStripViewTypes.Contains(view.ViewType ?? string.Empty); } - protected override async Task<Stream> CreateImageAsync(IHasImages item, List<BaseItem> itemsWithImages, ImageType imageType, int imageIndex) + protected override Stream CreateImageAsync(IHasImages item, List<BaseItem> itemsWithImages, ImageType imageType, int imageIndex) { var view = (UserView)item; if (imageType == ImageType.Primary && IsUsingCollectionStrip(view)) @@ -248,15 +248,17 @@ namespace MediaBrowser.Server.Implementations.UserViews return null; } - return new StripCollageBuilder(ApplicationPaths).BuildThumbCollage(GetStripCollageImagePaths(itemsWithImages, view.ViewType), 960, 540, false, item.Name); + return GetThumbCollage(item, itemsWithImages, 960, 540, false, item.Name); } - return await base.CreateImageAsync(item, itemsWithImages, imageType, imageIndex); + return base.CreateImageAsync(item, itemsWithImages, imageType, imageIndex); } - private IEnumerable<String> GetStripCollageImagePaths(IEnumerable<BaseItem> items, string viewType) + protected override IEnumerable<String> GetStripCollageImagePaths(IHasImages primaryItem, IEnumerable<BaseItem> items) { - if (string.Equals(viewType, CollectionType.LiveTv, StringComparison.OrdinalIgnoreCase)) + var userView = primaryItem as UserView; + + if (userView != null && string.Equals(userView.ViewType, CollectionType.LiveTv, StringComparison.OrdinalIgnoreCase)) { var list = new List<string>(); for (int i = 1; i <= 8; i++) @@ -266,9 +268,7 @@ namespace MediaBrowser.Server.Implementations.UserViews return list; } - return items - .Select(i => i.GetImagePath(ImageType.Primary) ?? i.GetImagePath(ImageType.Thumb)) - .Where(i => !string.IsNullOrWhiteSpace(i)); + return base.GetStripCollageImagePaths(primaryItem, items); } private string ExtractLiveTvResource(string name, IApplicationPaths paths) diff --git a/MediaBrowser.Server.Implementations/UserViews/StripCollageBuilder.cs b/MediaBrowser.Server.Implementations/UserViews/StripCollageBuilder.cs deleted file mode 100644 index a0212c3c7..000000000 --- a/MediaBrowser.Server.Implementations/UserViews/StripCollageBuilder.cs +++ /dev/null @@ -1,512 +0,0 @@ -using ImageMagickSharp; -using MediaBrowser.Common.Configuration; -using MediaBrowser.Server.Implementations.Drawing; -using MediaBrowser.Server.Implementations.Photos; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; - -namespace MediaBrowser.Server.Implementations.UserViews -{ - public class StripCollageBuilder - { - private readonly IApplicationPaths _appPaths; - - public StripCollageBuilder(IApplicationPaths appPaths) - { - _appPaths = appPaths; - } - - public Stream BuildPosterCollage(IEnumerable<string> paths, int width, int height, bool renderWithText, string text) - { - if (renderWithText) - { - using (var wand = BuildPosterCollageWandWithText(paths, text, width, height)) - { - return DynamicImageHelpers.GetStream(wand, _appPaths); - } - } - using (var wand = BuildPosterCollageWand(paths, width, height)) - { - return DynamicImageHelpers.GetStream(wand, _appPaths); - } - } - - public Stream BuildSquareCollage(IEnumerable<string> paths, int width, int height, bool renderWithText, string text) - { - if (renderWithText) - { - using (var wand = BuildSquareCollageWandWithText(paths, text, width, height)) - { - return DynamicImageHelpers.GetStream(wand, _appPaths); - } - } - using (var wand = BuildSquareCollageWand(paths, width, height)) - { - return DynamicImageHelpers.GetStream(wand, _appPaths); - } - } - - public Stream BuildThumbCollage(IEnumerable<string> paths, int width, int height, bool renderWithText, string text) - { - if (renderWithText) - { - using (var wand = BuildThumbCollageWandWithText(paths, text, width, height)) - { - return DynamicImageHelpers.GetStream(wand, _appPaths); - } - } - using (var wand = BuildThumbCollageWand(paths, width, height)) - { - return DynamicImageHelpers.GetStream(wand, _appPaths); - } - } - - private string[] ProjectPaths(IEnumerable<string> paths, int count) - { - var clone = paths.ToList(); - var list = new List<string>(); - - while (list.Count < count) - { - foreach (var path in clone) - { - list.Add(path); - - if (list.Count >= count) - { - break; - } - } - } - - return list.Take(count).ToArray(); - } - - private MagickWand BuildThumbCollageWandWithText(IEnumerable<string> paths, string text, int width, int height) - { - var inputPaths = ProjectPaths(paths, 8); - using (var wandImages = new MagickWand(inputPaths)) - { - var wand = new MagickWand(width, height); - wand.OpenImage("gradient:#111111-#111111"); - using (var draw = new DrawingWand()) - { - using (var fcolor = new PixelWand(ColorName.White)) - { - draw.FillColor = fcolor; - draw.Font = MontserratLightFont; - draw.FontSize = 60; - draw.FontWeight = FontWeightType.LightStyle; - draw.TextAntialias = true; - } - - var fontMetrics = wand.QueryFontMetrics(draw, text); - var textContainerY = Convert.ToInt32(height * .165); - wand.CurrentImage.AnnotateImage(draw, (width - fontMetrics.TextWidth) / 2, textContainerY, 0.0, text); - - var iSlice = Convert.ToInt32(width * .1166666667); - int iTrans = Convert.ToInt32(height * 0.2); - int iHeight = Convert.ToInt32(height * 0.46296296296296296296296296296296); - var horizontalImagePadding = Convert.ToInt32(width * 0.0125); - - foreach (var element in wandImages.ImageList) - { - int iWidth = (int)Math.Abs(iHeight * element.Width / element.Height); - element.Gravity = GravityType.CenterGravity; - element.BackgroundColor = new PixelWand("none", 1); - 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.DstInCompositeOp, 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 * 0.26851851851851851851851851851852)); - } - } - } - } - } - } - - return wand; - } - } - - private MagickWand BuildPosterCollageWand(IEnumerable<string> paths, int width, int height) - { - var inputPaths = ProjectPaths(paths, 4); - using (var wandImages = new MagickWand(inputPaths)) - { - var wand = new MagickWand(width, height); - wand.OpenImage("gradient:#111111-#111111"); - using (var draw = new DrawingWand()) - { - var iSlice = Convert.ToInt32(width * 0.225); - int iTrans = Convert.ToInt32(height * .25); - int iHeight = Convert.ToInt32(height * .65); - var horizontalImagePadding = Convert.ToInt32(width * 0.0275); - - 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); - - 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)); - } - } - } - } - } - } - - return wand; - } - } - - private MagickWand BuildPosterCollageWandWithText(IEnumerable<string> paths, string label, int width, int height) - { - var inputPaths = ProjectPaths(paths, 4); - using (var wandImages = new MagickWand(inputPaths)) - { - var wand = new MagickWand(width, height); - wand.OpenImage("gradient:#111111-#111111"); - using (var draw = new DrawingWand()) - { - using (var fcolor = new PixelWand(ColorName.White)) - { - draw.FillColor = fcolor; - draw.Font = MontserratLightFont; - draw.FontSize = 60; - draw.FontWeight = FontWeightType.LightStyle; - draw.TextAntialias = true; - } - - var fontMetrics = wand.QueryFontMetrics(draw, label); - var textContainerY = Convert.ToInt32(height * .165); - wand.CurrentImage.AnnotateImage(draw, (width - fontMetrics.TextWidth) / 2, textContainerY, 0.0, label); - - var iSlice = Convert.ToInt32(width * 0.225); - int iTrans = Convert.ToInt32(height * 0.2); - int iHeight = Convert.ToInt32(height * 0.46296296296296296296296296296296); - var horizontalImagePadding = Convert.ToInt32(width * 0.0275); - - foreach (var element in wandImages.ImageList) - { - int iWidth = (int)Math.Abs(iHeight * element.Width / element.Height); - element.Gravity = GravityType.CenterGravity; - element.BackgroundColor = new PixelWand("none", 1); - 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.DstInCompositeOp, 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 * 0.26851851851851851851851851851852)); - } - } - } - } - } - } - - return wand; - } - } - - private MagickWand BuildThumbCollageWand(IEnumerable<string> paths, int width, int height) - { - var inputPaths = ProjectPaths(paths, 8); - using (var wandImages = new MagickWand(inputPaths)) - { - var wand = new MagickWand(width, height); - wand.OpenImage("gradient:#111111-#111111"); - using (var draw = new DrawingWand()) - { - var iSlice = Convert.ToInt32(width * .1166666667); - int iTrans = Convert.ToInt32(height * .25); - int iHeight = Convert.ToInt32(height * .62); - var horizontalImagePadding = Convert.ToInt32(width * 0.0125); - - 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); - - 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 * .085)); - } - } - } - } - } - } - - return wand; - } - } - - private MagickWand BuildSquareCollageWand(IEnumerable<string> paths, int width, int height) - { - var inputPaths = ProjectPaths(paths, 4); - using (var wandImages = new MagickWand(inputPaths)) - { - var wand = new MagickWand(width, height); - wand.OpenImage("gradient:#111111-#111111"); - using (var draw = new DrawingWand()) - { - var iSlice = Convert.ToInt32(width * .225); - int iTrans = Convert.ToInt32(height * .25); - int iHeight = Convert.ToInt32(height * .63); - var horizontalImagePadding = Convert.ToInt32(width * 0.02); - - 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); - - 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 * .07)); - } - } - } - } - } - } - - return wand; - } - } - - private MagickWand BuildSquareCollageWandWithText(IEnumerable<string> paths, string label, int width, int height) - { - var inputPaths = ProjectPaths(paths, 4); - using (var wandImages = new MagickWand(inputPaths)) - { - var wand = new MagickWand(width, height); - wand.OpenImage("gradient:#111111-#111111"); - using (var draw = new DrawingWand()) - { - using (var fcolor = new PixelWand(ColorName.White)) - { - draw.FillColor = fcolor; - draw.Font = MontserratLightFont; - draw.FontSize = 60; - draw.FontWeight = FontWeightType.LightStyle; - draw.TextAntialias = true; - } - - var fontMetrics = wand.QueryFontMetrics(draw, label); - var textContainerY = Convert.ToInt32(height * .165); - wand.CurrentImage.AnnotateImage(draw, (width - fontMetrics.TextWidth) / 2, textContainerY, 0.0, label); - - var iSlice = Convert.ToInt32(width * .225); - int iTrans = Convert.ToInt32(height * 0.2); - int iHeight = Convert.ToInt32(height * 0.46296296296296296296296296296296); - var horizontalImagePadding = Convert.ToInt32(width * 0.02); - - foreach (var element in wandImages.ImageList) - { - int iWidth = (int)Math.Abs(iHeight * element.Width / element.Height); - element.Gravity = GravityType.CenterGravity; - element.BackgroundColor = new PixelWand("none", 1); - 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.DstInCompositeOp, 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 * 0.26851851851851851851851851851852)); - } - } - } - } - } - } - - return wand; - } - } - - private string MontserratLightFont - { - get { return PlayedIndicatorDrawer.ExtractFont("MontserratLight.otf", _appPaths); } - } - } -} |
