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 --- .../UserViews/DynamicImageProvider.cs | 3 +- .../UserViews/StripCollageBuilder.cs | 64 ++++++++++++++++++++++ 2 files changed, 65 insertions(+), 2 deletions(-) (limited to 'MediaBrowser.Server.Implementations/UserViews') 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/UserViews') 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/UserViews') 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/UserViews') 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/UserViews') 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 From 3e9efeb44f716d9211ffe37f9dac1fa42bafd9e1 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 6 Apr 2015 16:55:37 -0400 Subject: updated image magick --- .../MediaBrowser.Server.Implementations.csproj | 6 +- .../Photos/BaseDynamicImageProvider.cs | 2 +- .../UserViews/StripCollageBuilder.cs | 261 ++++++++++++--------- .../packages.config | 4 +- .../MediaBrowser.ServerApplication.csproj | 2 +- MediaBrowser.ServerApplication/packages.config | 2 +- .../MediaBrowser.WebDashboard.csproj | 4 +- MediaBrowser.WebDashboard/packages.config | 2 +- 8 files changed, 164 insertions(+), 119 deletions(-) (limited to 'MediaBrowser.Server.Implementations/UserViews') diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index 8e026ea1d..949dd903c 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -47,15 +47,15 @@ False - ..\packages\ImageMagickSharp.1.0.0.11\lib\net45\ImageMagickSharp.dll + ..\packages\ImageMagickSharp.1.0.0.13\lib\net45\ImageMagickSharp.dll False ..\packages\MediaBrowser.Naming.1.0.0.32\lib\portable-net45+sl4+wp71+win8+wpa81\MediaBrowser.Naming.dll - + False - ..\packages\Mono.Nat.1.2.21.0\lib\net40\Mono.Nat.dll + ..\packages\Mono.Nat.1.2.23.0\lib\net40\Mono.Nat.dll False diff --git a/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs b/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs index 79a1181ca..3101897d2 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 = "18"; + private const string Version = "19"; 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 a9ac0946a..a0212c3c7 100644 --- a/MediaBrowser.Server.Implementations/UserViews/StripCollageBuilder.cs +++ b/MediaBrowser.Server.Implementations/UserViews/StripCollageBuilder.cs @@ -129,21 +129,27 @@ namespace MediaBrowser.Server.Implementations.UserViews 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)) + using (var blackPixelWand = new PixelWand(ColorName.Black)) { - 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)); + 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)); + } + } } } } @@ -169,14 +175,17 @@ namespace MediaBrowser.Server.Implementations.UserViews 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); + 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(); @@ -185,21 +194,27 @@ namespace MediaBrowser.Server.Implementations.UserViews 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)) + using (var blackPixelWand = new PixelWand(ColorName.Black)) { - 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)); + 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)); + } + } } } } @@ -254,21 +269,27 @@ namespace MediaBrowser.Server.Implementations.UserViews 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)) + using (var blackPixelWand = new PixelWand(ColorName.Black)) { - 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)); + 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)); + } + } } } } @@ -294,14 +315,17 @@ namespace MediaBrowser.Server.Implementations.UserViews 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); + 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(); @@ -310,21 +334,27 @@ namespace MediaBrowser.Server.Implementations.UserViews 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)) + using (var blackPixelWand = new PixelWand(ColorName.Black)) { - 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)); + 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)); + } + } } } } @@ -350,14 +380,17 @@ namespace MediaBrowser.Server.Implementations.UserViews 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); + 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(); @@ -366,21 +399,27 @@ namespace MediaBrowser.Server.Implementations.UserViews 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)) + using (var blackPixelWand = new PixelWand(ColorName.Black)) { - 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)); + 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)); + } + } } } } @@ -435,21 +474,27 @@ namespace MediaBrowser.Server.Implementations.UserViews 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)) + using (var blackPixelWand = new PixelWand(ColorName.Black)) { - 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)); + 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)); + } + } } } } diff --git a/MediaBrowser.Server.Implementations/packages.config b/MediaBrowser.Server.Implementations/packages.config index 438ccff92..c7e4684d1 100644 --- a/MediaBrowser.Server.Implementations/packages.config +++ b/MediaBrowser.Server.Implementations/packages.config @@ -1,8 +1,8 @@  - + - + diff --git a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj index 2adb9fbbc..e96f2c89f 100644 --- a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj +++ b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj @@ -62,7 +62,7 @@ False - ..\packages\ImageMagickSharp.1.0.0.11\lib\net45\ImageMagickSharp.dll + ..\packages\ImageMagickSharp.1.0.0.13\lib\net45\ImageMagickSharp.dll ..\packages\MediaBrowser.IsoMounting.3.0.69\lib\net45\MediaBrowser.IsoMounter.dll diff --git a/MediaBrowser.ServerApplication/packages.config b/MediaBrowser.ServerApplication/packages.config index f429269b3..2e984af6a 100644 --- a/MediaBrowser.ServerApplication/packages.config +++ b/MediaBrowser.ServerApplication/packages.config @@ -1,6 +1,6 @@  - + \ No newline at end of file diff --git a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj index a684cb909..4ad2ab685 100644 --- a/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj +++ b/MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj @@ -57,9 +57,9 @@ ..\ThirdParty\ServiceStack\ServiceStack.Interfaces.dll - + False - ..\packages\WebMarkupMin.Core.0.9.11\lib\net40\WebMarkupMin.Core.dll + ..\packages\WebMarkupMin.Core.0.9.12\lib\net40\WebMarkupMin.Core.dll diff --git a/MediaBrowser.WebDashboard/packages.config b/MediaBrowser.WebDashboard/packages.config index aed67fb69..48f68789b 100644 --- a/MediaBrowser.WebDashboard/packages.config +++ b/MediaBrowser.WebDashboard/packages.config @@ -1,5 +1,5 @@  - + \ No newline at end of file -- cgit v1.2.3 From 4820fe80971c83cde97a445e45b9e0b1952b0d90 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 8 Apr 2015 10:38:02 -0400 Subject: added drawing project --- Emby.Drawing/Common/ImageHeader.cs | 223 +++++++++ Emby.Drawing/Emby.Drawing.csproj | 34 +- Emby.Drawing/GDI/GDIImageEncoder.cs | 233 +++++++++ Emby.Drawing/GDI/ImageExtensions.cs | 217 +++++++++ Emby.Drawing/GDI/PercentPlayedDrawer.cs | 34 ++ Emby.Drawing/GDI/PlayedIndicatorDrawer.cs | 32 ++ Emby.Drawing/GDI/UnplayedCountIndicator.cs | 50 ++ Emby.Drawing/IImageEncoder.cs | 48 ++ Emby.Drawing/ImageHeader.cs | 223 --------- Emby.Drawing/ImageMagick/ImageMagickEncoder.cs | 224 +++++++++ Emby.Drawing/ImageMagick/PercentPlayedDrawer.cs | 40 ++ Emby.Drawing/ImageMagick/PlayedIndicatorDrawer.cs | 86 ++++ Emby.Drawing/ImageMagick/StripCollageBuilder.cs | 518 +++++++++++++++++++++ Emby.Drawing/ImageMagick/UnplayedCountIndicator.cs | 70 +++ Emby.Drawing/ImageProcessor.cs | 153 +----- Emby.Drawing/PercentPlayedDrawer.cs | 40 -- Emby.Drawing/PlayedIndicatorDrawer.cs | 86 ---- Emby.Drawing/UnplayedCountIndicator.cs | 70 --- MediaBrowser.Controller/Drawing/IImageProcessor.cs | 12 + .../Drawing/ImageCollageOptions.cs | 32 ++ .../MediaBrowser.Controller.csproj | 1 + .../Collections/CollectionImageProvider.cs | 3 +- .../Library/Resolvers/PhotoAlbumResolver.cs | 13 +- .../Library/Resolvers/PhotoResolver.cs | 18 +- .../MediaBrowser.Server.Implementations.csproj | 2 - .../Photos/BaseDynamicImageProvider.cs | 63 ++- .../Photos/DynamicImageHelpers.cs | 132 ------ .../Photos/PhotoAlbumImageProvider.cs | 3 +- .../Playlists/PlaylistImageProvider.cs | 3 +- .../UserViews/DynamicImageProvider.cs | 20 +- .../UserViews/StripCollageBuilder.cs | 512 -------------------- .../ApplicationHost.cs | 25 +- MediaBrowser.ServerApplication/MainStartup.cs | 1 - 33 files changed, 1972 insertions(+), 1249 deletions(-) create mode 100644 Emby.Drawing/Common/ImageHeader.cs create mode 100644 Emby.Drawing/GDI/GDIImageEncoder.cs create mode 100644 Emby.Drawing/GDI/ImageExtensions.cs create mode 100644 Emby.Drawing/GDI/PercentPlayedDrawer.cs create mode 100644 Emby.Drawing/GDI/PlayedIndicatorDrawer.cs create mode 100644 Emby.Drawing/GDI/UnplayedCountIndicator.cs create mode 100644 Emby.Drawing/IImageEncoder.cs delete mode 100644 Emby.Drawing/ImageHeader.cs create mode 100644 Emby.Drawing/ImageMagick/ImageMagickEncoder.cs create mode 100644 Emby.Drawing/ImageMagick/PercentPlayedDrawer.cs create mode 100644 Emby.Drawing/ImageMagick/PlayedIndicatorDrawer.cs create mode 100644 Emby.Drawing/ImageMagick/StripCollageBuilder.cs create mode 100644 Emby.Drawing/ImageMagick/UnplayedCountIndicator.cs delete mode 100644 Emby.Drawing/PercentPlayedDrawer.cs delete mode 100644 Emby.Drawing/PlayedIndicatorDrawer.cs delete mode 100644 Emby.Drawing/UnplayedCountIndicator.cs create mode 100644 MediaBrowser.Controller/Drawing/ImageCollageOptions.cs delete mode 100644 MediaBrowser.Server.Implementations/Photos/DynamicImageHelpers.cs delete mode 100644 MediaBrowser.Server.Implementations/UserViews/StripCollageBuilder.cs (limited to 'MediaBrowser.Server.Implementations/UserViews') diff --git a/Emby.Drawing/Common/ImageHeader.cs b/Emby.Drawing/Common/ImageHeader.cs new file mode 100644 index 000000000..b66bd71ea --- /dev/null +++ b/Emby.Drawing/Common/ImageHeader.cs @@ -0,0 +1,223 @@ +using MediaBrowser.Common.IO; +using MediaBrowser.Model.Drawing; +using MediaBrowser.Model.Logging; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; + +namespace Emby.Drawing.Common +{ + /// + /// Taken from http://stackoverflow.com/questions/111345/getting-image-dimensions-without-reading-the-entire-file/111349 + /// http://www.codeproject.com/Articles/35978/Reading-Image-Headers-to-Get-Width-and-Height + /// Minor improvements including supporting unsigned 16-bit integers when decoding Jfif and added logic + /// to load the image using new Bitmap if reading the headers fails + /// + public static class ImageHeader + { + /// + /// The error message + /// + const string ErrorMessage = "Could not recognize image format."; + + /// + /// The image format decoders + /// + private static readonly KeyValuePair>[] ImageFormatDecoders = new Dictionary> + { + { new byte[] { 0x42, 0x4D }, DecodeBitmap }, + { new byte[] { 0x47, 0x49, 0x46, 0x38, 0x37, 0x61 }, DecodeGif }, + { new byte[] { 0x47, 0x49, 0x46, 0x38, 0x39, 0x61 }, DecodeGif }, + { new byte[] { 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A }, DecodePng }, + { new byte[] { 0xff, 0xd8 }, DecodeJfif } + + }.ToArray(); + + private static readonly int MaxMagicBytesLength = ImageFormatDecoders.Select(i => i.Key.Length).OrderByDescending(i => i).First(); + + /// + /// Gets the dimensions of an image. + /// + /// The path of the image to get the dimensions of. + /// The logger. + /// The file system. + /// The dimensions of the specified image. + /// The image was of an unrecognised format. + public static ImageSize GetDimensions(string path, ILogger logger, IFileSystem fileSystem) + { + using (var fs = File.OpenRead(path)) + { + using (var binaryReader = new BinaryReader(fs)) + { + return GetDimensions(binaryReader); + } + } + } + + /// + /// Gets the dimensions of an image. + /// + /// The binary reader. + /// Size. + /// binaryReader + /// The image was of an unrecognized format. + private static ImageSize GetDimensions(BinaryReader binaryReader) + { + var magicBytes = new byte[MaxMagicBytesLength]; + + for (var i = 0; i < MaxMagicBytesLength; i += 1) + { + magicBytes[i] = binaryReader.ReadByte(); + + foreach (var kvPair in ImageFormatDecoders) + { + if (StartsWith(magicBytes, kvPair.Key)) + { + return kvPair.Value(binaryReader); + } + } + } + + throw new ArgumentException(ErrorMessage, "binaryReader"); + } + + /// + /// Startses the with. + /// + /// The this bytes. + /// The that bytes. + /// true if XXXX, false otherwise + private static bool StartsWith(byte[] thisBytes, byte[] thatBytes) + { + for (int i = 0; i < thatBytes.Length; i += 1) + { + if (thisBytes[i] != thatBytes[i]) + { + return false; + } + } + + return true; + } + + /// + /// Reads the little endian int16. + /// + /// The binary reader. + /// System.Int16. + private static short ReadLittleEndianInt16(BinaryReader binaryReader) + { + var bytes = new byte[sizeof(short)]; + + for (int i = 0; i < sizeof(short); i += 1) + { + bytes[sizeof(short) - 1 - i] = binaryReader.ReadByte(); + } + return BitConverter.ToInt16(bytes, 0); + } + + /// + /// Reads the little endian int32. + /// + /// The binary reader. + /// System.Int32. + private static int ReadLittleEndianInt32(BinaryReader binaryReader) + { + var bytes = new byte[sizeof(int)]; + for (int i = 0; i < sizeof(int); i += 1) + { + bytes[sizeof(int) - 1 - i] = binaryReader.ReadByte(); + } + return BitConverter.ToInt32(bytes, 0); + } + + /// + /// Decodes the bitmap. + /// + /// The binary reader. + /// Size. + private static ImageSize DecodeBitmap(BinaryReader binaryReader) + { + binaryReader.ReadBytes(16); + int width = binaryReader.ReadInt32(); + int height = binaryReader.ReadInt32(); + return new ImageSize + { + Width = width, + Height = height + }; + } + + /// + /// Decodes the GIF. + /// + /// The binary reader. + /// Size. + private static ImageSize DecodeGif(BinaryReader binaryReader) + { + int width = binaryReader.ReadInt16(); + int height = binaryReader.ReadInt16(); + return new ImageSize + { + Width = width, + Height = height + }; + } + + /// + /// Decodes the PNG. + /// + /// The binary reader. + /// Size. + private static ImageSize DecodePng(BinaryReader binaryReader) + { + binaryReader.ReadBytes(8); + int width = ReadLittleEndianInt32(binaryReader); + int height = ReadLittleEndianInt32(binaryReader); + return new ImageSize + { + Width = width, + Height = height + }; + } + + /// + /// Decodes the jfif. + /// + /// The binary reader. + /// Size. + /// + private static ImageSize DecodeJfif(BinaryReader binaryReader) + { + while (binaryReader.ReadByte() == 0xff) + { + byte marker = binaryReader.ReadByte(); + short chunkLength = ReadLittleEndianInt16(binaryReader); + if (marker == 0xc0) + { + binaryReader.ReadByte(); + int height = ReadLittleEndianInt16(binaryReader); + int width = ReadLittleEndianInt16(binaryReader); + return new ImageSize + { + Width = width, + Height = height + }; + } + + if (chunkLength < 0) + { + var uchunkLength = (ushort)chunkLength; + binaryReader.ReadBytes(uchunkLength - 2); + } + else + { + binaryReader.ReadBytes(chunkLength - 2); + } + } + + throw new ArgumentException(ErrorMessage); + } + } +} diff --git a/Emby.Drawing/Emby.Drawing.csproj b/Emby.Drawing/Emby.Drawing.csproj index 7e833eeeb..1907381e9 100644 --- a/Emby.Drawing/Emby.Drawing.csproj +++ b/Emby.Drawing/Emby.Drawing.csproj @@ -48,22 +48,42 @@ Properties\SharedVersion.cs - + + + + + + + + + - - + + - - - - + + + + + {9142eefa-7570-41e1-bfcc-468bb571af2f} + MediaBrowser.Common + + + {17e1f4e6-8abd-4fe5-9ecf-43d4b6087ba2} + MediaBrowser.Controller + + + {7eeeb4bb-f3e8-48fc-b4c5-70f0fff8329b} + MediaBrowser.Model + +