From 7e312e75bbb1324748319b29c9353716ed93a8da Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 26 Mar 2015 16:31:57 -0400 Subject: update stream sorting --- .../Photos/BaseDynamicImageProvider.cs | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) (limited to 'MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs') diff --git a/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs b/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs index 6fb02358e..eac0cd96d 100644 --- a/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs +++ b/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs @@ -223,8 +223,8 @@ namespace MediaBrowser.Server.Implementations.Photos protected virtual List GetFinalItems(List items, int limit) { - // Rotate the images no more than once per week - var random = new Random(GetWeekOfYear()).Next(); + // Rotate the images once every 7 days + var random = DateTime.Now.DayOfYear % 7; return items .OrderBy(i => (random + "" + items.IndexOf(i)).GetMD5()) @@ -233,18 +233,6 @@ namespace MediaBrowser.Server.Implementations.Photos .ToList(); } - private int GetWeekOfYear() - { - return DateTime.Now.Second; - var usCulture = new CultureInfo("en-US"); - var weekNo = usCulture.Calendar.GetWeekOfYear( - DateTime.Now, - usCulture.DateTimeFormat.CalendarWeekRule, - usCulture.DateTimeFormat.FirstDayOfWeek); - - return weekNo; - } - public int Order { get -- cgit v1.2.3 From 5e07bdf93c227bc98874ad333de4a6025fc53d6e Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 26 Mar 2015 19:10:34 -0400 Subject: sync fixes --- MediaBrowser.Api/Playback/MediaInfoService.cs | 16 +++++------ MediaBrowser.Model/Dlna/StreamInfoSorter.cs | 19 +++++++++---- .../Library/LibraryManager.cs | 8 ++++-- .../Photos/BaseDynamicImageProvider.cs | 6 ++-- .../Sync/MediaSync.cs | 33 ++++++++++++++++++---- .../UserViews/StripCollageBuilder.cs | 2 +- 6 files changed, 59 insertions(+), 25 deletions(-) (limited to 'MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs') diff --git a/MediaBrowser.Api/Playback/MediaInfoService.cs b/MediaBrowser.Api/Playback/MediaInfoService.cs index ce140365b..e219f4186 100644 --- a/MediaBrowser.Api/Playback/MediaInfoService.cs +++ b/MediaBrowser.Api/Playback/MediaInfoService.cs @@ -86,14 +86,14 @@ namespace MediaBrowser.Api.Playback var authInfo = AuthorizationContext.GetAuthorizationInfo(Request); var profile = request.DeviceProfile; - //if (profile == null) - //{ - // var caps = _deviceManager.GetCapabilities(authInfo.DeviceId); - // if (caps != null) - // { - // profile = caps.DeviceProfile; - // } - //} + if (profile == null) + { + var caps = _deviceManager.GetCapabilities(authInfo.DeviceId); + if (caps != null) + { + profile = caps.DeviceProfile; + } + } if (profile != null) { diff --git a/MediaBrowser.Model/Dlna/StreamInfoSorter.cs b/MediaBrowser.Model/Dlna/StreamInfoSorter.cs index 80eca193f..87c661548 100644 --- a/MediaBrowser.Model/Dlna/StreamInfoSorter.cs +++ b/MediaBrowser.Model/Dlna/StreamInfoSorter.cs @@ -1,6 +1,5 @@ using MediaBrowser.Model.MediaInfo; using MediaBrowser.Model.Session; -using System; using System.Collections.Generic; using System.Linq; @@ -11,17 +10,25 @@ namespace MediaBrowser.Model.Dlna public static List SortMediaSources(List streams) { return streams.OrderBy(i => + { + // Nothing beats direct playing a file + if (i.PlayMethod == PlayMethod.DirectPlay && i.MediaSource.Protocol == MediaProtocol.File) + { + return 0; + } + + return 1; + + }).ThenBy(i => { switch (i.PlayMethod) { + // Let's assume direct streaming a file is just as desirable as direct playing a remote url + case PlayMethod.DirectStream: case PlayMethod.DirectPlay: return 0; - case PlayMethod.DirectStream: - return 1; - case PlayMethod.Transcode: - return 2; default: - throw new ArgumentException("Unrecognized PlayMethod"); + return 2; } }).ThenBy(i => diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs index 64e5d20c9..f9fa1aae3 100644 --- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs +++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs @@ -1713,11 +1713,15 @@ namespace MediaBrowser.Server.Implementations.Library isNew = true; } - var refresh = isNew || (DateTime.UtcNow - item.DateLastSaved).TotalHours >= 6; + var refresh = isNew || (DateTime.UtcNow - item.DateLastSaved).TotalHours >= 12; if (refresh) { - _providerManagerFactory().QueueRefresh(item.Id, new MetadataRefreshOptions()); + _providerManagerFactory().QueueRefresh(item.Id, new MetadataRefreshOptions + { + // Need to force save to increment DateLastSaved + ForceSave = true + }); } return item; diff --git a/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs b/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs index eac0cd96d..1063fde53 100644 --- a/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs +++ b/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs @@ -125,7 +125,7 @@ namespace MediaBrowser.Server.Implementations.Photos protected abstract Task> GetItemsWithImages(IHasImages item); - private const string Version = "4"; + private const string Version = "5"; protected string GetConfigurationCacheKey(List items, string itemName) { var parts = Version + "_" + (itemName ?? string.Empty) + "_" + @@ -223,8 +223,8 @@ namespace MediaBrowser.Server.Implementations.Photos protected virtual List GetFinalItems(List items, int limit) { - // Rotate the images once every 7 days - var random = DateTime.Now.DayOfYear % 7; + // Rotate the images once every x days + var random = DateTime.Now.DayOfYear % 4; return items .OrderBy(i => (random + "" + items.IndexOf(i)).GetMD5()) diff --git a/MediaBrowser.Server.Implementations/Sync/MediaSync.cs b/MediaBrowser.Server.Implementations/Sync/MediaSync.cs index 429b72489..815756f9b 100644 --- a/MediaBrowser.Server.Implementations/Sync/MediaSync.cs +++ b/MediaBrowser.Server.Implementations/Sync/MediaSync.cs @@ -176,6 +176,8 @@ namespace MediaBrowser.Server.Implementations.Sync mediaSource.Path = sendFileResult.Path; mediaSource.Protocol = sendFileResult.Protocol; mediaSource.SupportsTranscoding = false; + + await SendSubtitles(localItem, mediaSource, provider, dataProvider, target, cancellationToken).ConfigureAwait(false); } } @@ -205,16 +207,37 @@ namespace MediaBrowser.Server.Implementations.Sync private async Task SendSubtitles(LocalItem localItem, MediaSourceInfo mediaSource, IServerSyncProvider provider, ISyncDataProvider dataProvider, SyncTarget target, CancellationToken cancellationToken) { + var failedSubtitles = new List(); + var requiresSave = false; + foreach (var mediaStream in mediaSource.MediaStreams .Where(i => i.Type == MediaStreamType.Subtitle && i.IsExternal) .ToList()) { - var sendFileResult = await SendFile(provider, mediaStream.Path, localItem, target, cancellationToken).ConfigureAwait(false); + try + { + var sendFileResult = await SendFile(provider, mediaStream.Path, localItem, target, cancellationToken).ConfigureAwait(false); - mediaStream.Path = sendFileResult.Path; - + mediaStream.Path = sendFileResult.Path; + requiresSave = true; + } + catch (Exception ex) + { + _logger.ErrorException("Error sending subtitle stream", ex); + failedSubtitles.Add(mediaStream); + } + } + + if (failedSubtitles.Count > 0) + { + mediaSource.MediaStreams = mediaSource.MediaStreams.Except(failedSubtitles).ToList(); + requiresSave = true; + } + + if (requiresSave) + { await dataProvider.AddOrUpdate(target, localItem).ConfigureAwait(false); - } + } } private async Task RemoveItem(IServerSyncProvider provider, @@ -374,7 +397,7 @@ namespace MediaBrowser.Server.Implementations.Sync var name = Path.GetFileNameWithoutExtension(item.LocalPath); - foreach (var file in list.Where(f => f.Name.Contains(name))) + foreach (var file in list.Where(f => f.Name.IndexOf(name, StringComparison.OrdinalIgnoreCase) != -1)) { var itemFile = new ItemFileInfo { diff --git a/MediaBrowser.Server.Implementations/UserViews/StripCollageBuilder.cs b/MediaBrowser.Server.Implementations/UserViews/StripCollageBuilder.cs index af2e01457..0bf4d8e4a 100644 --- a/MediaBrowser.Server.Implementations/UserViews/StripCollageBuilder.cs +++ b/MediaBrowser.Server.Implementations/UserViews/StripCollageBuilder.cs @@ -162,7 +162,7 @@ namespace MediaBrowser.Server.Implementations.UserViews 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 * .08)); + wand.CurrentImage.CompositeImage(wandList.AppendImages(true), CompositeOperator.AtopCompositeOp, ex, Convert.ToInt32(height * .085)); } } } -- cgit v1.2.3 From 285805d84a3d636b359e1a16f0d6b94fef6fc258 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 2 Apr 2015 12:58:52 -0400 Subject: create square collages --- .../Photos/BaseDynamicImageProvider.cs | 34 +++++------- .../UserViews/DynamicImageProvider.cs | 3 +- .../UserViews/StripCollageBuilder.cs | 64 ++++++++++++++++++++++ 3 files changed, 80 insertions(+), 21 deletions(-) (limited to 'MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs') diff --git a/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs b/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs index 1063fde53..0b5ffc903 100644 --- a/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs +++ b/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs @@ -13,6 +13,7 @@ using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Server.Implementations.UserViews; namespace MediaBrowser.Server.Implementations.Photos { @@ -134,30 +135,25 @@ namespace MediaBrowser.Server.Implementations.Photos return parts.GetMD5().ToString("N"); } - protected Task GetThumbCollage(List items) + protected Task GetThumbCollage(IHasImages primaryItem, List items) { - var files = items - .Select(i => i.GetImagePath(ImageType.Primary) ?? i.GetImagePath(ImageType.Thumb)) - .Where(i => !string.IsNullOrWhiteSpace(i)) - .ToList(); + var stream = new StripCollageBuilder(ApplicationPaths).BuildThumbCollage(GetStripCollageImagePaths(items), primaryItem.Name, 960, 540); - return DynamicImageHelpers.GetThumbCollage(files, - FileSystem, - 1600, - 900, - ApplicationPaths); + return Task.FromResult(stream); } - protected Task GetSquareCollage(List items) + private IEnumerable GetStripCollageImagePaths(IEnumerable items) { - var files = items + return items .Select(i => i.GetImagePath(ImageType.Primary) ?? i.GetImagePath(ImageType.Thumb)) - .Where(i => !string.IsNullOrWhiteSpace(i)) - .ToList(); + .Where(i => !string.IsNullOrWhiteSpace(i)); + } + + protected Task GetSquareCollage(IHasImages primaryItem, List items) + { + var stream = new StripCollageBuilder(ApplicationPaths).BuildSquareCollage(GetStripCollageImagePaths(items), primaryItem.Name, 800, 800); - return DynamicImageHelpers.GetSquareCollage(files, - FileSystem, - 800, ApplicationPaths); + return Task.FromResult(stream); } public string Name @@ -176,8 +172,8 @@ namespace MediaBrowser.Server.Implementations.Photos } return imageType == ImageType.Thumb ? - await GetThumbCollage(itemsWithImages).ConfigureAwait(false) : - await GetSquareCollage(itemsWithImages).ConfigureAwait(false); + await GetThumbCollage(item, itemsWithImages).ConfigureAwait(false) : + await GetSquareCollage(item, itemsWithImages).ConfigureAwait(false); } 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 d6a94210c..84bab1975 100644 --- a/MediaBrowser.Server.Implementations/UserViews/DynamicImageProvider.cs +++ b/MediaBrowser.Server.Implementations/UserViews/DynamicImageProvider.cs @@ -248,8 +248,7 @@ namespace MediaBrowser.Server.Implementations.UserViews return null; } - var stream = new StripCollageBuilder(ApplicationPaths).BuildThumbCollage(GetStripCollageImagePaths(itemsWithImages, view.ViewType), item.Name, 960, 540); - return stream; + return new StripCollageBuilder(ApplicationPaths).BuildThumbCollage(GetStripCollageImagePaths(itemsWithImages, view.ViewType), item.Name, 960, 540); } 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 0bf4d8e4a..10173c9f8 100644 --- a/MediaBrowser.Server.Implementations/UserViews/StripCollageBuilder.cs +++ b/MediaBrowser.Server.Implementations/UserViews/StripCollageBuilder.cs @@ -18,6 +18,14 @@ namespace MediaBrowser.Server.Implementations.UserViews _appPaths = appPaths; } + public Stream BuildSquareCollage(IEnumerable paths, string text, int width, int height) + { + using (var wand = BuildSquareCollageWand(paths, width, height)) + { + return DynamicImageHelpers.GetStream(wand, _appPaths); + } + } + public Stream BuildThumbCollage(IEnumerable paths, string text, int width, int height) { using (var wand = BuildThumbCollageWand(paths, width, height)) @@ -172,6 +180,62 @@ namespace MediaBrowser.Server.Implementations.UserViews } } + private MagickWand BuildSquareCollageWand(IEnumerable 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.2333333334); + int iTrans = Convert.ToInt32(height * .25); + int iHeight = Convert.ToInt32(height * .65); + 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 = ColorName.Black; + 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.Grey70); + + 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 string MontserratLightFont { get { return PlayedIndicatorDrawer.ExtractFont("MontserratLight.otf", _appPaths); } -- cgit v1.2.3 From 527f4887e91f33009be814a29313891c0827c8a7 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 2 Apr 2015 13:44:44 -0400 Subject: add new dynamic images --- .../Photos/BaseDynamicImageProvider.cs | 33 +++++-- .../UserViews/DynamicImageProvider.cs | 2 +- .../UserViews/StripCollageBuilder.cs | 105 +++++++++++++++++++-- 3 files changed, 123 insertions(+), 17 deletions(-) (limited to 'MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs') diff --git a/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs b/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs index 0b5ffc903..401234ac5 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 84bab1975..253bf36a2 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 10173c9f8..7dbfbb015 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) + { + using (var wand = BuildThumbCollageWandWithText(paths, text, width, height)) + { + return DynamicImageHelpers.GetStream(wand, _appPaths); + } + } + else { - return DynamicImageHelpers.GetStream(wand, _appPaths); + 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); } -- cgit v1.2.3 From c9c5a9345083c6af1a1ce3733fbc79f385cce0ea Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 2 Apr 2015 17:01:42 -0400 Subject: add poster dynamic images --- .../Photos/BaseDynamicImageProvider.cs | 4 +- .../UserViews/StripCollageBuilder.cs | 160 +++++++++++++++++++-- .../FFMpeg/FFMpegDownloader.cs | 9 +- 3 files changed, 157 insertions(+), 16 deletions(-) (limited to 'MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs') diff --git a/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs b/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs index 401234ac5..0909dfec9 100644 --- a/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs +++ b/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs @@ -126,7 +126,7 @@ namespace MediaBrowser.Server.Implementations.Photos protected abstract Task> GetItemsWithImages(IHasImages item); - private const string Version = "9"; + private const string Version = "15"; protected string GetConfigurationCacheKey(List items, string itemName) { var parts = Version + "_" + (itemName ?? string.Empty) + "_" + @@ -151,7 +151,7 @@ namespace MediaBrowser.Server.Implementations.Photos protected Task GetPosterCollage(IHasImages primaryItem, List items) { - var stream = new StripCollageBuilder(ApplicationPaths).BuildSquareCollage(GetStripCollageImagePaths(items), 800, 800, true, primaryItem.Name); + var stream = new StripCollageBuilder(ApplicationPaths).BuildPosterCollage(GetStripCollageImagePaths(items), 600, 900, true, primaryItem.Name); return Task.FromResult(stream); } diff --git a/MediaBrowser.Server.Implementations/UserViews/StripCollageBuilder.cs b/MediaBrowser.Server.Implementations/UserViews/StripCollageBuilder.cs index 7dbfbb015..de9587286 100644 --- a/MediaBrowser.Server.Implementations/UserViews/StripCollageBuilder.cs +++ b/MediaBrowser.Server.Implementations/UserViews/StripCollageBuilder.cs @@ -18,22 +18,34 @@ namespace MediaBrowser.Server.Implementations.UserViews _appPaths = appPaths; } - public Stream BuildSquareCollage(IEnumerable paths, int width, int height, bool renderWithText, string text) + public Stream BuildPosterCollage(IEnumerable paths, int width, int height, bool renderWithText, string text) { if (renderWithText) { - using (var wand = BuildSquareCollageWandWithText(paths, text, width, height)) + using (var wand = BuildPosterCollageWandWithText(paths, text, width, height)) { return DynamicImageHelpers.GetStream(wand, _appPaths); } } - else + using (var wand = BuildPosterCollageWand(paths, width, height)) + { + return DynamicImageHelpers.GetStream(wand, _appPaths); + } + } + + public Stream BuildSquareCollage(IEnumerable paths, int width, int height, bool renderWithText, string text) + { + if (renderWithText) { - using (var wand = BuildSquareCollageWand(paths, width, height)) + 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 paths, int width, int height, bool renderWithText, string text) @@ -45,12 +57,9 @@ namespace MediaBrowser.Server.Implementations.UserViews return DynamicImageHelpers.GetStream(wand, _appPaths); } } - else + using (var wand = BuildThumbCollageWand(paths, width, height)) { - using (var wand = BuildThumbCollageWand(paths, width, height)) - { - return DynamicImageHelpers.GetStream(wand, _appPaths); - } + return DynamicImageHelpers.GetStream(wand, _appPaths); } } @@ -144,6 +153,131 @@ namespace MediaBrowser.Server.Implementations.UserViews } } + private MagickWand BuildPosterCollageWand(IEnumerable paths, int width, int height) + { + var inputPaths = ProjectPaths(paths, 3); + 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 * .3); + int iTrans = Convert.ToInt32(height * .25); + int iHeight = Convert.ToInt32(height * .65); + var horizontalImagePadding = Convert.ToInt32(width * 0.025); + + foreach (var element in wandImages.ImageList) + { + int iWidth = (int)Math.Abs(iHeight * element.Width / element.Height); + element.Gravity = GravityType.CenterGravity; + element.BackgroundColor = ColorName.Black; + 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.Grey70); + + 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 paths, string label, int width, int height) + { + var inputPaths = ProjectPaths(paths, 3); + 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 * .3); + int iTrans = Convert.ToInt32(height * 0.2); + int iHeight = Convert.ToInt32(height * 0.46296296296296296296296296296296); + var horizontalImagePadding = Convert.ToInt32(width * 0.025); + + 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 MagickWand BuildThumbCollageWand(IEnumerable paths, int width, int height) { var inputPaths = ProjectPaths(paths, 8); @@ -209,9 +343,9 @@ namespace MediaBrowser.Server.Implementations.UserViews wand.OpenImage("gradient:#111111-#111111"); using (var draw = new DrawingWand()) { - var iSlice = Convert.ToInt32(width * 0.2333333334); + var iSlice = Convert.ToInt32(width * .225); int iTrans = Convert.ToInt32(height * .25); - int iHeight = Convert.ToInt32(height * .65); + int iHeight = Convert.ToInt32(height * .63); var horizontalImagePadding = Convert.ToInt32(width * 0.02); foreach (var element in wandImages.ImageList) @@ -246,7 +380,7 @@ namespace MediaBrowser.Server.Implementations.UserViews 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)); + wand.CurrentImage.CompositeImage(wandList.AppendImages(true), CompositeOperator.AtopCompositeOp, ex, Convert.ToInt32(height * .07)); } } } @@ -278,7 +412,7 @@ namespace MediaBrowser.Server.Implementations.UserViews 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); + 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); diff --git a/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloader.cs b/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloader.cs index d4cefdb10..fe7cd943a 100644 --- a/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloader.cs +++ b/MediaBrowser.Server.Startup.Common/FFMpeg/FFMpegDownloader.cs @@ -202,7 +202,14 @@ namespace MediaBrowser.Server.Startup.Common.FFMpeg } } - throw new ApplicationException("Unable to download required components. Please try again later."); + if (downloadinfo.DownloadUrls.Length == 0) + { + throw new ApplicationException("ffmpeg unvailable. Please install it and start the server with two command line arguments: -ffmpeg \"{PATH}\" and -ffprobe \"{PATH}\""); + } + else + { + throw new ApplicationException("Unable to download required components. Please try again later."); + } } private void ExtractFFMpeg(FFMpegDownloadInfo downloadinfo, string tempFile, string targetFolder) -- cgit v1.2.3 From 305398ed9c71ab75a19a20cd7ebcaab5de38892c Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 2 Apr 2015 22:54:40 -0400 Subject: update dynamic images --- .../Photos/BaseDynamicImageProvider.cs | 2 +- .../UserViews/StripCollageBuilder.cs | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs') diff --git a/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs b/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs index 0909dfec9..603ce87f2 100644 --- a/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs +++ b/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs @@ -126,7 +126,7 @@ namespace MediaBrowser.Server.Implementations.Photos protected abstract Task> GetItemsWithImages(IHasImages item); - private const string Version = "15"; + private const string Version = "17"; protected string GetConfigurationCacheKey(List items, string itemName) { var parts = Version + "_" + (itemName ?? string.Empty) + "_" + diff --git a/MediaBrowser.Server.Implementations/UserViews/StripCollageBuilder.cs b/MediaBrowser.Server.Implementations/UserViews/StripCollageBuilder.cs index de9587286..a9ac0946a 100644 --- a/MediaBrowser.Server.Implementations/UserViews/StripCollageBuilder.cs +++ b/MediaBrowser.Server.Implementations/UserViews/StripCollageBuilder.cs @@ -155,17 +155,17 @@ namespace MediaBrowser.Server.Implementations.UserViews private MagickWand BuildPosterCollageWand(IEnumerable paths, int width, int height) { - var inputPaths = ProjectPaths(paths, 3); + 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 * .3); + 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.025); + var horizontalImagePadding = Convert.ToInt32(width * 0.0275); foreach (var element in wandImages.ImageList) { @@ -211,7 +211,7 @@ namespace MediaBrowser.Server.Implementations.UserViews private MagickWand BuildPosterCollageWandWithText(IEnumerable paths, string label, int width, int height) { - var inputPaths = ProjectPaths(paths, 3); + var inputPaths = ProjectPaths(paths, 4); using (var wandImages = new MagickWand(inputPaths)) { var wand = new MagickWand(width, height); @@ -231,10 +231,10 @@ namespace MediaBrowser.Server.Implementations.UserViews var textContainerY = Convert.ToInt32(height * .165); wand.CurrentImage.AnnotateImage(draw, (width - fontMetrics.TextWidth) / 2, textContainerY, 0.0, label); - var iSlice = Convert.ToInt32(width * .3); + 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.025); + var horizontalImagePadding = Convert.ToInt32(width * 0.0275); foreach (var element in wandImages.ImageList) { -- cgit v1.2.3 From ef505c8e9e2b8f348aeaa89be6bc446014b72996 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 3 Apr 2015 12:58:12 -0400 Subject: update images --- MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs | 2 +- MediaBrowser.Server.Implementations/UserViews/DynamicImageProvider.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs') diff --git a/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs b/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs index 603ce87f2..79a1181ca 100644 --- a/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs +++ b/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs @@ -126,7 +126,7 @@ namespace MediaBrowser.Server.Implementations.Photos protected abstract Task> GetItemsWithImages(IHasImages item); - private const string Version = "17"; + private const string Version = "18"; protected string GetConfigurationCacheKey(List items, string itemName) { var parts = Version + "_" + (itemName ?? string.Empty) + "_" + diff --git a/MediaBrowser.Server.Implementations/UserViews/DynamicImageProvider.cs b/MediaBrowser.Server.Implementations/UserViews/DynamicImageProvider.cs index 253bf36a2..7bcbbd6a8 100644 --- a/MediaBrowser.Server.Implementations/UserViews/DynamicImageProvider.cs +++ b/MediaBrowser.Server.Implementations/UserViews/DynamicImageProvider.cs @@ -107,7 +107,7 @@ namespace MediaBrowser.Server.Implementations.UserViews User = _userManager.GetUserById(view.UserId.Value), CollapseBoxSetItems = false, Recursive = recursive, - ExcludeItemTypes = new[] { "UserView", "CollectionFolder" } + ExcludeItemTypes = new[] { "UserView", "CollectionFolder", "Playlist" } }).ConfigureAwait(false); -- cgit v1.2.3