mirror of https://github.com/SixLabors/ImageSharp
7 changed files with 109 additions and 118 deletions
@ -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 |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Adjusts an image so that its orientation is suitable for viewing. Adjustments are based on EXIF metadata embedded in the image.
|
||||
|
/// </summary>
|
||||
|
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
||||
|
internal class AutoOrientProcessor<TPixel> : ImageProcessor<TPixel> |
||||
|
where TPixel : struct, IPixel<TPixel> |
||||
|
{ |
||||
|
/// <inheritdoc/>
|
||||
|
protected override void BeforeImageApply(Image<TPixel> source, Rectangle sourceRectangle) |
||||
|
{ |
||||
|
Orientation orientation = GetExifOrientation(source); |
||||
|
|
||||
|
switch (orientation) |
||||
|
{ |
||||
|
case Orientation.TopRight: |
||||
|
new FlipProcessor<TPixel>(FlipType.Horizontal).Apply(source, sourceRectangle); |
||||
|
break; |
||||
|
|
||||
|
case Orientation.BottomRight: |
||||
|
new RotateProcessor<TPixel> { Angle = (int)RotateType.Rotate180, Expand = false }.Apply(source, sourceRectangle); |
||||
|
break; |
||||
|
|
||||
|
case Orientation.BottomLeft: |
||||
|
new FlipProcessor<TPixel>(FlipType.Vertical).Apply(source, sourceRectangle); |
||||
|
break; |
||||
|
|
||||
|
case Orientation.LeftTop: |
||||
|
new RotateProcessor<TPixel> { Angle = (int)RotateType.Rotate90, Expand = false }.Apply(source, sourceRectangle); |
||||
|
new FlipProcessor<TPixel>(FlipType.Horizontal).Apply(source, sourceRectangle); |
||||
|
break; |
||||
|
|
||||
|
case Orientation.RightTop: |
||||
|
new RotateProcessor<TPixel> { Angle = (int)RotateType.Rotate90, Expand = false }.Apply(source, sourceRectangle); |
||||
|
break; |
||||
|
|
||||
|
case Orientation.RightBottom: |
||||
|
new FlipProcessor<TPixel>(FlipType.Vertical).Apply(source, sourceRectangle); |
||||
|
new RotateProcessor<TPixel> { Angle = (int)RotateType.Rotate270, Expand = false }.Apply(source, sourceRectangle); |
||||
|
break; |
||||
|
|
||||
|
case Orientation.LeftBottom: |
||||
|
new RotateProcessor<TPixel> { Angle = (int)RotateType.Rotate270, Expand = false }.Apply(source, sourceRectangle); |
||||
|
break; |
||||
|
|
||||
|
case Orientation.Unknown: |
||||
|
case Orientation.TopLeft: |
||||
|
default: |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <inheritdoc />
|
||||
|
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle) |
||||
|
{ |
||||
|
// Nothing required here
|
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Returns the current EXIF orientation
|
||||
|
/// </summary>
|
||||
|
/// <param name="source">The image to auto rotate.</param>
|
||||
|
/// <returns>The <see cref="Orientation"/></returns>
|
||||
|
private static Orientation GetExifOrientation(Image<TPixel> 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; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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 |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// Adjusts an image so that its orientation is suitable for viewing. Adjustments are based on EXIF metadata embedded in the image.
|
|
||||
/// </summary>
|
|
||||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|
||||
internal class AutoRotateProcessor<TPixel> : ImageProcessor<TPixel> |
|
||||
where TPixel : struct, IPixel<TPixel> |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// Initializes a new instance of the <see cref="AutoRotateProcessor{TPixel}"/> class.
|
|
||||
/// </summary>
|
|
||||
public AutoRotateProcessor() |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
/// <inheritdoc/>
|
|
||||
protected override void OnApply(ImageFrame<TPixel> sourceBase, Rectangle sourceRectangle) |
|
||||
{ |
|
||||
// can only apply to the origional image
|
|
||||
var source = sourceBase as Image<TPixel>; |
|
||||
if (source != null) |
|
||||
{ |
|
||||
Orientation orientation = GetExifOrientation(source); |
|
||||
|
|
||||
switch (orientation) |
|
||||
{ |
|
||||
case Orientation.TopRight: |
|
||||
new FlipProcessor<TPixel>(FlipType.Horizontal).Apply(source, sourceRectangle); |
|
||||
break; |
|
||||
|
|
||||
case Orientation.BottomRight: |
|
||||
new RotateProcessor<TPixel>() { Angle = (int)RotateType.Rotate180, Expand = false }.Apply(source, sourceRectangle); |
|
||||
break; |
|
||||
|
|
||||
case Orientation.BottomLeft: |
|
||||
new FlipProcessor<TPixel>(FlipType.Vertical).Apply(source, sourceRectangle); |
|
||||
break; |
|
||||
|
|
||||
case Orientation.LeftTop: |
|
||||
new RotateProcessor<TPixel>() { Angle = (int)RotateType.Rotate90, Expand = false }.Apply(source, sourceRectangle); |
|
||||
new FlipProcessor<TPixel>(FlipType.Horizontal).Apply(source, sourceRectangle); |
|
||||
break; |
|
||||
|
|
||||
case Orientation.RightTop: |
|
||||
new RotateProcessor<TPixel>() { Angle = (int)RotateType.Rotate90, Expand = false }.Apply(source, sourceRectangle); |
|
||||
break; |
|
||||
|
|
||||
case Orientation.RightBottom: |
|
||||
new FlipProcessor<TPixel>(FlipType.Vertical).Apply(source, sourceRectangle); |
|
||||
new RotateProcessor<TPixel>() { Angle = (int)RotateType.Rotate270, Expand = false }.Apply(source, sourceRectangle); |
|
||||
break; |
|
||||
|
|
||||
case Orientation.LeftBottom: |
|
||||
new RotateProcessor<TPixel>() { Angle = (int)RotateType.Rotate270, Expand = false }.Apply(source, sourceRectangle); |
|
||||
break; |
|
||||
|
|
||||
case Orientation.Unknown: |
|
||||
case Orientation.TopLeft: |
|
||||
default: |
|
||||
break; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Returns the current EXIF orientation
|
|
||||
/// </summary>
|
|
||||
/// <param name="source">The image to auto rotate.</param>
|
|
||||
/// <returns>The <see cref="Orientation"/></returns>
|
|
||||
private static Orientation GetExifOrientation(Image<TPixel> 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; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
Loading…
Reference in new issue