Browse Source

Merge branch 'master' into dp/jpeg-grayscale-fix

pull/1979/head
James Jackson-South 4 years ago
committed by GitHub
parent
commit
4fd6a29bb2
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 19
      .github/workflows/build-and-test.yml
  2. 7
      src/ImageSharp/ImageSharp.csproj
  3. 24
      src/ImageSharp/Metadata/Profiles/Exif/Values/ExifOrientationMode.cs
  4. 36
      src/ImageSharp/Processing/Processors/Transforms/Linear/AutoOrientProcessor{TPixel}.cs
  5. 71
      tests/ImageSharp.Tests/Processing/Processors/Transforms/AutoOrientTests.cs

19
.github/workflows/build-and-test.yml

@ -98,15 +98,6 @@ jobs:
- name: Git Pull LFS
run: git lfs pull
- name: Setup .NET SDKs
uses: actions/setup-dotnet@v1
with:
dotnet-version: |
6.0.x
5.0.x
3.1.x
2.1.x
- name: NuGet Install
uses: NuGet/setup-nuget@v1
@ -118,12 +109,14 @@ jobs:
key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj', '**/*.props', '**/*.targets') }}
restore-keys: ${{ runner.os }}-nuget-
- name: DotNet Setup Preview
if: ${{ matrix.options.sdk-preview == true }}
- name: DotNet Setup
uses: actions/setup-dotnet@v1
with:
dotnet-version: ${{ matrix.options.sdk }}
include-prerelease: true
dotnet-version: |
6.0.x
5.0.x
3.1.x
2.1.x
- name: DotNet Build
if: ${{ matrix.options.sdk-preview != true }}

7
src/ImageSharp/ImageSharp.csproj

@ -58,13 +58,6 @@
<PackageReference Include="System.Memory" Version="4.5.4" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard1.3'">
<PackageReference Include="System.IO.Compression" Version="4.3.0" />
<PackageReference Include="System.IO.UnmanagedMemoryStream" Version="4.3.0" />
<PackageReference Include="System.Threading.Tasks.Parallel" Version="4.3.0" />
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
</ItemGroup>
<ItemGroup>
<Compile Update="Formats\Jpeg\Components\Block8x8F.Generated.cs">
<DesignTime>True</DesignTime>

24
src/ImageSharp/Processing/OrientationMode.cs → src/ImageSharp/Metadata/Profiles/Exif/Values/ExifOrientationMode.cs

@ -1,56 +1,56 @@
// Copyright (c) Six Labors.
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
namespace SixLabors.ImageSharp.Processing
namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
{
/// <summary>
/// Enumerates the available orientation values supplied by EXIF metadata.
/// </summary>
internal enum OrientationMode : ushort
public static class ExifOrientationMode
{
/// <summary>
/// Unknown rotation.
/// </summary>
Unknown = 0,
public const ushort Unknown = 0;
/// <summary>
/// The 0th row at the top, the 0th column on the left.
/// </summary>
TopLeft = 1,
public const ushort TopLeft = 1;
/// <summary>
/// The 0th row at the top, the 0th column on the right.
/// </summary>
TopRight = 2,
public const ushort TopRight = 2;
/// <summary>
/// The 0th row at the bottom, the 0th column on the right.
/// </summary>
BottomRight = 3,
public const ushort BottomRight = 3;
/// <summary>
/// The 0th row at the bottom, the 0th column on the left.
/// </summary>
BottomLeft = 4,
public const ushort BottomLeft = 4;
/// <summary>
/// The 0th row on the left, the 0th column at the top.
/// </summary>
LeftTop = 5,
public const ushort LeftTop = 5;
/// <summary>
/// The 0th row at the right, the 0th column at the top.
/// </summary>
RightTop = 6,
public const ushort RightTop = 6;
/// <summary>
/// The 0th row on the right, the 0th column at the bottom.
/// </summary>
RightBottom = 7,
public const ushort RightBottom = 7;
/// <summary>
/// The 0th row on the left, the 0th column at the bottom.
/// </summary>
LeftBottom = 8
public const ushort LeftBottom = 8;
}
}

