Browse Source

Merge branch 'tocsoft/mutate-api' of https://github.com/JimBobSquarePants/ImageSharp into tocsoft/mutate-api

# Conflicts:
#	src/ImageSharp/ApplyProcessors.cs
af/merge-core
Scott Williams 9 years ago
parent
commit
e7f40d0bed
  1. 19
      src/ImageSharp/ApplyProcessors.cs
  2. 7
      src/ImageSharp/Configuration.cs
  3. 38
      src/ImageSharp/IImageOperationsProvider.cs
  4. 2
      src/ImageSharp/IImageOperations{TPixel}.cs
  5. 5
      src/ImageSharp/Processing/Processors/DelegateProcessor.cs
  6. 11
      src/ImageSharp/Processing/Processors/Transforms/AutoRotateProcessor.cs
  7. 1
      src/ImageSharp/Processing/Transforms/AutoOrient.cs
  8. 4
      src/Shared/AssemblyInfo.Common.cs
  9. 2
      tests/ImageSharp.Sandbox46/ImageSharp.Sandbox46.csproj
  10. 25
      tests/ImageSharp.Tests/BaseImageOperationsExtensionTest.cs
  11. 17
      tests/ImageSharp.Tests/Colorspaces/ColorSpaceEqualityTests.cs
  12. 77
      tests/ImageSharp.Tests/FakeImageOperationsProvider.cs
  13. 16
      tests/ImageSharp.Tests/Image/PixelAccessorTests.cs
  14. 120
      tests/ImageSharp.Tests/ImageOperationTests.cs
  15. 4
      tests/ImageSharp.Tests/ImageSharp.Tests.csproj
  16. 13
      tests/ImageSharp.Tests/PixelFormats/ColorDefinitionTests.cs
  17. 35
      tests/ImageSharp.Tests/Processing/Transforms/AutoOrientTests.cs

19
src/ImageSharp/ApplyProcessors.cs

@ -28,7 +28,7 @@ namespace ImageSharp
Guard.NotNull(operations, nameof(operations));
// TODO: add parameter to Configuration to configure how this is created, create an IImageOperationsFactory that cna be used to switch this out with a fake for testing
var operationsRunner = new ImageOperations<TPixel>(source);
IImageOperations<TPixel> operationsRunner = source.Configuration.ImageOperationsProvider.CreateMutator(source);
operations(operationsRunner);
}
@ -44,7 +44,7 @@ namespace ImageSharp
Guard.NotNull(operations, nameof(operations));
// TODO: add parameter to Configuration to configure how this is created, create an IImageOperationsFactory that cna be used to switch this out with a fake for testing
var operationsRunner = new ImageOperations<TPixel>(source);
IImageOperations<TPixel> operationsRunner = source.Configuration.ImageOperationsProvider.CreateMutator(source);
operationsRunner.ApplyProcessors(operations);
}
@ -62,7 +62,7 @@ namespace ImageSharp
var generated = new Image<TPixel>(source);
// TODO: add parameter to Configuration to configure how this is created, create an IImageOperationsFactory that cna be used to switch this out with a fake for testing
var operationsRunner = new ImageOperations<TPixel>(generated);
IImageOperations<TPixel> operationsRunner = source.Configuration.ImageOperationsProvider.CreateMutator(generated);
operations(operationsRunner);
return generated;
}
@ -81,9 +81,20 @@ namespace ImageSharp
var generated = new Image<TPixel>(source);
// TODO: add parameter to Configuration to configure how this is created, create an IImageOperationsFactory that cna be used to switch this out with a fake for testing
var operationsRunner = new ImageOperations<TPixel>(generated);
IImageOperations<TPixel> operationsRunner = source.Configuration.ImageOperationsProvider.CreateMutator(generated);
operationsRunner.ApplyProcessors(operations);
return generated;
}
/// <summary>
/// Queues up a simple operation that provides access to the mutatable image.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="source">The image to rotate, flip, or both.</param>
/// <param name="operation">The operations to perform on the source.</param>
/// <returns>returns the current optinoatins class to allow chaining of oprations.</returns>
public static IImageOperations<TPixel> Run<TPixel>(this IImageOperations<TPixel> source, Action<Image<TPixel>> operation)
where TPixel : struct, IPixel<TPixel>
=> source.ApplyProcessor(new DelegateImageProcessor<TPixel>(operation));
}
}

