From 527f4887e91f33009be814a29313891c0827c8a7 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 2 Apr 2015 13:44:44 -0400 Subject: [PATCH] add new dynamic images --- .../Photos/BaseDynamicImageProvider.cs | 33 ++++-- .../UserViews/DynamicImageProvider.cs | 2 +- .../UserViews/StripCollageBuilder.cs | 105 ++++++++++++++++-- 3 files changed, 123 insertions(+), 17 deletions(-) diff --git a/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs b/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs index 0b5ffc903b..401234ac50 100644 --- a/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs +++ b/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs @@ -3,17 +3,17 @@ using MediaBrowser.Common.Extensions; using MediaBrowser.Common.IO; 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.Globalization; using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; -using MediaBrowser.Server.Implementations.UserViews; namespace MediaBrowser.Server.Implementations.Photos { @@ -126,7 +126,7 @@ namespace MediaBrowser.Server.Implementations.Photos protected abstract Task> GetItemsWithImages(IHasImages item); - private const string Version = "5"; + private const string Version = "9"; protected string GetConfigurationCacheKey(List items, string itemName) { var parts = Version + "_" + (itemName ?? string.Empty) + "_" + @@ -137,7 +137,7 @@ namespace MediaBrowser.Server.Implementations.Photos protected Task GetThumbCollage(IHasImages primaryItem, List items) { - var stream = new StripCollageBuilder(ApplicationPaths).BuildThumbCollage(GetStripCollageImagePaths(items), primaryItem.Name, 960, 540); + var stream = new StripCollageBuilder(ApplicationPaths).BuildThumbCollage(GetStripCollageImagePaths(items), 960, 540, true, primaryItem.Name); return Task.FromResult(stream); } @@ -149,9 +149,16 @@ namespace MediaBrowser.Server.Implementations.Photos .Where(i => !string.IsNullOrWhiteSpace(i)); } + protected Task GetPosterCollage(IHasImages primaryItem, List items) + { + var stream = new StripCollageBuilder(ApplicationPaths).BuildSquareCollage(GetStripCollageImagePaths(items), 800, 800, true, primaryItem.Name); + + return Task.FromResult(stream); + } + protected Task GetSquareCollage(IHasImages primaryItem, List items) { - var stream = new StripCollageBuilder(ApplicationPaths).BuildSquareCollage(GetStripCollageImagePaths(items), primaryItem.Name, 800, 800); + var stream = new StripCollageBuilder(ApplicationPaths).BuildSquareCollage(GetStripCollageImagePaths(items), 800, 800, true, primaryItem.Name); return Task.FromResult(stream); } @@ -171,9 +178,19 @@ namespace MediaBrowser.Server.Implementations.Photos return null; } - return imageType == ImageType.Thumb ? - await GetThumbCollage(item, itemsWithImages).ConfigureAwait(false) : - await GetSquareCollage(item, itemsWithImages).ConfigureAwait(false); + if (imageType == ImageType.Thumb) + { + return await GetThumbCollage(item, itemsWithImages).ConfigureAwait(false); + } + + if (imageType == ImageType.Primary) + { + return item is PhotoAlbum || item is Playlist ? + await GetSquareCollage(item, itemsWithImages).ConfigureAwait(false) : + await GetPosterCollage(item, itemsWithImages).ConfigureAwait(false); + } + + throw new ArgumentException("Unexpected image type"); } public bool HasChanged(IHasMetadata item, IDirectoryService directoryService, DateTime date) diff --git a/MediaBrowser.Server.Implementations/UserViews/DynamicImageProvider.cs b/MediaBrowser.Server.Implementations/UserViews/DynamicImageProvider.cs index 84bab19752..253bf36a26 100644 --- a/MediaBrowser.Server.Implementations/UserViews/DynamicImageProvider.cs +++ b/MediaBrowser.Server.Implementations/UserViews/DynamicImageProvider.cs @@ -248,7 +248,7 @@ namespace MediaBrowser.Server.Implementations.UserViews return null; } - return new StripCollageBuilder(ApplicationPaths).BuildThumbCollage(GetStripCollageImagePaths(itemsWithImages, view.ViewType), item.Name, 960, 540); + return new StripCollageBuilder(ApplicationPaths).BuildThumbCollage(GetStripCollageImagePaths(itemsWithImages, view.ViewType), 960, 540, false, item.Name); } return await base.CreateImageAsync(item, itemsWithImages, imageType, imageIndex); diff --git a/MediaBrowser.Server.Implementations/UserViews/StripCollageBuilder.cs b/MediaBrowser.Server.Implementations/UserViews/StripCollageBuilder.cs index 10173c9f89..7dbfbb0156 100644 --- a/MediaBrowser.Server.Implementations/UserViews/StripCollageBuilder.cs +++ b/MediaBrowser.Server.Implementations/UserViews/StripCollageBuilder.cs @@ -18,19 +18,39 @@ namespace MediaBrowser.Server.Implementations.UserViews _appPaths = appPaths; } - public Stream BuildSquareCollage(IEnumerable paths, string text, int width, int height) + public Stream BuildSquareCollage(IEnumerable paths, int width, int height, bool renderWithText, string text) { - using (var wand = BuildSquareCollageWand(paths, width, height)) + if (renderWithText) { - return DynamicImageHelpers.GetStream(wand, _appPaths); + using (var wand = BuildSquareCollageWandWithText(paths, text, width, height)) + { + return DynamicImageHelpers.GetStream(wand, _appPaths); + } + } + else + { + using (var wand = BuildSquareCollageWand(paths, width, height)) + { + return DynamicImageHelpers.GetStream(wand, _appPaths); + } } } - public Stream BuildThumbCollage(IEnumerable paths, string text, int width, int height) + public Stream BuildThumbCollage(IEnumerable paths, int width, int height, bool renderWithText, string text) { - using (var wand = BuildThumbCollageWand(paths, width, height)) + if (renderWithText) { - return DynamicImageHelpers.GetStream(wand, _appPaths); + using (var wand = BuildThumbCollageWandWithText(paths, text, width, height)) + { + return DynamicImageHelpers.GetStream(wand, _appPaths); + } + } + else + { + using (var wand = BuildThumbCollageWand(paths, width, height)) + { + return DynamicImageHelpers.GetStream(wand, _appPaths); + } } } @@ -68,7 +88,7 @@ namespace MediaBrowser.Server.Implementations.UserViews { draw.FillColor = fcolor; draw.Font = MontserratLightFont; - draw.FontSize = 50; + draw.FontSize = 60; draw.FontWeight = FontWeightType.LightStyle; draw.TextAntialias = true; } @@ -192,7 +212,7 @@ namespace MediaBrowser.Server.Implementations.UserViews var iSlice = Convert.ToInt32(width * 0.2333333334); int iTrans = Convert.ToInt32(height * .25); int iHeight = Convert.ToInt32(height * .65); - var horizontalImagePadding = Convert.ToInt32(width * 0.0125); + var horizontalImagePadding = Convert.ToInt32(width * 0.02); foreach (var element in wandImages.ImageList) { @@ -236,6 +256,75 @@ namespace MediaBrowser.Server.Implementations.UserViews } } + private MagickWand BuildSquareCollageWandWithText(IEnumerable 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.2333333334); + 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()) + { + mwr.CurrentImage.ResizeImage(wandList.CurrentImage.Width, (wandList.CurrentImage.Height / 2), FilterTypes.LanczosFilter, 1); + mwr.CurrentImage.FlipImage(); + + mwr.CurrentImage.AlphaChannel = AlphaChannelType.DeactivateAlphaChannel; + mwr.CurrentImage.ColorizeImage(ColorName.Black, ColorName.Grey60); + + 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); }