aboutsummaryrefslogtreecommitdiff
path: root/Emby.Drawing
diff options
context:
space:
mode:
Diffstat (limited to 'Emby.Drawing')
-rw-r--r--Emby.Drawing/Common/ImageHeader.cs2
-rw-r--r--Emby.Drawing/Emby.Drawing.csproj42
-rw-r--r--Emby.Drawing/GDI/DynamicImageHelpers.cs110
-rw-r--r--Emby.Drawing/GDI/GDIImageEncoder.cs281
-rw-r--r--Emby.Drawing/GDI/ImageExtensions.cs217
-rw-r--r--Emby.Drawing/GDI/PercentPlayedDrawer.cs34
-rw-r--r--Emby.Drawing/GDI/PlayedIndicatorDrawer.cs32
-rw-r--r--Emby.Drawing/GDI/UnplayedCountIndicator.cs50
-rw-r--r--Emby.Drawing/GDI/empty.pngbin158 -> 0 bytes
-rw-r--r--Emby.Drawing/IImageEncoder.cs61
-rw-r--r--Emby.Drawing/ImageHelpers.cs43
-rw-r--r--Emby.Drawing/ImageMagick/ImageMagickEncoder.cs333
-rw-r--r--Emby.Drawing/ImageMagick/PercentPlayedDrawer.cs40
-rw-r--r--Emby.Drawing/ImageMagick/PlayedIndicatorDrawer.cs125
-rw-r--r--Emby.Drawing/ImageMagick/StripCollageBuilder.cs202
-rw-r--r--Emby.Drawing/ImageMagick/UnplayedCountIndicator.cs75
-rw-r--r--Emby.Drawing/ImageProcessor.cs14
-rw-r--r--Emby.Drawing/packages.config4
-rw-r--r--Emby.Drawing/project.json17
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
deleted file mode 100644
index 42e2b375e..000000000
--- a/Emby.Drawing/GDI/empty.png
+++ /dev/null
Binary files differ
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