7
src/ImageSharp/Configuration.cs

@ -103,11 +103,16 @@ namespace ImageSharp
#if !NETSTANDARD1_1
/// <summary>
/// Gets or sets the fielsystem helper for accessing the local file system.
/// Gets or sets the filesystem helper for accessing the local file system.
/// </summary>
internal IFileSystem FileSystem { get; set; } = new LocalFileSystem();
#endif
/// <summary>
/// Gets or sets the image operations providers.
/// </summary>
internal IImageOperationsProvider ImageOperationsProvider { get; set; } = new DefaultImageOperationsProvider();
/// <summary>
/// Registers a new format provider.
/// </summary>

38
src/ImageSharp/IImageOperationsProvider.cs

@ -0,0 +1,38 @@
// <copyright file="IImageOperationsProvider.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp
{
using System;
using ImageSharp.PixelFormats;
/// <summary>
/// Represents an interface that will create IImageOperations
/// </summary>
internal interface IImageOperationsProvider
{
/// <summary>
/// Called during Mutate operations to generate the imageoperations provider.
/// </summary>
/// <typeparam name="TPixel">The pixel format</typeparam>
/// <param name="source">The source image.</param>
/// <returns>A new IImageOPeration</returns>
IImageOperations<TPixel> CreateMutator<TPixel>(Image<TPixel> source)
where TPixel : struct, IPixel<TPixel>;
}
/// <summary>
/// The default implmentation of IImageOperationsProvider
/// </summary>
internal class DefaultImageOperationsProvider : IImageOperationsProvider
{
/// <inheritdoc/>
public IImageOperations<TPixel> CreateMutator<TPixel>(Image<TPixel> source)
where TPixel : struct, IPixel<TPixel>
{
return new ImageOperations<TPixel>(source);
}
}
}

2
src/ImageSharp/IImageOperations{TPixel}.cs

@ -12,7 +12,7 @@ namespace ImageSharp
using SixLabors.Primitives;
/// <summary>
/// The static collection of all the default image formats
/// An interface to queue up image operations.
/// </summary>
/// <typeparam name="TPixel">The pixel format</typeparam>
public interface IImageOperations<TPixel>

5
src/ImageSharp/Processing/Processors/DelegateProcessor.cs

@ -29,6 +29,11 @@ namespace ImageSharp.Processing
this.action = action;
}
/// <summary>
/// Gets the action that will be applied to the image.
/// </summary>
internal Action<Image<TPixel>> Action => this.action;
/// <inheritdoc/>
protected override void BeforeImageApply(Image<TPixel> source, Rectangle sourceRectangle)
{

11
src/ImageSharp/Processing/Processors/Transforms/AutoRotateProcessor.cs

@ -93,7 +93,16 @@ namespace ImageSharp.Processing.Processors
return Orientation.Unknown;
}
var orientation = (Orientation)value.Value;
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);

1
src/ImageSharp/Processing/Transforms/AutoOrient.cs

@ -5,6 +5,7 @@
namespace ImageSharp
{
using System;
using ImageSharp.PixelFormats;
using ImageSharp.Processing;

4
src/Shared/AssemblyInfo.Common.cs

@ -37,4 +37,6 @@ using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("ImageSharp.Drawing")]
[assembly: InternalsVisibleTo("ImageSharp.Benchmarks")]
[assembly: InternalsVisibleTo("ImageSharp.Tests")]
[assembly: InternalsVisibleTo("ImageSharp.Sandbox46")]
[assembly: InternalsVisibleTo("ImageSharp.Sandbox46")]
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")]