36
src/ImageSharp/Processing/Processors/Transforms/Linear/AutoOrientProcessor{TPixel}.cs

@ -28,42 +28,42 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
/// <inheritdoc/>
protected override void BeforeImageApply()
{
OrientationMode orientation = GetExifOrientation(this.Source);
ushort orientation = GetExifOrientation(this.Source);
Size size = this.SourceRectangle.Size;
switch (orientation)
{
case OrientationMode.TopRight:
case ExifOrientationMode.TopRight:
new FlipProcessor(FlipMode.Horizontal).Execute(this.Configuration, this.Source, this.SourceRectangle);
break;
case OrientationMode.BottomRight:
case ExifOrientationMode.BottomRight:
new RotateProcessor((int)RotateMode.Rotate180, size).Execute(this.Configuration, this.Source, this.SourceRectangle);
break;
case OrientationMode.BottomLeft:
case ExifOrientationMode.BottomLeft:
new FlipProcessor(FlipMode.Vertical).Execute(this.Configuration, this.Source, this.SourceRectangle);
break;
case OrientationMode.LeftTop:
case ExifOrientationMode.LeftTop:
new RotateProcessor((int)RotateMode.Rotate90, size).Execute(this.Configuration, this.Source, this.SourceRectangle);
new FlipProcessor(FlipMode.Horizontal).Execute(this.Configuration, this.Source, this.SourceRectangle);
break;
case OrientationMode.RightTop:
case ExifOrientationMode.RightTop:
new RotateProcessor((int)RotateMode.Rotate90, size).Execute(this.Configuration, this.Source, this.SourceRectangle);
break;
case OrientationMode.RightBottom:
case ExifOrientationMode.RightBottom:
new FlipProcessor(FlipMode.Vertical).Execute(this.Configuration, this.Source, this.SourceRectangle);
new RotateProcessor((int)RotateMode.Rotate270, size).Execute(this.Configuration, this.Source, this.SourceRectangle);
break;
case OrientationMode.LeftBottom:
case ExifOrientationMode.LeftBottom:
new RotateProcessor((int)RotateMode.Rotate270, size).Execute(this.Configuration, this.Source, this.SourceRectangle);
break;
case OrientationMode.Unknown:
case OrientationMode.TopLeft:
case ExifOrientationMode.Unknown:
case ExifOrientationMode.TopLeft:
default:
break;
}
@ -81,32 +81,32 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
/// Returns the current EXIF orientation
/// </summary>
/// <param name="source">The image to auto rotate.</param>
/// <returns>The <see cref="OrientationMode"/></returns>
private static OrientationMode GetExifOrientation(Image<TPixel> source)
/// <returns>The <see cref="ushort"/></returns>
private static ushort GetExifOrientation(Image<TPixel> source)
{
if (source.Metadata.ExifProfile is null)
{
return OrientationMode.Unknown;
return ExifOrientationMode.Unknown;
}
IExifValue<ushort> value = source.Metadata.ExifProfile.GetValue(ExifTag.Orientation);
if (value is null)
{
return OrientationMode.Unknown;
return ExifOrientationMode.Unknown;
}
OrientationMode orientation;
ushort orientation;
if (value.DataType == ExifDataType.Short)
{
orientation = (OrientationMode)value.Value;
orientation = value.Value;
}
else
{
orientation = (OrientationMode)Convert.ToUInt16(value.Value);
orientation = Convert.ToUInt16(value.Value);
source.Metadata.ExifProfile.RemoveValue(ExifTag.Orientation);
}
source.Metadata.ExifProfile.SetValue(ExifTag.Orientation, (ushort)OrientationMode.TopLeft);
source.Metadata.ExifProfile.SetValue(ExifTag.Orientation, ExifOrientationMode.TopLeft);
return orientation;
}

71
tests/ImageSharp.Tests/Processing/Processors/Transforms/AutoOrientTests.cs

@ -18,42 +18,41 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms
public const string FlipTestFile = TestImages.Bmp.F;
public static readonly TheoryData<ExifDataType, byte[]> InvalidOrientationValues
= new TheoryData<ExifDataType, byte[]>
{
{ ExifDataType.Byte, new byte[] { 1 } },
{ ExifDataType.SignedByte, new byte[] { 2 } },
{ ExifDataType.SignedShort, BitConverter.GetBytes((short)3) },
{ ExifDataType.Long, BitConverter.GetBytes(4U) },
{ ExifDataType.SignedLong, BitConverter.GetBytes(5) }
};
= new()
{
{ ExifDataType.Byte, new byte[] { 1 } },
{ ExifDataType.SignedByte, new byte[] { 2 } },
{ ExifDataType.SignedShort, BitConverter.GetBytes((short)3) },
{ ExifDataType.Long, BitConverter.GetBytes(4U) },
{ ExifDataType.SignedLong, BitConverter.GetBytes(5) }
};
public static readonly TheoryData<ushort> ExifOrientationValues = new TheoryData<ushort>
{
0,
1,
2,
3,
4,
5,
6,
7,
8
};
public static readonly TheoryData<ushort> ExifOrientationValues
= new()
{
ExifOrientationMode.Unknown,
ExifOrientationMode.TopLeft,
ExifOrientationMode.TopRight,
ExifOrientationMode.BottomRight,
ExifOrientationMode.BottomLeft,
ExifOrientationMode.LeftTop,
ExifOrientationMode.RightTop,
ExifOrientationMode.RightBottom,
ExifOrientationMode.LeftBottom
};
[Theory]
[WithFile(FlipTestFile, nameof(ExifOrientationValues), PixelTypes.Rgba32)]
public void AutoOrient_WorksForAllExifOrientations<TPixel>(TestImageProvider<TPixel> provider, ushort orientation)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage())
{
image.Metadata.ExifProfile = new ExifProfile();
image.Metadata.ExifProfile.SetValue(ExifTag.Orientation, orientation);
using Image<TPixel> image = provider.GetImage();
image.Metadata.ExifProfile = new ExifProfile();
image.Metadata.ExifProfile.SetValue(ExifTag.Orientation, orientation);
image.Mutate(x => x.AutoOrient());
image.DebugSave(provider, orientation, appendPixelTypeToFileName: false);
image.CompareToReferenceOutput(provider, orientation, appendPixelTypeToFileName: false);
}
image.Mutate(x => x.AutoOrient());
image.DebugSave(provider, orientation, appendPixelTypeToFileName: false);
image.CompareToReferenceOutput(provider, orientation, appendPixelTypeToFileName: false);
}
[Theory]
@ -76,19 +75,17 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms
// Change the number of components
bytes[20] = 1;
var orientationCodeData = new byte[8];
byte[] orientationCodeData = new byte[8];
Array.Copy(orientation, orientationCodeData, orientation.Length);
ulong orientationCode = BitConverter.ToUInt64(orientationCodeData, 0);
using (Image<TPixel> image = provider.GetImage())
using (Image<TPixel> reference = image.Clone())
{
image.Metadata.ExifProfile = new ExifProfile(bytes);
image.Mutate(x => x.AutoOrient());
image.DebugSave(provider, $"{dataType}-{orientationCode}", appendPixelTypeToFileName: false);
ImageComparer.Exact.VerifySimilarity(image, reference);
}
using Image<TPixel> image = provider.GetImage();
using Image<TPixel> reference = image.Clone();
image.Metadata.ExifProfile = new ExifProfile(bytes);
image.Mutate(x => x.AutoOrient());
image.DebugSave(provider, $"{dataType}-{orientationCode}", appendPixelTypeToFileName: false);
ImageComparer.Exact.VerifySimilarity(image, reference);
}
}
}

Loading…
Cancel
Save