diff options
| author | Luke Pulverenti <luke.pulverenti@gmail.com> | 2017-06-09 15:24:31 -0400 |
|---|---|---|
| committer | Luke Pulverenti <luke.pulverenti@gmail.com> | 2017-06-09 15:24:31 -0400 |
| commit | d76bcd8473c7a0d554168ea5b05554e2a7e560f7 (patch) | |
| tree | d82fca3610657edb2df085467be5b8bff2e7d7f4 /Emby.Drawing.Skia | |
| parent | e2ec83cbaae3d2d711126a2c29b3f112c613dda4 (diff) | |
fix photo orientation
Diffstat (limited to 'Emby.Drawing.Skia')
| -rw-r--r-- | Emby.Drawing.Skia/SkiaEncoder.cs | 121 |
1 files changed, 112 insertions, 9 deletions
diff --git a/Emby.Drawing.Skia/SkiaEncoder.cs b/Emby.Drawing.Skia/SkiaEncoder.cs index 8a38b9248..2c7dc58c2 100644 --- a/Emby.Drawing.Skia/SkiaEncoder.cs +++ b/Emby.Drawing.Skia/SkiaEncoder.cs @@ -184,7 +184,7 @@ namespace Emby.Drawing.Skia } private string[] TransparentImageTypes = new string[] { ".png", ".gif", ".webp" }; - private SKBitmap Decode(string path, bool forceCleanBitmap = false) + private SKBitmap Decode(string path, bool forceCleanBitmap, out SKCodecOrigin origin) { var requiresTransparencyHack = TransparentImageTypes.Contains(Path.GetExtension(path) ?? string.Empty); @@ -199,6 +199,8 @@ namespace Emby.Drawing.Skia // decode codec.GetPixels(bitmap.Info, bitmap.GetPixels()); + origin = codec.Origin; + return bitmap; } } @@ -207,7 +209,7 @@ namespace Emby.Drawing.Skia if (resultBitmap == null) { - return Decode(path, true); + return Decode(path, true, out origin); } // If we have to resize these they often end up distorted @@ -215,27 +217,128 @@ namespace Emby.Drawing.Skia { using (resultBitmap) { - return Decode(path, true); + return Decode(path, true, out origin); } } + origin = SKCodecOrigin.TopLeft; return resultBitmap; } - private SKBitmap GetBitmap(string path, bool cropWhitespace) + private SKBitmap GetBitmap(string path, bool cropWhitespace, bool forceAnalyzeBitmap, out SKCodecOrigin origin) { if (cropWhitespace) { - using (var bitmap = Decode(path)) + using (var bitmap = Decode(path, forceAnalyzeBitmap, out origin)) { return CropWhiteSpace(bitmap); } } - return Decode(path); + return Decode(path, forceAnalyzeBitmap, out origin); + } + + private SKBitmap GetBitmap(string path, bool cropWhitespace, bool autoOrient, ImageOrientation? orientation) + { + SKCodecOrigin origin; + + if (autoOrient) + { + var bitmap = GetBitmap(path, cropWhitespace, true, out origin); + + if (origin != SKCodecOrigin.TopLeft) + { + using (bitmap) + { + return RotateAndFlip(bitmap, origin); + } + } + + return bitmap; + } + + return GetBitmap(path, cropWhitespace, false, out origin); + } + + private SKBitmap RotateAndFlip(SKBitmap original, SKCodecOrigin origin) + { + // these are the origins that represent a 90 degree turn in some fashion + var differentOrientations = new SKCodecOrigin[] + { + SKCodecOrigin.LeftBottom, + SKCodecOrigin.LeftTop, + SKCodecOrigin.RightBottom, + SKCodecOrigin.RightTop + }; + + // check if we need to turn the image + bool isDifferentOrientation = differentOrientations.Any(o => o == origin); + + // define new width/height + var width = isDifferentOrientation ? original.Height : original.Width; + var height = isDifferentOrientation ? original.Width : original.Height; + + var bitmap = new SKBitmap(width, height, true); + + // todo: the stuff in this switch statement should be rewritten to use pointers + switch (origin) + { + case SKCodecOrigin.LeftBottom: + + for (var x = 0; x < original.Width; x++) + for (var y = 0; y < original.Height; y++) + bitmap.SetPixel(y, original.Width - 1 - x, original.GetPixel(x, y)); + break; + + case SKCodecOrigin.RightTop: + + for (var x = 0; x < original.Width; x++) + for (var y = 0; y < original.Height; y++) + bitmap.SetPixel(original.Height - 1 - y, x, original.GetPixel(x, y)); + break; + + case SKCodecOrigin.RightBottom: + + for (var x = 0; x < original.Width; x++) + for (var y = 0; y < original.Height; y++) + bitmap.SetPixel(original.Height - 1 - y, original.Width - 1 - x, original.GetPixel(x, y)); + + break; + + case SKCodecOrigin.LeftTop: + + for (var x = 0; x < original.Width; x++) + for (var y = 0; y < original.Height; y++) + bitmap.SetPixel(y, x, original.GetPixel(x, y)); + break; + + case SKCodecOrigin.BottomLeft: + + for (var x = 0; x < original.Width; x++) + for (var y = 0; y < original.Height; y++) + bitmap.SetPixel(x, original.Height - 1 - y, original.GetPixel(x, y)); + break; + + case SKCodecOrigin.BottomRight: + + for (var x = 0; x < original.Width; x++) + for (var y = 0; y < original.Height; y++) + bitmap.SetPixel(original.Width - 1 - x, original.Height - 1 - y, original.GetPixel(x, y)); + break; + + case SKCodecOrigin.TopRight: + + for (var x = 0; x < original.Width; x++) + for (var y = 0; y < original.Height; y++) + bitmap.SetPixel(original.Width - 1 - x, y, original.GetPixel(x, y)); + break; + + } + + return bitmap; } - public string EncodeImage(string inputPath, DateTime dateModified, string outputPath, bool autoOrient, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat) + public string EncodeImage(string inputPath, DateTime dateModified, string outputPath, bool autoOrient, ImageOrientation? orientation, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat) { if (string.IsNullOrWhiteSpace(inputPath)) { @@ -253,7 +356,7 @@ namespace Emby.Drawing.Skia var blur = options.Blur ?? 0; var hasIndicator = options.AddPlayedIndicator || options.UnplayedCount.HasValue || !options.PercentPlayed.Equals(0); - using (var bitmap = GetBitmap(inputPath, options.CropWhiteSpace)) + using (var bitmap = GetBitmap(inputPath, options.CropWhiteSpace, autoOrient, orientation)) { if (bitmap == null) { @@ -265,7 +368,7 @@ namespace Emby.Drawing.Skia var originalImageSize = new ImageSize(bitmap.Width, bitmap.Height); ImageHelper.SaveImageSize(inputPath, dateModified, originalImageSize); - if (!options.CropWhiteSpace && options.HasDefaultOptions(inputPath, originalImageSize)) + if (!options.CropWhiteSpace && options.HasDefaultOptions(inputPath, originalImageSize) && !autoOrient) { // Just spit out the original file if all the options are default return inputPath; |
