From e4893e850a229f577425c320f86d559c8df51782 Mon Sep 17 00:00:00 2001 From: JimBobSquarePants Date: Wed, 6 Sep 2017 10:46:39 +1000 Subject: [PATCH] Fix AutoOrientProcessor --- .../DefaultInternalImageProcessorContext.cs | 3 +- src/ImageSharp/Image/ImageFrame{TPixel}.cs | 6 +- .../Processing/Processors/ImageProcessor.cs | 1 - .../Transforms/AutoOrientProcessor.cs | 103 ++++++++++++++++ .../Transforms/AutoRotateProcessor.cs | 110 ------------------ .../Processing/Transforms/AutoOrient.cs | 2 +- .../Processing/Transforms/AutoOrientTests.cs | 2 +- 7 files changed, 109 insertions(+), 118 deletions(-) create mode 100644 src/ImageSharp/Processing/Processors/Transforms/AutoOrientProcessor.cs delete mode 100644 src/ImageSharp/Processing/Processors/Transforms/AutoRotateProcessor.cs diff --git a/src/ImageSharp/DefaultInternalImageProcessorContext.cs b/src/ImageSharp/DefaultInternalImageProcessorContext.cs index 2e2602d3c..575525a77 100644 --- a/src/ImageSharp/DefaultInternalImageProcessorContext.cs +++ b/src/ImageSharp/DefaultInternalImageProcessorContext.cs @@ -54,8 +54,7 @@ namespace SixLabors.ImageSharp // This will only work if the first processor applied is the cloning one thus // realistically for this optermissation to work the resize must the first processor // applied any only up processors will take the douple data path. - var cloningImageProcessor = processor as ICloningImageProcessor; - if (cloningImageProcessor != null) + if (processor is ICloningImageProcessor cloningImageProcessor) { this.destination = cloningImageProcessor.CloneAndApply(this.source, rectangle); return this; diff --git a/src/ImageSharp/Image/ImageFrame{TPixel}.cs b/src/ImageSharp/Image/ImageFrame{TPixel}.cs index 9d6b945ab..063108515 100644 --- a/src/ImageSharp/Image/ImageFrame{TPixel}.cs +++ b/src/ImageSharp/Image/ImageFrame{TPixel}.cs @@ -155,7 +155,7 @@ namespace SixLabors.ImageSharp Guard.NotNull(pixelSource, nameof(pixelSource)); // Push my memory into the accessor (which in turn unpins the old buffer ready for the images use) - var newPixels = pixelSource.SwapBufferOwnership(this.pixelBuffer); + Buffer2D newPixels = pixelSource.SwapBufferOwnership(this.pixelBuffer); this.pixelBuffer = newPixels; } @@ -169,7 +169,7 @@ namespace SixLabors.ImageSharp int newWidth = pixelSource.Width; int newHeight = pixelSource.Height; - var newPixels = pixelSource.pixelBuffer; + Buffer2D newPixels = pixelSource.pixelBuffer; pixelSource.pixelBuffer = this.pixelBuffer; @@ -227,7 +227,7 @@ namespace SixLabors.ImageSharp { for (int x = 0; x < target.Width; x++) { - TPixel2 color = default(TPixel2); + var color = default(TPixel2); color.PackFromVector4(scaleFunc(pixels[x, y].ToVector4())); targetPixels[x, y] = color; } diff --git a/src/ImageSharp/Processing/Processors/ImageProcessor.cs b/src/ImageSharp/Processing/Processors/ImageProcessor.cs index 46f8f2525..26e084305 100644 --- a/src/ImageSharp/Processing/Processors/ImageProcessor.cs +++ b/src/ImageSharp/Processing/Processors/ImageProcessor.cs @@ -25,7 +25,6 @@ namespace SixLabors.ImageSharp.Processing foreach (ImageFrame sourceFrame in source.Frames) { this.BeforeApply(sourceFrame, sourceRectangle); - this.OnApply(sourceFrame, sourceRectangle); this.AfterApply(sourceFrame, sourceRectangle); } diff --git a/src/ImageSharp/Processing/Processors/Transforms/AutoOrientProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/AutoOrientProcessor.cs new file mode 100644 index 000000000..f18d775f5 --- /dev/null +++ b/src/ImageSharp/Processing/Processors/Transforms/AutoOrientProcessor.cs @@ -0,0 +1,103 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; + +using SixLabors.ImageSharp.MetaData.Profiles.Exif; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.Primitives; + +namespace SixLabors.ImageSharp.Processing.Processors +{ + /// + /// Adjusts an image so that its orientation is suitable for viewing. Adjustments are based on EXIF metadata embedded in the image. + /// + /// The pixel format. + internal class AutoOrientProcessor : ImageProcessor + where TPixel : struct, IPixel + { + /// + protected override void BeforeImageApply(Image source, Rectangle sourceRectangle) + { + Orientation orientation = GetExifOrientation(source); + + switch (orientation) + { + case Orientation.TopRight: + new FlipProcessor(FlipType.Horizontal).Apply(source, sourceRectangle); + break; + + case Orientation.BottomRight: + new RotateProcessor { Angle = (int)RotateType.Rotate180, Expand = false }.Apply(source, sourceRectangle); + break; + + case Orientation.BottomLeft: + new FlipProcessor(FlipType.Vertical).Apply(source, sourceRectangle); + break; + + case Orientation.LeftTop: + new RotateProcessor { Angle = (int)RotateType.Rotate90, Expand = false }.Apply(source, sourceRectangle); + new FlipProcessor(FlipType.Horizontal).Apply(source, sourceRectangle); + break; + + case Orientation.RightTop: + new RotateProcessor { Angle = (int)RotateType.Rotate90, Expand = false }.Apply(source, sourceRectangle); + break; + + case Orientation.RightBottom: + new FlipProcessor(FlipType.Vertical).Apply(source, sourceRectangle); + new RotateProcessor { Angle = (int)RotateType.Rotate270, Expand = false }.Apply(source, sourceRectangle); + break; + + case Orientation.LeftBottom: + new RotateProcessor { Angle = (int)RotateType.Rotate270, Expand = false }.Apply(source, sourceRectangle); + break; + + case Orientation.Unknown: + case Orientation.TopLeft: + default: + break; + } + } + + /// + protected override void OnApply(ImageFrame source, Rectangle sourceRectangle) + { + // Nothing required here + } + + /// + /// Returns the current EXIF orientation + /// + /// The image to auto rotate. + /// The + private static Orientation GetExifOrientation(Image source) + { + if (source.MetaData.ExifProfile == null) + { + return Orientation.Unknown; + } + + ExifValue value = source.MetaData.ExifProfile.GetValue(ExifTag.Orientation); + if (value == null) + { + return Orientation.Unknown; + } + + Orientation orientation; + if (value.DataType == ExifDataType.Short) + { + orientation = (Orientation)value.Value; + } + else + { + orientation = (Orientation)Convert.ToUInt16(value.Value); + source.MetaData.ExifProfile.RemoveValue(ExifTag.Orientation); + } + + source.MetaData.ExifProfile.SetValue(ExifTag.Orientation, (ushort)Orientation.TopLeft); + + return orientation; + } + } +} \ No newline at end of file diff --git a/src/ImageSharp/Processing/Processors/Transforms/AutoRotateProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/AutoRotateProcessor.cs deleted file mode 100644 index a84a7b189..000000000 --- a/src/ImageSharp/Processing/Processors/Transforms/AutoRotateProcessor.cs +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; -using System.Threading.Tasks; -using SixLabors.ImageSharp.Memory; -using SixLabors.ImageSharp.MetaData.Profiles.Exif; -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.Primitives; - -namespace SixLabors.ImageSharp.Processing.Processors -{ - /// - /// Adjusts an image so that its orientation is suitable for viewing. Adjustments are based on EXIF metadata embedded in the image. - /// - /// The pixel format. - internal class AutoRotateProcessor : ImageProcessor - where TPixel : struct, IPixel - { - /// - /// Initializes a new instance of the class. - /// - public AutoRotateProcessor() - { - } - - /// - protected override void OnApply(ImageFrame sourceBase, Rectangle sourceRectangle) - { - // can only apply to the origional image - var source = sourceBase as Image; - if (source != null) - { - Orientation orientation = GetExifOrientation(source); - - switch (orientation) - { - case Orientation.TopRight: - new FlipProcessor(FlipType.Horizontal).Apply(source, sourceRectangle); - break; - - case Orientation.BottomRight: - new RotateProcessor() { Angle = (int)RotateType.Rotate180, Expand = false }.Apply(source, sourceRectangle); - break; - - case Orientation.BottomLeft: - new FlipProcessor(FlipType.Vertical).Apply(source, sourceRectangle); - break; - - case Orientation.LeftTop: - new RotateProcessor() { Angle = (int)RotateType.Rotate90, Expand = false }.Apply(source, sourceRectangle); - new FlipProcessor(FlipType.Horizontal).Apply(source, sourceRectangle); - break; - - case Orientation.RightTop: - new RotateProcessor() { Angle = (int)RotateType.Rotate90, Expand = false }.Apply(source, sourceRectangle); - break; - - case Orientation.RightBottom: - new FlipProcessor(FlipType.Vertical).Apply(source, sourceRectangle); - new RotateProcessor() { Angle = (int)RotateType.Rotate270, Expand = false }.Apply(source, sourceRectangle); - break; - - case Orientation.LeftBottom: - new RotateProcessor() { Angle = (int)RotateType.Rotate270, Expand = false }.Apply(source, sourceRectangle); - break; - - case Orientation.Unknown: - case Orientation.TopLeft: - default: - break; - } - } - } - - /// - /// Returns the current EXIF orientation - /// - /// The image to auto rotate. - /// The - private static Orientation GetExifOrientation(Image source) - { - if (source.MetaData.ExifProfile == null) - { - return Orientation.Unknown; - } - - ExifValue value = source.MetaData.ExifProfile.GetValue(ExifTag.Orientation); - if (value == null) - { - return Orientation.Unknown; - } - - Orientation orientation; - if (value.DataType == ExifDataType.Short) - { - orientation = (Orientation)value.Value; - } - else - { - orientation = (Orientation)Convert.ToUInt16(value.Value); - source.MetaData.ExifProfile.RemoveValue(ExifTag.Orientation); - } - - source.MetaData.ExifProfile.SetValue(ExifTag.Orientation, (ushort)Orientation.TopLeft); - - return orientation; - } - } -} \ No newline at end of file diff --git a/src/ImageSharp/Processing/Transforms/AutoOrient.cs b/src/ImageSharp/Processing/Transforms/AutoOrient.cs index 186c3b223..6e5a8829f 100644 --- a/src/ImageSharp/Processing/Transforms/AutoOrient.cs +++ b/src/ImageSharp/Processing/Transforms/AutoOrient.cs @@ -20,6 +20,6 @@ namespace SixLabors.ImageSharp /// The public static IImageProcessingContext AutoOrient(this IImageProcessingContext source) where TPixel : struct, IPixel - => source.ApplyProcessor(new Processing.Processors.AutoRotateProcessor()); + => source.ApplyProcessor(new Processing.Processors.AutoOrientProcessor()); } } \ No newline at end of file diff --git a/tests/ImageSharp.Tests/Processing/Transforms/AutoOrientTests.cs b/tests/ImageSharp.Tests/Processing/Transforms/AutoOrientTests.cs index dbb2d8415..fd4c333d5 100644 --- a/tests/ImageSharp.Tests/Processing/Transforms/AutoOrientTests.cs +++ b/tests/ImageSharp.Tests/Processing/Transforms/AutoOrientTests.cs @@ -15,7 +15,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Transforms public void AutoOrient_AutoRotateProcessor() { this.operations.AutoOrient(); - this.Verify>(); + this.Verify>(); } } } \ No newline at end of file