From aaf316884d4e705a9dc47002f492f28649e4821b Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 21 Jan 2016 03:23:02 -0500 Subject: [PATCH] support photo orientation --- Emby.Drawing/GDI/GDIImageEncoder.cs | 2 +- Emby.Drawing/IImageEncoder.cs | 3 +- .../ImageMagick/ImageMagickEncoder.cs | 20 +++++++++++- Emby.Drawing/ImageProcessor.cs | 31 ++++++++++++++++++- Emby.Drawing/NullImageEncoder.cs | 2 +- .../Dto/DtoService.cs | 26 ++++++++++++++-- 6 files changed, 76 insertions(+), 8 deletions(-) diff --git a/Emby.Drawing/GDI/GDIImageEncoder.cs b/Emby.Drawing/GDI/GDIImageEncoder.cs index 3df84cf112..51b4605c33 100644 --- a/Emby.Drawing/GDI/GDIImageEncoder.cs +++ b/Emby.Drawing/GDI/GDIImageEncoder.cs @@ -89,7 +89,7 @@ namespace Emby.Drawing.GDI } } - public void EncodeImage(string inputPath, string cacheFilePath, int width, int height, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat) + public void EncodeImage(string inputPath, string cacheFilePath, int rotationAngle, int width, int height, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat) { var hasPostProcessing = !string.IsNullOrEmpty(options.BackgroundColor) || options.UnplayedCount.HasValue || options.AddPlayedIndicator || options.PercentPlayed > 0; diff --git a/Emby.Drawing/IImageEncoder.cs b/Emby.Drawing/IImageEncoder.cs index bfd382bb7c..f36498be76 100644 --- a/Emby.Drawing/IImageEncoder.cs +++ b/Emby.Drawing/IImageEncoder.cs @@ -27,12 +27,13 @@ namespace Emby.Drawing /// /// The input path. /// The output path. + /// The rotation angle. /// The width. /// The height. /// The quality. /// The options. /// The output format. - void EncodeImage(string inputPath, string outputPath, int width, int height, int quality, ImageProcessingOptions options, ImageFormat outputFormat); + void EncodeImage(string inputPath, string outputPath, int rotationAngle, int width, int height, int quality, ImageProcessingOptions options, ImageFormat outputFormat); /// /// Creates the image collage. diff --git a/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs b/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs index 6858c6d520..fd9ed5f1e5 100644 --- a/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs +++ b/Emby.Drawing/ImageMagick/ImageMagickEncoder.cs @@ -139,7 +139,7 @@ namespace Emby.Drawing.ImageMagick string.Equals(ext, ".webp", StringComparison.OrdinalIgnoreCase); } - public void EncodeImage(string inputPath, string outputPath, int width, int height, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat) + public void EncodeImage(string inputPath, string outputPath, int rotationAngle, 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); @@ -150,6 +150,11 @@ namespace Emby.Drawing.ImageMagick { ScaleImage(originalImage, width, height); + if (rotationAngle > 0) + { + RotateImage(originalImage, rotationAngle); + } + DrawIndicator(originalImage, width, height, options); originalImage.CurrentImage.CompressionQuality = quality; @@ -166,6 +171,11 @@ namespace Emby.Drawing.ImageMagick { ScaleImage(originalImage, width, height); + if (rotationAngle > 0) + { + RotateImage(originalImage, rotationAngle); + } + wand.CurrentImage.CompositeImage(originalImage, CompositeOperator.OverCompositeOp, 0, 0); DrawIndicator(wand, width, height, options); @@ -179,6 +189,14 @@ namespace Emby.Drawing.ImageMagick SaveDelay(); } + 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; diff --git a/Emby.Drawing/ImageProcessor.cs b/Emby.Drawing/ImageProcessor.cs index e1b92bbffc..9de6d20427 100644 --- a/Emby.Drawing/ImageProcessor.cs +++ b/Emby.Drawing/ImageProcessor.cs @@ -257,7 +257,7 @@ namespace Emby.Drawing imageProcessingLockTaken = true; - _imageEncoder.EncodeImage(originalImagePath, cacheFilePath, newWidth, newHeight, quality, options, outputFormat); + _imageEncoder.EncodeImage(originalImagePath, cacheFilePath, GetRotationAngle(options.Item), newWidth, newHeight, quality, options, outputFormat); } return new Tuple(cacheFilePath, GetMimeType(outputFormat, cacheFilePath)); @@ -281,6 +281,35 @@ namespace Emby.Drawing } } + private int GetRotationAngle(IHasImages item) + { + var photo = item as Photo; + if (photo != null && photo.Orientation.HasValue) + { + switch (photo.Orientation.Value) + { + case ImageOrientation.TopLeft: + return 0; + case ImageOrientation.TopRight: + return 0; + case ImageOrientation.BottomLeft: + return 270; + case ImageOrientation.BottomRight: + return 180; + case ImageOrientation.LeftBottom: + return -90; + case ImageOrientation.LeftTop: + return 0; + case ImageOrientation.RightBottom: + return 0; + case ImageOrientation.RightTop: + return 90; + } + } + + return 0; + } + private string GetMimeType(ImageFormat format, string path) { if (format == ImageFormat.Bmp) diff --git a/Emby.Drawing/NullImageEncoder.cs b/Emby.Drawing/NullImageEncoder.cs index 1638a675ac..032335a460 100644 --- a/Emby.Drawing/NullImageEncoder.cs +++ b/Emby.Drawing/NullImageEncoder.cs @@ -32,7 +32,7 @@ namespace Emby.Drawing throw new NotImplementedException(); } - public void EncodeImage(string inputPath, string outputPath, int width, int height, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat) + public void EncodeImage(string inputPath, string outputPath, int rotationAngle, int width, int height, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat) { throw new NotImplementedException(); } diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs index b0071828e2..0cd551f6a7 100644 --- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs +++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs @@ -1783,11 +1783,31 @@ namespace MediaBrowser.Server.Implementations.Dto } } - if (size.Width > 0 && size.Height > 0) + var width = size.Width; + var height = size.Height; + + if (width == 0 || height == 0) { - return size.Width / size.Height; + return null; } - return null; + + var photo = item as Photo; + if (photo != null && photo.Orientation.HasValue) + { + switch (photo.Orientation.Value) + { + case ImageOrientation.LeftBottom: + case ImageOrientation.LeftTop: + case ImageOrientation.RightBottom: + case ImageOrientation.RightTop: + var temp = height; + height = width; + width = temp; + break; + } + } + + return width / height; } } }