2
tests/ImageSharp.Sandbox46/ImageSharp.Sandbox46.csproj

@ -18,7 +18,7 @@
<ItemGroup>
<!--<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0" />-->
<PackageReference Include="Moq" Version="4.7.1" />
<PackageReference Include="xunit" Version="2.3.0-beta2-build3683" />
<PackageReference Include="xunit" Version="2.3.0-beta3-build3705" />
<!--<PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />-->
</ItemGroup>
<ItemGroup>

25
tests/ImageSharp.Tests/BaseImageOperationsExtensionTest.cs

@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Text;
using ImageSharp.Processing;
using Xunit;
namespace ImageSharp.Tests
{
public abstract class BaseImageOperationsExtensionTest
{
protected readonly FakeImageOperationsProvider.FakeImageOperations<Rgba32> operations;
public BaseImageOperationsExtensionTest()
{
this.operations = new FakeImageOperationsProvider.FakeImageOperations<Rgba32>(null);
}
public T Verify<T>(int index = 0)
{
var operation = this.operations.applied[index];
return Assert.IsType<T>(operation.Processor);
}
}
}

17
tests/ImageSharp.Tests/Colorspaces/ColorSpaceEqualityTests.cs

@ -3,6 +3,7 @@
// Licensed under the Apache License, Version 2.0.
// </copyright>
// ReSharper disable InconsistentNaming
namespace ImageSharp.Tests.Colorspaces
{
using System;
@ -141,7 +142,7 @@ namespace ImageSharp.Tests.Colorspaces
[Theory]
[MemberData(nameof(EmptyData))]
public void Equality(IColorVector color)
public void Vector_Equals_WhenTrue(IColorVector color)
{
// Act
bool equal = color.Vector.Equals(Vector3.Zero);
@ -152,7 +153,7 @@ namespace ImageSharp.Tests.Colorspaces
[Theory]
[MemberData(nameof(EqualityData))]
public void Equality(object first, object second, Type type)
public void Equals_WhenTrue(object first, object second, Type type)
{
// Act
bool equal = first.Equals(second);
@ -165,7 +166,7 @@ namespace ImageSharp.Tests.Colorspaces
[MemberData(nameof(NotEqualityDataNulls))]
[MemberData(nameof(NotEqualityDataDifferentObjects))]
[MemberData(nameof(NotEqualityData))]
public void NotEquality(object first, object second, Type type)
public void Equals_WhenFalse(object first, object second, Type type)
{
// Act
bool equal = first.Equals(second);
@ -176,7 +177,7 @@ namespace ImageSharp.Tests.Colorspaces
[Theory]
[MemberData(nameof(EqualityData))]
public void HashCodeEqual(object first, object second, Type type)
public void GetHashCode_WhenEqual(object first, object second, Type type)
{
// Act
bool equal = first.GetHashCode() == second.GetHashCode();
@ -187,7 +188,7 @@ namespace ImageSharp.Tests.Colorspaces
[Theory]
[MemberData(nameof(NotEqualityDataDifferentObjects))]
public void HashCodeNotEqual(object first, object second, Type type)
public void GetHashCode_WhenNotEqual(object first, object second, Type type)
{
// Act
bool equal = first.GetHashCode() == second.GetHashCode();
@ -198,7 +199,7 @@ namespace ImageSharp.Tests.Colorspaces
[Theory]
[MemberData(nameof(EqualityData))]
public void EqualityObject(object first, object second, Type type)
public void GenericEquals_WhenTrue(object first, object second, Type type)
{
// Arrange
// Cast to the known object types, this is so that we can hit the
@ -216,7 +217,7 @@ namespace ImageSharp.Tests.Colorspaces
[Theory]
[MemberData(nameof(NotEqualityData))]
public void NotEqualityObject(object first, object second, Type type)
public void GenericEquals_WhenFalse(object first, object second, Type type)
{
// Arrange
// Cast to the known object types, this is so that we can hit the
@ -253,7 +254,7 @@ namespace ImageSharp.Tests.Colorspaces
[Theory]
[MemberData(nameof(NotEqualityData))]
public void NotEqualityOperator(object first, object second, Type type)
public void Operator_WhenTrue(object first, object second, Type type)
{
// Arrange
// Cast to the known object types, this is so that we can hit the

77
tests/ImageSharp.Tests/FakeImageOperationsProvider.cs

@ -0,0 +1,77 @@
namespace ImageSharp.Tests
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ImageSharp.PixelFormats;
using ImageSharp.Processing;
using SixLabors.Primitives;
public class FakeImageOperationsProvider : IImageOperationsProvider
{
private List<object> ImageOperators = new List<object>();
public bool HasCreated<TPixel>(Image<TPixel> source)
where TPixel : struct, IPixel<TPixel>
{
return Created(source).Any();
}
public IEnumerable<FakeImageOperations<TPixel>> Created<TPixel>(Image<TPixel> source) where TPixel : struct, IPixel<TPixel>
{
return this.ImageOperators.OfType<FakeImageOperations<TPixel>>()
.Where(x => x.source == source);
}
public IEnumerable<FakeImageOperations<TPixel>.AppliedOpperation> AppliedOperations<TPixel>(Image<TPixel> source) where TPixel : struct, IPixel<TPixel>
{
return Created(source)
.SelectMany(x => x.applied);
}
public IImageOperations<TPixel> CreateMutator<TPixel>(Image<TPixel> source) where TPixel : struct, IPixel<TPixel>
{
var op = new FakeImageOperations<TPixel>(source);
this.ImageOperators.Add(op);
return op;
}
public class FakeImageOperations<TPixel> : IImageOperations<TPixel>
where TPixel : struct, IPixel<TPixel>
{
public Image<TPixel> source;
public List<AppliedOpperation> applied = new List<AppliedOpperation>();
public FakeImageOperations(Image<TPixel> source)
{
this.source = source;
}
public IImageOperations<TPixel> ApplyProcessor(IImageProcessor<TPixel> processor, Rectangle rectangle)
{
applied.Add(new AppliedOpperation
{
Processor = processor,
Rectangle = rectangle
});
return this;
}
public IImageOperations<TPixel> ApplyProcessor(IImageProcessor<TPixel> processor)
{
applied.Add(new AppliedOpperation
{
Processor = processor
});
return this;
}
public struct AppliedOpperation
{
public Rectangle? Rectangle { get; set; }
public IImageProcessor<TPixel> Processor { get; set; }
}
}
}
}

16
tests/ImageSharp.Tests/Image/PixelAccessorTests.cs

@ -114,7 +114,7 @@ namespace ImageSharp.Tests
{
using (Image<Rgba32> image = new Image<Rgba32>(1, 1))
{
CopyFromZYX(image);
CopyFromZYXImpl(image);
}
}
@ -123,7 +123,7 @@ namespace ImageSharp.Tests
{
using (Image<Rgba32> image = new Image<Rgba32>(1, 1))
{
CopyFromZYXW(image);
CopyFromZYXWImpl(image);
}
}
@ -132,7 +132,7 @@ namespace ImageSharp.Tests
{
using (Image<Rgba32> image = new Image<Rgba32>(1, 1))
{
CopyToZYX(image);
CopyToZYXImpl(image);
}
}
@ -141,11 +141,11 @@ namespace ImageSharp.Tests
{
using (Image<Rgba32> image = new Image<Rgba32>(1, 1))
{
CopyToZYXW(image);
CopyToZYXWImpl(image);
}
}
private static void CopyFromZYX<TPixel>(Image<TPixel> image)
private static void CopyFromZYXImpl<TPixel>(Image<TPixel> image)
where TPixel : struct, IPixel<TPixel>
{
using (PixelAccessor<TPixel> pixels = image.Lock())
@ -172,7 +172,7 @@ namespace ImageSharp.Tests
}
}
private static void CopyFromZYXW<TPixel>(Image<TPixel> image)
private static void CopyFromZYXWImpl<TPixel>(Image<TPixel> image)
where TPixel : struct, IPixel<TPixel>
{
using (PixelAccessor<TPixel> pixels = image.Lock())
@ -200,7 +200,7 @@ namespace ImageSharp.Tests
}
}
private static void CopyToZYX<TPixel>(Image<TPixel> image)
private static void CopyToZYXImpl<TPixel>(Image<TPixel> image)
where TPixel : struct, IPixel<TPixel>
{
using (PixelAccessor<TPixel> pixels = image.Lock())
@ -222,7 +222,7 @@ namespace ImageSharp.Tests
}
}
private static void CopyToZYXW<TPixel>(Image<TPixel> image)
private static void CopyToZYXWImpl<TPixel>(Image<TPixel> image)
where TPixel : struct, IPixel<TPixel>
{
using (PixelAccessor<TPixel> pixels = image.Lock())

120
tests/ImageSharp.Tests/ImageOperationTests.cs

@ -0,0 +1,120 @@
// <copyright file="ConfigurationTests.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Tests
{
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using ImageSharp.Formats;
using ImageSharp.IO;
using ImageSharp.PixelFormats;
using ImageSharp.Processing;
using Moq;
using SixLabors.Primitives;
using Xunit;
/// <summary>
/// Tests the configuration class.
/// </summary>
public class ImageOperationTests : IDisposable
{
private readonly Image<Rgba32> image;
private readonly FakeImageOperationsProvider provider;
private readonly IImageProcessor<Rgba32> processor;
public Configuration Configuration { get; private set; }
public ImageOperationTests()
{
this.provider = new FakeImageOperationsProvider();
this.processor = new Mock<IImageProcessor<Rgba32>>().Object;
this.image = new Image<Rgba32>(new Configuration()
{
ImageOperationsProvider = this.provider
}, 1, 1);
}
[Fact]
public void MutateCallsImageOperationsProvider_Func_OriginalImage()
{
this.image.Mutate(x => x.ApplyProcessor(this.processor));
Assert.True(this.provider.HasCreated(this.image));
Assert.Contains(this.processor, this.provider.AppliedOperations(this.image).Select(x=>x.Processor));
}
[Fact]
public void MutateCallsImageOperationsProvider_ListOfProcessors_OriginalImage()
{
this.image.Mutate(this.processor);
Assert.True(this.provider.HasCreated(this.image));
Assert.Contains(this.processor, this.provider.AppliedOperations(this.image).Select(x => x.Processor));
}
[Fact]
public void CloneCallsImageOperationsProvider_Func_WithDuplicateImage()
{
var returned = this.image.Clone(x => x.ApplyProcessor(this.processor));
Assert.True(this.provider.HasCreated(returned));
Assert.Contains(this.processor, this.provider.AppliedOperations(returned).Select(x => x.Processor));
}
[Fact]
public void CloneCallsImageOperationsProvider_ListOfProcessors_WithDuplicateImage()
{
var returned = this.image.Clone(this.processor);
Assert.True(this.provider.HasCreated(returned));
Assert.Contains(this.processor, this.provider.AppliedOperations(returned).Select(x => x.Processor));
}
[Fact]
public void CloneCallsImageOperationsProvider_Func_NotOnOrigional()
{
var returned = this.image.Clone(x => x.ApplyProcessor(this.processor));
Assert.False(this.provider.HasCreated(this.image));
Assert.DoesNotContain(this.processor, this.provider.AppliedOperations(this.image).Select(x => x.Processor));
}
[Fact]
public void CloneCallsImageOperationsProvider_ListOfProcessors_NotOnOrigional()
{
var returned = this.image.Clone(this.processor);
Assert.False(this.provider.HasCreated(this.image));
Assert.DoesNotContain(this.processor, this.provider.AppliedOperations(this.image).Select(x => x.Processor));
}
[Fact]
public void ApplyProcessors_ListOfProcessors_AppliesALlProcessorsToOperation()
{
var operations = new FakeImageOperationsProvider.FakeImageOperations<Rgba32>(null);
operations.ApplyProcessors(this.processor);
Assert.Contains(this.processor, operations.applied.Select(x => x.Processor));
}
public void Dispose()
{
this.image.Dispose();
}
}
public class RunImageOperation : BaseImageOperationsExtensionTest
{
[Fact]
public void Run_CreatedDelegateProcessor()
{
Action<Image<Rgba32>> action = (i) => { };
this.operations.Run(action);
DelegateImageProcessor<Rgba32> processor = this.Verify<DelegateImageProcessor<Rgba32>>();
Assert.Equal(action, processor.Action);
}
}
}

4
tests/ImageSharp.Tests/ImageSharp.Tests.csproj

@ -12,8 +12,8 @@
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0" />
<PackageReference Include="Moq" Version="4.7.1" />
<PackageReference Include="xunit" Version="2.3.0-beta2-build3683" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.0-beta2-build1317" />
<PackageReference Include="xunit" Version="2.3.0-beta3-build3705" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.0-beta3-build3705" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\ImageSharp.Drawing\ImageSharp.Drawing.csproj" />

13
tests/ImageSharp.Tests/PixelFormats/ColorDefinitionTests.cs

@ -15,7 +15,18 @@ namespace ImageSharp.Tests
public class ColorDefinitionTests
{
public static IEnumerable<string[]> ColorNames => typeof(NamedColors<Rgba32>).GetTypeInfo().GetFields().Select(x => new[] { x.Name });
public static TheoryData<string> ColorNames
{
get
{
var result = new TheoryData<string>();
foreach (string name in typeof(NamedColors<Rgba32>).GetTypeInfo().GetFields().Select(x => x.Name ))
{
result.Add(name);
}
return result;
}
}
[Theory]
[MemberData(nameof(ColorNames))]

35
tests/ImageSharp.Tests/Processing/Transforms/AutoOrientTests.cs

@ -5,6 +5,7 @@
namespace ImageSharp.Tests.Processing.Transforms
{
using System;
using ImageSharp.PixelFormats;
using ImageSharp.Processing;
@ -28,6 +29,16 @@ namespace ImageSharp.Tests.Processing.Transforms
{ RotateType.Rotate90, FlipType.None, 8 },
};
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((uint) 4) },
{ ExifDataType.SignedLong, BitConverter.GetBytes((int) 5) }
};
[Theory]
[WithFileCollection(nameof(FlipFiles), nameof(OrientationValues), DefaultPixelType)]
public void ImageShouldAutoRotate<TPixel>(TestImageProvider<TPixel> provider, RotateType rotateType, FlipType flipType, ushort orientation)
@ -45,5 +56,29 @@ namespace ImageSharp.Tests.Processing.Transforms
image.DebugSave(provider, string.Join("_", rotateType, flipType, orientation, "2_after"), Extensions.Bmp);
}
}
[Theory]
[WithFileCollection(nameof(FlipFiles), nameof(InvalidOrientationValues), DefaultPixelType)]
public void ImageShouldAutoRotateInvalidValues<TPixel>(TestImageProvider<TPixel> provider, ExifDataType dataType, byte[] orientation)
where TPixel : struct, IPixel<TPixel>
{
var profile = new ExifProfile();
profile.SetValue(ExifTag.JPEGTables, orientation);
byte[] bytes = profile.ToByteArray();
// Change the tag into ExifTag.Orientation
bytes[16] = 18;
bytes[17] = 1;
// Change the data type
bytes[18] = (byte)dataType;
// Change the number of components
bytes[20] = 1;
using (Image<TPixel> image = provider.GetImage())
{
image.MetaData.ExifProfile = new ExifProfile(bytes);
image.Mutate(x=>x.AutoOrient());
}
}
}
}
Loading…
Cancel
Save