diff options
Diffstat (limited to 'Emby.Drawing')
| -rw-r--r-- | Emby.Drawing/Common/ImageHeader.cs | 2 | ||||
| -rw-r--r-- | Emby.Drawing/Emby.Drawing.csproj | 42 | ||||
| -rw-r--r-- | Emby.Drawing/GDI/DynamicImageHelpers.cs | 110 | ||||
| -rw-r--r-- | Emby.Drawing/GDI/GDIImageEncoder.cs | 281 | ||||
| -rw-r--r-- | Emby.Drawing/GDI/ImageExtensions.cs | 217 | ||||
| -rw-r--r-- | Emby.Drawing/GDI/PercentPlayedDrawer.cs | 34 | ||||
| -rw-r--r-- | Emby.Drawing/GDI/PlayedIndicatorDrawer.cs | 32 | ||||
| -rw-r--r-- | Emby.Drawing/GDI/UnplayedCountIndicator.cs | 50 | ||||
| -rw-r--r-- | Emby.Drawing/GDI/empty.png | bin | 158 -> 0 bytes | |||
| -rw-r--r-- | Emby.Drawing/IImageEncoder.cs | 61 | ||||
| -rw-r--r-- | Emby.Drawing/ImageHelpers.cs | 43 | ||||
| -rw-r--r-- | Emby.Drawing/ImageMagick/ImageMagickEncoder.cs | 333 | ||||
| -rw-r--r-- | Emby.Drawing/ImageMagick/PercentPlayedDrawer.cs | 40 | ||||
| -rw-r--r-- | Emby.Drawing/ImageMagick/PlayedIndicatorDrawer.cs | 125 | ||||
| -rw-r--r-- | Emby.Drawing/ImageMagick/StripCollageBuilder.cs | 202 | ||||
| -rw-r--r-- | Emby.Drawing/ImageMagick/UnplayedCountIndicator.cs | 75 | ||||
| -rw-r--r-- | Emby.Drawing/ImageProcessor.cs | 14 | ||||
| -rw-r--r-- | Emby.Drawing/packages.config | 4 | ||||
| -rw-r--r-- | Emby.Drawing/project.json | 17 |
19 files changed, 30 insertions, 1652 deletions
diff --git a/Emby.Drawing/Common/ImageHeader.cs b/Emby.Drawing/Common/ImageHeader.cs index 45a8f0d47..c385779a1 100644 --- a/Emby.Drawing/Common/ImageHeader.cs +++ b/Emby.Drawing/Common/ImageHeader.cs @@ -48,7 +48,7 @@ namespace Emby.Drawing.Common /// <exception cref="ArgumentException">The image was of an unrecognised format.</exception> public static ImageSize GetDimensions(string path, ILogger logger, IFileSystem fileSystem) { - using (var fs = File.OpenRead(path)) + using (var fs = fileSystem.OpenRead(path)) { using (var binaryReader = new BinaryReader(fs)) { diff --git a/Emby.Drawing/Emby.Drawing.csproj b/Emby.Drawing/Emby.Drawing.csproj index a883d0649..90418f631 100644 --- a/Emby.Drawing/Emby.Drawing.csproj +++ b/Emby.Drawing/Emby.Drawing.csproj @@ -9,10 +9,11 @@ <AppDesignerFolder>Properties</AppDesignerFolder> <RootNamespace>Emby.Drawing</RootNamespace> <AssemblyName>Emby.Drawing</AssemblyName> - <TargetFrameworkVersion>v4.6</TargetFrameworkVersion> + <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> + <TargetFrameworkProfile>Profile7</TargetFrameworkProfile> + <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> <FileAlignment>512</FileAlignment> <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir> - <TargetFrameworkProfile /> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <DebugSymbols>true</DebugSymbols> @@ -32,18 +33,6 @@ <WarningLevel>4</WarningLevel> </PropertyGroup> <ItemGroup> - <Reference Include="ImageMagickSharp, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL"> - <SpecificVersion>False</SpecificVersion> - <HintPath>..\packages\ImageMagickSharp.1.0.0.18\lib\net45\ImageMagickSharp.dll</HintPath> - </Reference> - <Reference Include="System" /> - <Reference Include="System.Core" /> - <Reference Include="System.Drawing" /> - <Reference Include="System.Xml.Linq" /> - <Reference Include="System.Data.DataSetExtensions" /> - <Reference Include="Microsoft.CSharp" /> - <Reference Include="System.Data" /> - <Reference Include="System.Xml" /> <Reference Include="TagLib.Portable"> <HintPath>..\ThirdParty\taglib\TagLib.Portable.dll</HintPath> </Reference> @@ -53,25 +42,9 @@ <Link>Properties\SharedVersion.cs</Link> </Compile> <Compile Include="Common\ImageHeader.cs" /> - <Compile Include="GDI\DynamicImageHelpers.cs" /> - <Compile Include="GDI\GDIImageEncoder.cs" /> - <Compile Include="GDI\ImageExtensions.cs" /> - <Compile Include="GDI\PercentPlayedDrawer.cs" /> - <Compile Include="GDI\PlayedIndicatorDrawer.cs" /> - <Compile Include="GDI\UnplayedCountIndicator.cs" /> - <Compile Include="IImageEncoder.cs" /> - <Compile Include="ImageHelpers.cs" /> - <Compile Include="ImageMagick\ImageMagickEncoder.cs" /> - <Compile Include="ImageMagick\StripCollageBuilder.cs" /> <Compile Include="ImageProcessor.cs" /> - <Compile Include="ImageMagick\PercentPlayedDrawer.cs" /> - <Compile Include="ImageMagick\PlayedIndicatorDrawer.cs" /> <Compile Include="NullImageEncoder.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> - <Compile Include="ImageMagick\UnplayedCountIndicator.cs" /> - </ItemGroup> - <ItemGroup> - <EmbeddedResource Include="ImageMagick\fonts\robotoregular.ttf" /> </ItemGroup> <ItemGroup> <ProjectReference Include="..\MediaBrowser.Common\MediaBrowser.Common.csproj"> @@ -87,13 +60,8 @@ <Name>MediaBrowser.Model</Name> </ProjectReference> </ItemGroup> - <ItemGroup> - <None Include="packages.config" /> - </ItemGroup> - <ItemGroup> - <EmbeddedResource Include="GDI\empty.png" /> - </ItemGroup> - <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> + <ItemGroup /> + <Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" /> <!-- To modify your build process, add your task inside one of the targets below and uncomment it. Other similar extension points exist, see Microsoft.Common.targets. <Target Name="BeforeBuild"> diff --git a/Emby.Drawing/GDI/DynamicImageHelpers.cs b/Emby.Drawing/GDI/DynamicImageHelpers.cs deleted file mode 100644 index 9cbd6cbe3..000000000 --- a/Emby.Drawing/GDI/DynamicImageHelpers.cs +++ /dev/null @@ -1,110 +0,0 @@ -using System.Collections.Generic; -using System.Drawing; -using System.Drawing.Drawing2D; -using System.Drawing.Imaging; -using System.IO; -using MediaBrowser.Common.IO; -using MediaBrowser.Controller.IO; -using MediaBrowser.Model.IO; - -namespace Emby.Drawing.GDI -{ - public static class DynamicImageHelpers - { - public static void CreateThumbCollage(List<string> files, - IFileSystem fileSystem, - string file, - int width, - int height) - { - const int numStrips = 4; - files = ImageHelpers.ProjectPaths(files, numStrips); - - const int rows = 1; - int cols = numStrips; - - int cellWidth = 2 * (width / 3); - int cellHeight = height; - var index = 0; - - using (var img = new Bitmap(width, height, PixelFormat.Format32bppPArgb)) - { - using (var graphics = Graphics.FromImage(img)) - { - graphics.CompositingQuality = CompositingQuality.HighQuality; - graphics.SmoothingMode = SmoothingMode.HighQuality; - graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; - graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; - - // SourceCopy causes the image to be blank in OSX - //graphics.CompositingMode = CompositingMode.SourceCopy; - - for (var row = 0; row < rows; row++) - { - for (var col = 0; col < cols; col++) - { - var x = col * (cellWidth / 2); - var y = row * cellHeight; - - if (files.Count > index) - { - using (var imgtemp = Image.FromFile(files[index])) - { - graphics.DrawImage(imgtemp, x, y, cellWidth, cellHeight); - } - } - - index++; - } - } - img.Save(file); - } - } - } - - public static void CreateSquareCollage(List<string> files, - IFileSystem fileSystem, - string file, - int width, - int height) - { - files = ImageHelpers.ProjectPaths(files, 4); - - const int rows = 2; - const int cols = 2; - - int singleSize = width / 2; - var index = 0; - - using (var img = new Bitmap(width, height, PixelFormat.Format32bppPArgb)) - { - using (var graphics = Graphics.FromImage(img)) - { - graphics.CompositingQuality = CompositingQuality.HighQuality; - graphics.SmoothingMode = SmoothingMode.HighQuality; - graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; - graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; - - // SourceCopy causes the image to be blank in OSX - //graphics.CompositingMode = CompositingMode.SourceCopy; - - for (var row = 0; row < rows; row++) - { - for (var col = 0; col < cols; col++) - { - var x = col * singleSize; - var y = row * singleSize; - - using (var imgtemp = Image.FromFile(files[index])) - { - graphics.DrawImage(imgtemp, x, y, singleSize, singleSize); - } - index++; - } - } - img.Save(file); - } - } - } - } -} diff --git a/Emby.Drawing/GDI/GDIImageEncoder.cs b/Emby.Drawing/GDI/GDIImageEncoder.cs deleted file mode 100644 index 2fd2cac7e..000000000 --- a/Emby.Drawing/GDI/GDIImageEncoder.cs +++ /dev/null @@ -1,281 +0,0 @@ -using MediaBrowser.Controller.Drawing; -using MediaBrowser.Model.Drawing; -using MediaBrowser.Model.Logging; -using System; -using System.Drawing; -using System.Drawing.Drawing2D; -using System.Drawing.Imaging; -using System.IO; -using System.Linq; -using MediaBrowser.Common.IO; -using MediaBrowser.Controller.IO; -using MediaBrowser.Model.IO; -using ImageFormat = MediaBrowser.Model.Drawing.ImageFormat; - -namespace Emby.Drawing.GDI -{ - public class GDIImageEncoder : IImageEncoder - { - private readonly IFileSystem _fileSystem; - private readonly ILogger _logger; - - public GDIImageEncoder(IFileSystem fileSystem, ILogger logger) - { - _fileSystem = fileSystem; - _logger = logger; - - LogInfo(); - } - - private void LogInfo() - { - _logger.Info("GDIImageEncoder starting"); - using (var stream = GetType().Assembly.GetManifestResourceStream(GetType().Namespace + ".empty.png")) - { - using (var img = Image.FromStream(stream)) - { - - } - } - _logger.Info("GDIImageEncoder started"); - } - - public string[] SupportedInputFormats - { - get - { - return new[] - { - "png", - "jpeg", - "jpg", - "gif", - "bmp" - }; - } - } - - public ImageFormat[] SupportedOutputFormats - { - get - { - return new[] { ImageFormat.Gif, ImageFormat.Jpg, ImageFormat.Png }; - } - } - - public ImageSize GetImageSize(string path) - { - using (var image = Image.FromFile(path)) - { - return new ImageSize - { - Width = image.Width, - Height = image.Height - }; - } - } - - public void CropWhiteSpace(string inputPath, string outputPath) - { - using (var image = (Bitmap)Image.FromFile(inputPath)) - { - using (var croppedImage = image.CropWhitespace()) - { - _fileSystem.CreateDirectory(Path.GetDirectoryName(outputPath)); - - using (var outputStream = _fileSystem.GetFileStream(outputPath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, false)) - { - croppedImage.Save(System.Drawing.Imaging.ImageFormat.Png, outputStream, 100); - } - } - } - } - - public void EncodeImage(string inputPath, string cacheFilePath, bool autoOrient, int width, int height, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat) - { - var hasPostProcessing = !string.IsNullOrEmpty(options.BackgroundColor) || options.UnplayedCount.HasValue || options.AddPlayedIndicator || options.PercentPlayed > 0; - - using (var originalImage = Image.FromFile(inputPath)) - { - var newWidth = Convert.ToInt32(width); - var newHeight = Convert.ToInt32(height); - - // Graphics.FromImage will throw an exception if the PixelFormat is Indexed, so we need to handle that here - // Also, Webp only supports Format32bppArgb and Format32bppRgb - var pixelFormat = selectedOutputFormat == ImageFormat.Webp - ? PixelFormat.Format32bppArgb - : PixelFormat.Format32bppPArgb; - - using (var thumbnail = new Bitmap(newWidth, newHeight, pixelFormat)) - { - // Mono throw an exeception if assign 0 to SetResolution - if (originalImage.HorizontalResolution > 0 && originalImage.VerticalResolution > 0) - { - // Preserve the original resolution - thumbnail.SetResolution(originalImage.HorizontalResolution, originalImage.VerticalResolution); - } - - using (var thumbnailGraph = Graphics.FromImage(thumbnail)) - { - thumbnailGraph.CompositingQuality = CompositingQuality.HighQuality; - thumbnailGraph.SmoothingMode = SmoothingMode.HighQuality; - thumbnailGraph.InterpolationMode = InterpolationMode.HighQualityBicubic; - thumbnailGraph.PixelOffsetMode = PixelOffsetMode.HighQuality; - - // SourceCopy causes the image to be blank in OSX - //thumbnailGraph.CompositingMode = !hasPostProcessing ? - // CompositingMode.SourceCopy : - // CompositingMode.SourceOver; - - SetBackgroundColor(thumbnailGraph, options); - - thumbnailGraph.DrawImage(originalImage, 0, 0, newWidth, newHeight); - - DrawIndicator(thumbnailGraph, newWidth, newHeight, options); - - var outputFormat = GetOutputFormat(originalImage, selectedOutputFormat); - - _fileSystem.CreateDirectory(Path.GetDirectoryName(cacheFilePath)); - - // Save to the cache location - using (var cacheFileStream = _fileSystem.GetFileStream(cacheFilePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, false)) - { - // Save to the memory stream - thumbnail.Save(outputFormat, cacheFileStream, quality); - } - } - } - - } - } - - /// <summary> - /// Sets the color of the background. - /// </summary> - /// <param name="graphics">The graphics.</param> - /// <param name="options">The options.</param> - private void SetBackgroundColor(Graphics graphics, ImageProcessingOptions options) - { - var color = options.BackgroundColor; - - if (!string.IsNullOrEmpty(color)) - { - Color drawingColor; - - try - { - drawingColor = ColorTranslator.FromHtml(color); - } - catch - { - drawingColor = ColorTranslator.FromHtml("#" + color); - } - - graphics.Clear(drawingColor); - } - } - - /// <summary> - /// Draws the indicator. - /// </summary> - /// <param name="graphics">The graphics.</param> - /// <param name="imageWidth">Width of the image.</param> - /// <param name="imageHeight">Height of the image.</param> - /// <param name="options">The options.</param> - private void DrawIndicator(Graphics graphics, int imageWidth, int imageHeight, ImageProcessingOptions options) - { - if (!options.AddPlayedIndicator && !options.UnplayedCount.HasValue && options.PercentPlayed.Equals(0)) - { - return; - } - - try - { - if (options.AddPlayedIndicator) - { - var currentImageSize = new Size(imageWidth, imageHeight); - - new PlayedIndicatorDrawer().DrawPlayedIndicator(graphics, currentImageSize); - } - else if (options.UnplayedCount.HasValue) - { - var currentImageSize = new Size(imageWidth, imageHeight); - - new UnplayedCountIndicator().DrawUnplayedCountIndicator(graphics, currentImageSize, options.UnplayedCount.Value); - } - - if (options.PercentPlayed > 0) - { - var currentImageSize = new Size(imageWidth, imageHeight); - - new PercentPlayedDrawer().Process(graphics, currentImageSize, options.PercentPlayed); - } - } - catch (Exception ex) - { - _logger.ErrorException("Error drawing indicator overlay", ex); - } - } - - /// <summary> - /// Gets the output format. - /// </summary> - /// <param name="image">The image.</param> - /// <param name="outputFormat">The output format.</param> - /// <returns>ImageFormat.</returns> - private System.Drawing.Imaging.ImageFormat GetOutputFormat(Image image, ImageFormat outputFormat) - { - switch (outputFormat) - { - case ImageFormat.Bmp: - return System.Drawing.Imaging.ImageFormat.Bmp; - case ImageFormat.Gif: - return System.Drawing.Imaging.ImageFormat.Gif; - case ImageFormat.Jpg: - return System.Drawing.Imaging.ImageFormat.Jpeg; - case ImageFormat.Png: - return System.Drawing.Imaging.ImageFormat.Png; - default: - return image.RawFormat; - } - } - - public void CreateImageCollage(ImageCollageOptions options) - { - double ratio = options.Width; - ratio /= options.Height; - - if (ratio >= 1.4) - { - DynamicImageHelpers.CreateThumbCollage(options.InputPaths.ToList(), _fileSystem, options.OutputPath, options.Width, options.Height); - } - else if (ratio >= .9) - { - DynamicImageHelpers.CreateSquareCollage(options.InputPaths.ToList(), _fileSystem, options.OutputPath, options.Width, options.Height); - } - else - { - DynamicImageHelpers.CreateSquareCollage(options.InputPaths.ToList(), _fileSystem, options.OutputPath, options.Width, options.Width); - } - } - - public void Dispose() - { - } - - public string Name - { - get { return "GDI"; } - } - - public bool SupportsImageCollageCreation - { - get { return true; } - } - - public bool SupportsImageEncoding - { - get { return true; } - } - } -} diff --git a/Emby.Drawing/GDI/ImageExtensions.cs b/Emby.Drawing/GDI/ImageExtensions.cs deleted file mode 100644 index 6af5a8688..000000000 --- a/Emby.Drawing/GDI/ImageExtensions.cs +++ /dev/null @@ -1,217 +0,0 @@ -using System; -using System.Drawing; -using System.Drawing.Drawing2D; -using System.Drawing.Imaging; -using System.IO; - -namespace Emby.Drawing.GDI -{ - public static class ImageExtensions - { - /// <summary> - /// Saves the image. - /// </summary> - /// <param name="outputFormat">The output format.</param> - /// <param name="image">The image.</param> - /// <param name="toStream">To stream.</param> - /// <param name="quality">The quality.</param> - public static void Save(this Image image, ImageFormat outputFormat, Stream toStream, int quality) - { - // Use special save methods for jpeg and png that will result in a much higher quality image - // All other formats use the generic Image.Save - if (ImageFormat.Jpeg.Equals(outputFormat)) - { - SaveAsJpeg(image, toStream, quality); - } - else if (ImageFormat.Png.Equals(outputFormat)) - { - image.Save(toStream, ImageFormat.Png); - } - else - { - image.Save(toStream, outputFormat); - } - } - - /// <summary> - /// Saves the JPEG. - /// </summary> - /// <param name="image">The image.</param> - /// <param name="target">The target.</param> - /// <param name="quality">The quality.</param> - public static void SaveAsJpeg(this Image image, Stream target, int quality) - { - using (var encoderParameters = new EncoderParameters(1)) - { - encoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, quality); - image.Save(target, GetImageCodecInfo("image/jpeg"), encoderParameters); - } - } - - private static readonly ImageCodecInfo[] Encoders = ImageCodecInfo.GetImageEncoders(); - - /// <summary> - /// Gets the image codec info. - /// </summary> - /// <param name="mimeType">Type of the MIME.</param> - /// <returns>ImageCodecInfo.</returns> - private static ImageCodecInfo GetImageCodecInfo(string mimeType) - { - foreach (var encoder in Encoders) - { - if (string.Equals(encoder.MimeType, mimeType, StringComparison.OrdinalIgnoreCase)) - { - return encoder; - } - } - - return Encoders.Length == 0 ? null : Encoders[0]; - } - - /// <summary> - /// Crops an image by removing whitespace and transparency from the edges - /// </summary> - /// <param name="bmp">The BMP.</param> - /// <returns>Bitmap.</returns> - /// <exception cref="System.Exception"></exception> - public static Bitmap CropWhitespace(this Bitmap bmp) - { - var width = bmp.Width; - var height = bmp.Height; - - var topmost = 0; - for (int row = 0; row < height; ++row) - { - if (IsAllWhiteRow(bmp, row, width)) - topmost = row; - else break; - } - - int bottommost = 0; - for (int row = height - 1; row >= 0; --row) - { - if (IsAllWhiteRow(bmp, row, width)) - bottommost = row; - else break; - } - - int leftmost = 0, rightmost = 0; - for (int col = 0; col < width; ++col) - { - if (IsAllWhiteColumn(bmp, col, height)) - leftmost = col; - else - break; - } - - for (int col = width - 1; col >= 0; --col) - { - if (IsAllWhiteColumn(bmp, col, height)) - rightmost = col; - else - break; - } - - if (rightmost == 0) rightmost = width; // As reached left - if (bottommost == 0) bottommost = height; // As reached top. - - var croppedWidth = rightmost - leftmost; - var croppedHeight = bottommost - topmost; - - if (croppedWidth == 0) // No border on left or right - { - leftmost = 0; - croppedWidth = width; - } - - if (croppedHeight == 0) // No border on top or bottom - { - topmost = 0; - croppedHeight = height; - } - - // Graphics.FromImage will throw an exception if the PixelFormat is Indexed, so we need to handle that here - var thumbnail = new Bitmap(croppedWidth, croppedHeight, PixelFormat.Format32bppPArgb); - - // Preserve the original resolution - TrySetResolution(thumbnail, bmp.HorizontalResolution, bmp.VerticalResolution); - - using (var thumbnailGraph = Graphics.FromImage(thumbnail)) - { - thumbnailGraph.CompositingQuality = CompositingQuality.HighQuality; - thumbnailGraph.SmoothingMode = SmoothingMode.HighQuality; - thumbnailGraph.InterpolationMode = InterpolationMode.HighQualityBicubic; - thumbnailGraph.PixelOffsetMode = PixelOffsetMode.HighQuality; - thumbnailGraph.CompositingMode = CompositingMode.SourceCopy; - - thumbnailGraph.DrawImage(bmp, - new RectangleF(0, 0, croppedWidth, croppedHeight), - new RectangleF(leftmost, topmost, croppedWidth, croppedHeight), - GraphicsUnit.Pixel); - } - return thumbnail; - } - - /// <summary> - /// Tries the set resolution. - /// </summary> - /// <param name="bmp">The BMP.</param> - /// <param name="x">The x.</param> - /// <param name="y">The y.</param> - private static void TrySetResolution(Bitmap bmp, float x, float y) - { - if (x > 0 && y > 0) - { - bmp.SetResolution(x, y); - } - } - - /// <summary> - /// Determines whether or not a row of pixels is all whitespace - /// </summary> - /// <param name="bmp">The BMP.</param> - /// <param name="row">The row.</param> - /// <param name="width">The width.</param> - /// <returns><c>true</c> if [is all white row] [the specified BMP]; otherwise, <c>false</c>.</returns> - private static bool IsAllWhiteRow(Bitmap bmp, int row, int width) - { - for (var i = 0; i < width; ++i) - { - if (!IsWhiteSpace(bmp.GetPixel(i, row))) - { - return false; - } - } - return true; - } - - /// <summary> - /// Determines whether or not a column of pixels is all whitespace - /// </summary> - /// <param name="bmp">The BMP.</param> - /// <param name="col">The col.</param> - /// <param name="height">The height.</param> - /// <returns><c>true</c> if [is all white column] [the specified BMP]; otherwise, <c>false</c>.</returns> - private static bool IsAllWhiteColumn(Bitmap bmp, int col, int height) - { - for (var i = 0; i < height; ++i) - { - if (!IsWhiteSpace(bmp.GetPixel(col, i))) - { - return false; - } - } - return true; - } - - /// <summary> - /// Determines if a color is whitespace - /// </summary> - /// <param name="color">The color.</param> - /// <returns><c>true</c> if [is white space] [the specified color]; otherwise, <c>false</c>.</returns> - private static bool IsWhiteSpace(Color color) - { - return (color.R == 255 && color.G == 255 && color.B == 255) || color.A == 0; - } - } -} diff --git a/Emby.Drawing/GDI/PercentPlayedDrawer.cs b/Emby.Drawing/GDI/PercentPlayedDrawer.cs deleted file mode 100644 index c7afda60e..000000000 --- a/Emby.Drawing/GDI/PercentPlayedDrawer.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; -using System.Drawing; - -namespace Emby.Drawing.GDI -{ - public class PercentPlayedDrawer - { - private const int IndicatorHeight = 8; - - public void Process(Graphics graphics, Size imageSize, double percent) - { - var y = imageSize.Height - IndicatorHeight; - - using (var backdroundBrush = new SolidBrush(Color.FromArgb(225, 0, 0, 0))) - { - const int innerX = 0; - var innerY = y; - var innerWidth = imageSize.Width; - var innerHeight = imageSize.Height; - - graphics.FillRectangle(backdroundBrush, innerX, innerY, innerWidth, innerHeight); - - using (var foregroundBrush = new SolidBrush(Color.FromArgb(82, 181, 75))) - { - double foregroundWidth = innerWidth; - foregroundWidth *= percent; - foregroundWidth /= 100; - - graphics.FillRectangle(foregroundBrush, innerX, innerY, Convert.ToInt32(Math.Round(foregroundWidth)), innerHeight); - } - } - } - } -} diff --git a/Emby.Drawing/GDI/PlayedIndicatorDrawer.cs b/Emby.Drawing/GDI/PlayedIndicatorDrawer.cs deleted file mode 100644 index 4428e4cba..000000000 --- a/Emby.Drawing/GDI/PlayedIndicatorDrawer.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System.Drawing; - -namespace Emby.Drawing.GDI -{ - public class PlayedIndicatorDrawer - { - private const int IndicatorHeight = 40; - public const int IndicatorWidth = 40; - private const int FontSize = 40; - private const int OffsetFromTopRightCorner = 10; - - public void DrawPlayedIndicator(Graphics graphics, Size imageSize) - { - var x = imageSize.Width - IndicatorWidth - OffsetFromTopRightCorner; - - using (var backdroundBrush = new SolidBrush(Color.FromArgb(225, 82, 181, 75))) - { - graphics.FillEllipse(backdroundBrush, x, OffsetFromTopRightCorner, IndicatorWidth, IndicatorHeight); - - x = imageSize.Width - 45 - OffsetFromTopRightCorner; - - using (var font = new Font("Webdings", FontSize, FontStyle.Regular, GraphicsUnit.Pixel)) - { - using (var fontBrush = new SolidBrush(Color.White)) - { - graphics.DrawString("a", font, fontBrush, x, OffsetFromTopRightCorner - 2); - } - } - } - } - } -} diff --git a/Emby.Drawing/GDI/UnplayedCountIndicator.cs b/Emby.Drawing/GDI/UnplayedCountIndicator.cs deleted file mode 100644 index 6420abb27..000000000 --- a/Emby.Drawing/GDI/UnplayedCountIndicator.cs +++ /dev/null @@ -1,50 +0,0 @@ -using System.Drawing; - -namespace Emby.Drawing.GDI -{ - public class UnplayedCountIndicator - { - private const int IndicatorHeight = 41; - public const int IndicatorWidth = 41; - private const int OffsetFromTopRightCorner = 10; - - public void DrawUnplayedCountIndicator(Graphics graphics, Size imageSize, int count) - { - var x = imageSize.Width - IndicatorWidth - OffsetFromTopRightCorner; - - using (var backdroundBrush = new SolidBrush(Color.FromArgb(225, 82, 181, 75))) - { - graphics.FillEllipse(backdroundBrush, x, OffsetFromTopRightCorner, IndicatorWidth, IndicatorHeight); - - var text = count.ToString(); - - x = imageSize.Width - IndicatorWidth - OffsetFromTopRightCorner; - var y = OffsetFromTopRightCorner + 6; - var fontSize = 24; - - if (text.Length == 1) - { - x += 10; - } - else if (text.Length == 2) - { - x += 3; - } - else if (text.Length == 3) - { - x += 1; - y += 1; - fontSize = 20; - } - - using (var font = new Font("Sans-Serif", fontSize, FontStyle.Regular, GraphicsUnit.Pixel)) - { - using (var fontBrush = new SolidBrush(Color.White)) - { - graphics.DrawString(text, font, fontBrush, x, y); - } - } - } - } - } -} diff --git a/Emby.Drawing/GDI/empty.png b/Emby.Drawing/GDI/empty.png Binary files differdeleted file mode 100644 index 42e2b375e..000000000 --- a/Emby.Drawing/GDI/empty.png +++ /dev/null diff --git a/Emby.Drawing/IImageEncoder.cs b/Emby.Drawing/IImageEncoder.cs deleted file mode 100644 index 73b539899..000000000 --- a/Emby.Drawing/IImageEncoder.cs +++ /dev/null @@ -1,61 +0,0 @@ -using MediaBrowser.Controller.Drawing; -using MediaBrowser.Model.Drawing; -using System; - -namespace Emby.Drawing -{ - public interface IImageEncoder : IDisposable - { - /// <summary> - /// Gets the supported input formats. - /// </summary> - /// <value>The supported input formats.</value> - string[] SupportedInputFormats { get; } - /// <summary> - /// Gets the supported output formats. - /// </summary> - /// <value>The supported output formats.</value> - ImageFormat[] SupportedOutputFormats { get; } - /// <summary> - /// Crops the white space. - /// </summary> - /// <param name="inputPath">The input path.</param> - /// <param name="outputPath">The output path.</param> - void CropWhiteSpace(string inputPath, string outputPath); - /// <summary> - /// Encodes the image. - /// </summary> - /// <param name="inputPath">The input path.</param> - /// <param name="outputPath">The output path.</param> - /// <param name="autoOrient">if set to <c>true</c> [automatic orient].</param> - /// <param name="width">The width.</param> - /// <param name="height">The height.</param> - /// <param name="quality">The quality.</param> - /// <param name="options">The options.</param> - /// <param name="outputFormat">The output format.</param> - void EncodeImage(string inputPath, string outputPath, bool autoOrient, int width, int height, int quality, ImageProcessingOptions options, ImageFormat outputFormat); - - /// <summary> - /// Creates the image collage. - /// </summary> - /// <param name="options">The options.</param> - void CreateImageCollage(ImageCollageOptions options); - /// <summary> - /// Gets the name. - /// </summary> - /// <value>The name.</value> - string Name { get; } - - /// <summary> - /// Gets a value indicating whether [supports image collage creation]. - /// </summary> - /// <value><c>true</c> if [supports image collage creation]; otherwise, <c>false</c>.</value> - bool SupportsImageCollageCreation { get; } - - /// <summary> - /// Gets a value indicating whether [supports image encoding]. - /// </summary> - /// <value><c>true</c> if [supports image encoding]; otherwise, <c>false</c>.</value> - bool SupportsImageEncoding { get; } - } -} diff --git a/Emby.Drawing/ImageHelpers.cs b/Emby.Drawing/ImageHelpers.cs deleted file mode 100644 index 90bde8b3b..000000000 --- a/Emby.Drawing/ImageHelpers.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; - -namespace Emby.Drawing -{ - internal static class ImageHelpers - { - internal static List<string> ProjectPaths(List<string> paths, int count) - { - if (count <= 0) - { - throw new ArgumentOutOfRangeException("count"); - } - if (paths.Count == 0) - { - throw new ArgumentOutOfRangeException("paths"); - } - - var list = new List<string>(); - - AddToList(list, paths, count); - - return list.Take(count).ToList(); - } - - private static void AddToList(List<string> list, List<string> paths, int count) - { - while (list.Count < count) - { - foreach (var path in paths) - { - list.Add(path); - - if (list.Count >= count) - { - return; - } - } - } - } - } -} diff --git a/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs b/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs deleted file mode 100644 index 3410ef003..000000000 --- a/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs +++ /dev/null @@ -1,333 +0,0 @@ -using System.Threading.Tasks; -using ImageMagickSharp; -using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Net; -using MediaBrowser.Controller.Drawing; -using MediaBrowser.Model.Drawing; -using MediaBrowser.Model.Logging; -using System; -using System.IO; -using System.Linq; -using MediaBrowser.Common.IO; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.IO; -using MediaBrowser.Model.IO; - -namespace Emby.Drawing.ImageMagick -{ - public class ImageMagickEncoder : IImageEncoder - { - private readonly ILogger _logger; - private readonly IApplicationPaths _appPaths; - private readonly IHttpClient _httpClient; - private readonly IFileSystem _fileSystem; - private readonly IServerConfigurationManager _config; - - public ImageMagickEncoder(ILogger logger, IApplicationPaths appPaths, IHttpClient httpClient, IFileSystem fileSystem, IServerConfigurationManager config) - { - _logger = logger; - _appPaths = appPaths; - _httpClient = httpClient; - _fileSystem = fileSystem; - _config = config; - - LogVersion(); - } - - public string[] SupportedInputFormats - { - get - { - // Some common file name extensions for RAW picture files include: .cr2, .crw, .dng, .nef, .orf, .rw2, .pef, .arw, .sr2, .srf, and .tif. - return new[] - { - "tiff", - "jpeg", - "jpg", - "png", - "aiff", - "cr2", - "crw", - "dng", - "nef", - "orf", - "pef", - "arw", - "webp", - "gif", - "bmp", - "erf", - "raf", - "rw2", - "nrw" - }; - } - } - - public ImageFormat[] SupportedOutputFormats - { - get - { - if (_webpAvailable) - { - return new[] { ImageFormat.Webp, ImageFormat.Gif, ImageFormat.Jpg, ImageFormat.Png }; - } - return new[] { ImageFormat.Gif, ImageFormat.Jpg, ImageFormat.Png }; - } - } - - private void LogVersion() - { - _logger.Info("ImageMagick version: " + GetVersion()); - TestWebp(); - Wand.SetMagickThreadCount(1); - } - - public static string GetVersion() - { - return Wand.VersionString; - } - - private bool _webpAvailable = true; - private void TestWebp() - { - try - { - var tmpPath = Path.Combine(_appPaths.TempDirectory, Guid.NewGuid() + ".webp"); - _fileSystem.CreateDirectory(Path.GetDirectoryName(tmpPath)); - - using (var wand = new MagickWand(1, 1, new PixelWand("none", 1))) - { - wand.SaveImage(tmpPath); - } - } - catch - { - //_logger.ErrorException("Error loading webp: ", ex); - _webpAvailable = false; - } - } - - public void CropWhiteSpace(string inputPath, string outputPath) - { - CheckDisposed(); - - using (var wand = new MagickWand(inputPath)) - { - wand.CurrentImage.TrimImage(10); - wand.SaveImage(outputPath); - } - } - - public ImageSize GetImageSize(string path) - { - CheckDisposed(); - - using (var wand = new MagickWand()) - { - wand.PingImage(path); - var img = wand.CurrentImage; - - return new ImageSize - { - Width = img.Width, - Height = img.Height - }; - } - } - - private bool HasTransparency(string path) - { - var ext = Path.GetExtension(path); - - return string.Equals(ext, ".png", StringComparison.OrdinalIgnoreCase) || - string.Equals(ext, ".webp", StringComparison.OrdinalIgnoreCase); - } - - public void EncodeImage(string inputPath, string outputPath, bool autoOrient, int width, int height, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat) - { - // Even if the caller specified 100, don't use it because it takes forever - quality = Math.Min(quality, 99); - - if (string.IsNullOrWhiteSpace(options.BackgroundColor) || !HasTransparency(inputPath)) - { - using (var originalImage = new MagickWand(inputPath)) - { - ScaleImage(originalImage, width, height); - - if (autoOrient) - { - AutoOrientImage(originalImage); - } - - AddForegroundLayer(originalImage, options); - DrawIndicator(originalImage, width, height, options); - - originalImage.CurrentImage.CompressionQuality = quality; - originalImage.CurrentImage.StripImage(); - - originalImage.SaveImage(outputPath); - } - } - else - { - using (var wand = new MagickWand(width, height, options.BackgroundColor)) - { - using (var originalImage = new MagickWand(inputPath)) - { - ScaleImage(originalImage, width, height); - - if (autoOrient) - { - AutoOrientImage(originalImage); - } - - wand.CurrentImage.CompositeImage(originalImage, CompositeOperator.OverCompositeOp, 0, 0); - - AddForegroundLayer(wand, options); - DrawIndicator(wand, width, height, options); - - wand.CurrentImage.CompressionQuality = quality; - wand.CurrentImage.StripImage(); - - wand.SaveImage(outputPath); - } - } - } - } - - private void AddForegroundLayer(MagickWand wand, ImageProcessingOptions options) - { - if (string.IsNullOrWhiteSpace(options.ForegroundLayer)) - { - return; - } - - Double opacity; - if (!Double.TryParse(options.ForegroundLayer, out opacity)) opacity = .4; - - using (var pixel = new PixelWand("#000", opacity)) - using (var overlay = new MagickWand(wand.CurrentImage.Width, wand.CurrentImage.Height, pixel)) - { - wand.CurrentImage.CompositeImage(overlay, CompositeOperator.OverCompositeOp, 0, 0); - } - } - - private void AutoOrientImage(MagickWand wand) - { - wand.CurrentImage.AutoOrientImage(); - } - - public static void RotateImage(MagickWand wand, float angle) - { - using (var pixelWand = new PixelWand("none", 1)) - { - wand.CurrentImage.RotateImage(pixelWand, angle); - } - } - - private void ScaleImage(MagickWand wand, int width, int height) - { - var highQuality = false; - - if (highQuality) - { - wand.CurrentImage.ResizeImage(width, height); - } - else - { - wand.CurrentImage.ScaleImage(width, height); - } - } - - /// <summary> - /// Draws the indicator. - /// </summary> - /// <param name="wand">The wand.</param> - /// <param name="imageWidth">Width of the image.</param> - /// <param name="imageHeight">Height of the image.</param> - /// <param name="options">The options.</param> - private void DrawIndicator(MagickWand wand, int imageWidth, int imageHeight, ImageProcessingOptions options) - { - if (!options.AddPlayedIndicator && !options.UnplayedCount.HasValue && options.PercentPlayed.Equals(0)) - { - return; - } - - try - { - if (options.AddPlayedIndicator) - { - var currentImageSize = new ImageSize(imageWidth, imageHeight); - - var task = new PlayedIndicatorDrawer(_appPaths, _httpClient, _fileSystem).DrawPlayedIndicator(wand, currentImageSize); - Task.WaitAll(task); - } - else if (options.UnplayedCount.HasValue) - { - var currentImageSize = new ImageSize(imageWidth, imageHeight); - - new UnplayedCountIndicator(_appPaths, _fileSystem).DrawUnplayedCountIndicator(wand, currentImageSize, options.UnplayedCount.Value); - } - - if (options.PercentPlayed > 0) - { - new PercentPlayedDrawer().Process(wand, options.PercentPlayed); - } - } - catch (Exception ex) - { - _logger.ErrorException("Error drawing indicator overlay", ex); - } - } - - public void CreateImageCollage(ImageCollageOptions options) - { - double ratio = options.Width; - ratio /= options.Height; - - if (ratio >= 1.4) - { - new StripCollageBuilder(_appPaths, _fileSystem).BuildThumbCollage(options.InputPaths.ToList(), options.OutputPath, options.Width, options.Height); - } - else if (ratio >= .9) - { - new StripCollageBuilder(_appPaths, _fileSystem).BuildSquareCollage(options.InputPaths.ToList(), options.OutputPath, options.Width, options.Height); - } - else - { - new StripCollageBuilder(_appPaths, _fileSystem).BuildPosterCollage(options.InputPaths.ToList(), options.OutputPath, options.Width, options.Height); - } - } - - public string Name - { - get { return "ImageMagick"; } - } - - private bool _disposed; - public void Dispose() - { - _disposed = true; - Wand.CloseEnvironment(); - } - - private void CheckDisposed() - { - if (_disposed) - { - throw new ObjectDisposedException(GetType().Name); - } - } - - public bool SupportsImageCollageCreation - { - get { return true; } - } - - public bool SupportsImageEncoding - { - get { return true; } - } - } -} diff --git a/Emby.Drawing/ImageMagick/PercentPlayedDrawer.cs b/Emby.Drawing/ImageMagick/PercentPlayedDrawer.cs deleted file mode 100644 index 90f9d5609..000000000 --- a/Emby.Drawing/ImageMagick/PercentPlayedDrawer.cs +++ /dev/null @@ -1,40 +0,0 @@ -using ImageMagickSharp; -using System; - -namespace Emby.Drawing.ImageMagick -{ - public class PercentPlayedDrawer - { - private const int IndicatorHeight = 8; - - public void Process(MagickWand wand, double percent) - { - var currentImage = wand.CurrentImage; - var height = currentImage.Height; - - using (var draw = new DrawingWand()) - { - using (PixelWand pixel = new PixelWand()) - { - var endX = currentImage.Width - 1; - var endY = height - 1; - - pixel.Color = "black"; - pixel.Opacity = 0.4; - draw.FillColor = pixel; - draw.DrawRectangle(0, endY - IndicatorHeight, endX, endY); - - double foregroundWidth = endX; - foregroundWidth *= percent; - foregroundWidth /= 100; - - pixel.Color = "#52B54B"; - pixel.Opacity = 0; - draw.FillColor = pixel; - draw.DrawRectangle(0, endY - IndicatorHeight, Convert.ToInt32(Math.Round(foregroundWidth)), endY); - wand.CurrentImage.DrawImage(draw); - } - } - } - } -} diff --git a/Emby.Drawing/ImageMagick/PlayedIndicatorDrawer.cs b/Emby.Drawing/ImageMagick/PlayedIndicatorDrawer.cs deleted file mode 100644 index 14fb0ddf1..000000000 --- a/Emby.Drawing/ImageMagick/PlayedIndicatorDrawer.cs +++ /dev/null @@ -1,125 +0,0 @@ -using ImageMagickSharp; -using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Net; -using MediaBrowser.Model.Drawing; -using System; -using System.IO; -using System.Threading.Tasks; -using MediaBrowser.Common.IO; -using MediaBrowser.Controller.IO; -using MediaBrowser.Model.IO; - -namespace Emby.Drawing.ImageMagick -{ - public class PlayedIndicatorDrawer - { - private const int FontSize = 52; - private const int OffsetFromTopRightCorner = 38; - - private readonly IApplicationPaths _appPaths; - private readonly IHttpClient _iHttpClient; - private readonly IFileSystem _fileSystem; - - public PlayedIndicatorDrawer(IApplicationPaths appPaths, IHttpClient iHttpClient, IFileSystem fileSystem) - { - _appPaths = appPaths; - _iHttpClient = iHttpClient; - _fileSystem = fileSystem; - } - - public async Task DrawPlayedIndicator(MagickWand wand, ImageSize imageSize) - { - var x = imageSize.Width - OffsetFromTopRightCorner; - - using (var draw = new DrawingWand()) - { - using (PixelWand pixel = new PixelWand()) - { - pixel.Color = "#52B54B"; - pixel.Opacity = 0.2; - draw.FillColor = pixel; - draw.DrawCircle(x, OffsetFromTopRightCorner, x - 20, OffsetFromTopRightCorner - 20); - - pixel.Opacity = 0; - pixel.Color = "white"; - draw.FillColor = pixel; - draw.Font = await DownloadFont("webdings.ttf", "https://github.com/MediaBrowser/Emby.Resources/raw/master/fonts/webdings.ttf", _appPaths, _iHttpClient, _fileSystem).ConfigureAwait(false); - draw.FontSize = FontSize; - draw.FontStyle = FontStyleType.NormalStyle; - draw.TextAlignment = TextAlignType.CenterAlign; - draw.FontWeight = FontWeightType.RegularStyle; - draw.TextAntialias = true; - draw.DrawAnnotation(x + 4, OffsetFromTopRightCorner + 14, "a"); - - draw.FillColor = pixel; - wand.CurrentImage.DrawImage(draw); - } - } - } - - internal static string ExtractFont(string name, IApplicationPaths paths, IFileSystem fileSystem) - { - var filePath = Path.Combine(paths.ProgramDataPath, "fonts", name); - - if (fileSystem.FileExists(filePath)) - { - return filePath; - } - - var namespacePath = typeof(PlayedIndicatorDrawer).Namespace + ".fonts." + name; - var tempPath = Path.Combine(paths.TempDirectory, Guid.NewGuid().ToString("N") + ".ttf"); - fileSystem.CreateDirectory(Path.GetDirectoryName(tempPath)); - - using (var stream = typeof(PlayedIndicatorDrawer).Assembly.GetManifestResourceStream(namespacePath)) - { - using (var fileStream = new FileStream(tempPath, FileMode.Create, FileAccess.Write, FileShare.Read)) - { - stream.CopyTo(fileStream); - } - } - - fileSystem.CreateDirectory(Path.GetDirectoryName(filePath)); - - try - { - fileSystem.CopyFile(tempPath, filePath, false); - } - catch (IOException) - { - - } - - return tempPath; - } - - internal static async Task<string> DownloadFont(string name, string url, IApplicationPaths paths, IHttpClient httpClient, IFileSystem fileSystem) - { - var filePath = Path.Combine(paths.ProgramDataPath, "fonts", name); - - if (fileSystem.FileExists(filePath)) - { - return filePath; - } - - var tempPath = await httpClient.GetTempFile(new HttpRequestOptions - { - Url = url, - Progress = new Progress<double>() - - }).ConfigureAwait(false); - - fileSystem.CreateDirectory(Path.GetDirectoryName(filePath)); - - try - { - fileSystem.CopyFile(tempPath, filePath, false); - } - catch (IOException) - { - - } - - return tempPath; - } - } -} diff --git a/Emby.Drawing/ImageMagick/StripCollageBuilder.cs b/Emby.Drawing/ImageMagick/StripCollageBuilder.cs deleted file mode 100644 index 715ab4680..000000000 --- a/Emby.Drawing/ImageMagick/StripCollageBuilder.cs +++ /dev/null @@ -1,202 +0,0 @@ -using ImageMagickSharp; -using MediaBrowser.Common.Configuration; -using System; -using System.Collections.Generic; -using MediaBrowser.Common.IO; -using MediaBrowser.Controller.IO; -using MediaBrowser.Model.IO; - -namespace Emby.Drawing.ImageMagick -{ - public class StripCollageBuilder - { - private readonly IApplicationPaths _appPaths; - private readonly IFileSystem _fileSystem; - - public StripCollageBuilder(IApplicationPaths appPaths, IFileSystem fileSystem) - { - _appPaths = appPaths; - _fileSystem = fileSystem; - } - - public void BuildPosterCollage(List<string> paths, string outputPath, int width, int height) - { - using (var wand = BuildPosterCollageWand(paths, width, height)) - { - wand.SaveImage(outputPath); - } - } - - public void BuildSquareCollage(List<string> paths, string outputPath, int width, int height) - { - using (var wand = BuildSquareCollageWand(paths, width, height)) - { - wand.SaveImage(outputPath); - } - } - - public void BuildThumbCollage(List<string> paths, string outputPath, int width, int height) - { - using (var wand = BuildThumbCollageWand(paths, width, height)) - { - wand.SaveImage(outputPath); - } - } - - private MagickWand BuildPosterCollageWand(List<string> paths, int width, int height) - { - var inputPaths = ImageHelpers.ProjectPaths(paths, 3); - using (var wandImages = new MagickWand(inputPaths.ToArray())) - { - var wand = new MagickWand(width, height); - wand.OpenImage("gradient:#111111-#111111"); - using (var draw = new DrawingWand()) - { - var iSlice = Convert.ToInt32(width * 0.3); - int iTrans = Convert.ToInt32(height * .25); - int iHeight = Convert.ToInt32(height * .65); - var horizontalImagePadding = Convert.ToInt32(width * 0.0366); - - foreach (var element in wandImages.ImageList) - { - using (var blackPixelWand = new PixelWand(ColorName.Black)) - { - int iWidth = (int)Math.Abs(iHeight * element.Width / element.Height); - element.Gravity = GravityType.CenterGravity; - element.BackgroundColor = blackPixelWand; - element.ResizeImage(iWidth, iHeight, FilterTypes.LanczosFilter); - int ix = (int)Math.Abs((iWidth - iSlice) / 2); - element.CropImage(iSlice, iHeight, ix, 0); - - element.ExtentImage(iSlice, iHeight, 0 - horizontalImagePadding, 0); - } - } - - wandImages.SetFirstIterator(); - using (var wandList = wandImages.AppendImages()) - { - wandList.CurrentImage.TrimImage(1); - using (var mwr = wandList.CloneMagickWand()) - { - using (var blackPixelWand = new PixelWand(ColorName.Black)) - { - using (var greyPixelWand = new PixelWand(ColorName.Grey70)) - { - mwr.CurrentImage.ResizeImage(wandList.CurrentImage.Width, (wandList.CurrentImage.Height / 2), FilterTypes.LanczosFilter, 1); - mwr.CurrentImage.FlipImage(); - - mwr.CurrentImage.AlphaChannel = AlphaChannelType.DeactivateAlphaChannel; - mwr.CurrentImage.ColorizeImage(blackPixelWand, greyPixelWand); - - using (var mwg = new MagickWand(wandList.CurrentImage.Width, iTrans)) - { - mwg.OpenImage("gradient:black-none"); - var verticalSpacing = Convert.ToInt32(height * 0.01111111111111111111111111111111); - mwr.CurrentImage.CompositeImage(mwg, CompositeOperator.CopyOpacityCompositeOp, 0, verticalSpacing); - - wandList.AddImage(mwr); - int ex = (int)(wand.CurrentImage.Width - mwg.CurrentImage.Width) / 2; - wand.CurrentImage.CompositeImage(wandList.AppendImages(true), CompositeOperator.AtopCompositeOp, ex, Convert.ToInt32(height * .05)); - } - } - } - } - } - } - - return wand; - } - } - - private MagickWand BuildThumbCollageWand(List<string> paths, int width, int height) - { - var inputPaths = ImageHelpers.ProjectPaths(paths, 4); - using (var wandImages = new MagickWand(inputPaths.ToArray())) - { - var wand = new MagickWand(width, height); - wand.OpenImage("gradient:#111111-#111111"); - using (var draw = new DrawingWand()) - { - var iSlice = Convert.ToInt32(width * 0.24125); - int iTrans = Convert.ToInt32(height * .25); - int iHeight = Convert.ToInt32(height * .70); - var horizontalImagePadding = Convert.ToInt32(width * 0.0125); - - foreach (var element in wandImages.ImageList) - { - using (var blackPixelWand = new PixelWand(ColorName.Black)) - { - int iWidth = (int)Math.Abs(iHeight * element.Width / element.Height); - element.Gravity = GravityType.CenterGravity; - element.BackgroundColor = blackPixelWand; - element.ResizeImage(iWidth, iHeight, FilterTypes.LanczosFilter); - int ix = (int)Math.Abs((iWidth - iSlice) / 2); - element.CropImage(iSlice, iHeight, ix, 0); - - element.ExtentImage(iSlice, iHeight, 0 - horizontalImagePadding, 0); - } - } - - wandImages.SetFirstIterator(); - using (var wandList = wandImages.AppendImages()) - { - wandList.CurrentImage.TrimImage(1); - using (var mwr = wandList.CloneMagickWand()) - { - using (var blackPixelWand = new PixelWand(ColorName.Black)) - { - using (var greyPixelWand = new PixelWand(ColorName.Grey70)) - { - mwr.CurrentImage.ResizeImage(wandList.CurrentImage.Width, (wandList.CurrentImage.Height / 2), FilterTypes.LanczosFilter, 1); - mwr.CurrentImage.FlipImage(); - - mwr.CurrentImage.AlphaChannel = AlphaChannelType.DeactivateAlphaChannel; - mwr.CurrentImage.ColorizeImage(blackPixelWand, greyPixelWand); - - using (var mwg = new MagickWand(wandList.CurrentImage.Width, iTrans)) - { - mwg.OpenImage("gradient:black-none"); - var verticalSpacing = Convert.ToInt32(height * 0.01111111111111111111111111111111); - mwr.CurrentImage.CompositeImage(mwg, CompositeOperator.CopyOpacityCompositeOp, 0, verticalSpacing); - - wandList.AddImage(mwr); - int ex = (int)(wand.CurrentImage.Width - mwg.CurrentImage.Width) / 2; - wand.CurrentImage.CompositeImage(wandList.AppendImages(true), CompositeOperator.AtopCompositeOp, ex, Convert.ToInt32(height * .045)); - } - } - } - } - } - } - - return wand; - } - } - - private MagickWand BuildSquareCollageWand(List<string> paths, int width, int height) - { - var inputPaths = ImageHelpers.ProjectPaths(paths, 4); - var outputWand = new MagickWand(width, height, new PixelWand("none", 1)); - var imageIndex = 0; - var cellWidth = width/2; - var cellHeight = height/2; - for (var x = 0; x < 2; x++) - { - for (var y = 0; y < 2; y++) - { - using (var temp = new MagickWand(inputPaths[imageIndex])) - { - temp.CurrentImage.ScaleImage(cellWidth, cellHeight); - // draw this image into the strip at the next position - var xPos = x*cellWidth; - var yPos = y*cellHeight; - outputWand.CurrentImage.CompositeImage(temp, CompositeOperator.OverCompositeOp, xPos, yPos); - } - imageIndex++; - } - } - - return outputWand; - } - } -} diff --git a/Emby.Drawing/ImageMagick/UnplayedCountIndicator.cs b/Emby.Drawing/ImageMagick/UnplayedCountIndicator.cs deleted file mode 100644 index c53140099..000000000 --- a/Emby.Drawing/ImageMagick/UnplayedCountIndicator.cs +++ /dev/null @@ -1,75 +0,0 @@ -using ImageMagickSharp; -using MediaBrowser.Common.Configuration; -using MediaBrowser.Model.Drawing; -using System.Globalization; -using MediaBrowser.Common.IO; -using MediaBrowser.Controller.IO; -using MediaBrowser.Model.IO; - -namespace Emby.Drawing.ImageMagick -{ - public class UnplayedCountIndicator - { - private const int OffsetFromTopRightCorner = 38; - - private readonly IApplicationPaths _appPaths; - private readonly IFileSystem _fileSystem; - - public UnplayedCountIndicator(IApplicationPaths appPaths, IFileSystem fileSystem) - { - _appPaths = appPaths; - _fileSystem = fileSystem; - } - - public void DrawUnplayedCountIndicator(MagickWand wand, ImageSize imageSize, int count) - { - var x = imageSize.Width - OffsetFromTopRightCorner; - var text = count.ToString(CultureInfo.InvariantCulture); - - using (var draw = new DrawingWand()) - { - using (PixelWand pixel = new PixelWand()) - { - pixel.Color = "#52B54B"; - pixel.Opacity = 0.2; - draw.FillColor = pixel; - draw.DrawCircle(x, OffsetFromTopRightCorner, x - 20, OffsetFromTopRightCorner - 20); - - pixel.Opacity = 0; - pixel.Color = "white"; - draw.FillColor = pixel; - draw.Font = PlayedIndicatorDrawer.ExtractFont("robotoregular.ttf", _appPaths, _fileSystem); - draw.FontStyle = FontStyleType.NormalStyle; - draw.TextAlignment = TextAlignType.CenterAlign; - draw.FontWeight = FontWeightType.RegularStyle; - draw.TextAntialias = true; - - var fontSize = 30; - var y = OffsetFromTopRightCorner + 11; - - if (text.Length == 1) - { - x += 1; - } - else if (text.Length == 2) - { - x += 1; - } - else if (text.Length >= 3) - { - //x += 1; - y -= 2; - fontSize = 24; - } - - draw.FontSize = fontSize; - draw.DrawAnnotation(x, y, text); - - draw.FillColor = pixel; - wand.CurrentImage.DrawImage(draw); - } - - } - } - } -} diff --git a/Emby.Drawing/ImageProcessor.cs b/Emby.Drawing/ImageProcessor.cs index aa1805871..292896856 100644 --- a/Emby.Drawing/ImageProcessor.cs +++ b/Emby.Drawing/ImageProcessor.cs @@ -21,8 +21,8 @@ using MediaBrowser.Common.IO; using MediaBrowser.Controller.IO; using MediaBrowser.Controller.Library; using MediaBrowser.Model.Net; +using MediaBrowser.Model.Threading; using TagLib; -using File = System.IO.File; namespace Emby.Drawing { @@ -65,7 +65,7 @@ namespace Emby.Drawing IFileSystem fileSystem, IJsonSerializer jsonSerializer, IImageEncoder imageEncoder, - int maxConcurrentImageProcesses, Func<ILibraryManager> libraryManager) + int maxConcurrentImageProcesses, Func<ILibraryManager> libraryManager, ITimerFactory timerFactory) { _logger = logger; _fileSystem = fileSystem; @@ -75,7 +75,7 @@ namespace Emby.Drawing _appPaths = appPaths; ImageEnhancers = new List<IImageEnhancer>(); - _saveImageSizeTimer = new Timer(SaveImageSizeCallback, null, Timeout.Infinite, Timeout.Infinite); + _saveImageSizeTimer = timerFactory.Create(SaveImageSizeCallback, null, Timeout.Infinite, Timeout.Infinite); Dictionary<Guid, ImageSize> sizeDictionary; @@ -89,7 +89,7 @@ namespace Emby.Drawing // No biggie sizeDictionary = new Dictionary<Guid, ImageSize>(); } - catch (DirectoryNotFoundException) + catch (IOException) { // No biggie sizeDictionary = new Dictionary<Guid, ImageSize>(); @@ -286,7 +286,7 @@ namespace Emby.Drawing { try { - File.Copy(src, destination, true); + _fileSystem.CopyFile(src, destination, true); } catch { @@ -600,7 +600,7 @@ namespace Emby.Drawing return ImageHeader.GetDimensions(path, _logger, _fileSystem); } - private readonly Timer _saveImageSizeTimer; + private readonly ITimer _saveImageSizeTimer; private const int SaveImageSizeTimeout = 5000; private readonly object _saveImageSizeLock = new object(); private void StartSaveImageSizeTimer() @@ -801,7 +801,7 @@ namespace Emby.Drawing try { - File.Copy(tmpPath, enhancedImagePath, true); + _fileSystem.CopyFile(tmpPath, enhancedImagePath, true); } catch { diff --git a/Emby.Drawing/packages.config b/Emby.Drawing/packages.config deleted file mode 100644 index be2fb4187..000000000 --- a/Emby.Drawing/packages.config +++ /dev/null @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<packages> - <package id="ImageMagickSharp" version="1.0.0.18" targetFramework="net45" /> -</packages>
\ No newline at end of file diff --git a/Emby.Drawing/project.json b/Emby.Drawing/project.json new file mode 100644 index 000000000..fbbe9eaf3 --- /dev/null +++ b/Emby.Drawing/project.json @@ -0,0 +1,17 @@ +{ + "frameworks":{ + "netstandard1.6":{ + "dependencies":{ + "NETStandard.Library":"1.6.0", + } + }, + ".NETPortable,Version=v4.5,Profile=Profile7":{ + "buildOptions": { + "define": [ ] + }, + "frameworkAssemblies":{ + + } + } + } +}
\ No newline at end of file |
