|
|
|
@ -154,83 +154,90 @@ namespace SixLabors.ImageSharp.Tests |
|
|
|
Assert.Equal(new Rational(double.PositiveInfinity), value2.Value); |
|
|
|
} |
|
|
|
|
|
|
|
//[Theory]
|
|
|
|
//[InlineData(TestImageWriteFormat.Jpeg)]
|
|
|
|
//[InlineData(TestImageWriteFormat.Png)]
|
|
|
|
//public void SetValue(TestImageWriteFormat imageFormat)
|
|
|
|
//{
|
|
|
|
// var latitude = new Rational[] { new Rational(12.3), new Rational(4.56), new Rational(789.0) };
|
|
|
|
|
|
|
|
// Image<Rgba32> image = TestFile.Create(TestImages.Jpeg.Baseline.Floorplan).CreateRgba32Image();
|
|
|
|
// image.Metadata.ExifProfile.SetValue(ExifTag.Software, "ImageSharp");
|
|
|
|
[Theory] |
|
|
|
[InlineData(TestImageWriteFormat.Jpeg)] |
|
|
|
[InlineData(TestImageWriteFormat.Png)] |
|
|
|
public void SetValue(TestImageWriteFormat imageFormat) |
|
|
|
{ |
|
|
|
Image<Rgba32> image = TestFile.Create(TestImages.Jpeg.Baseline.Floorplan).CreateRgba32Image(); |
|
|
|
image.Metadata.ExifProfile.SetValue(ExifTag.Software, "ImageSharp"); |
|
|
|
|
|
|
|
// IExifValue value = image.Metadata.ExifProfile.GetValue(ExifTag.Software);
|
|
|
|
// TestValue(value, "ImageSharp");
|
|
|
|
IExifValue<string> software = image.Metadata.ExifProfile.GetValue(ExifTag.Software); |
|
|
|
Assert.Equal("ImageSharp", software.Value); |
|
|
|
|
|
|
|
// Assert.Throws<ArgumentException>(() => { value.SetValue(15); });
|
|
|
|
// ExifString can set integer values.
|
|
|
|
Assert.True(software.TrySetValue(15)); |
|
|
|
Assert.False(software.TrySetValue(15F)); |
|
|
|
|
|
|
|
// image.Metadata.ExifProfile.SetValue(ExifTag.ShutterSpeedValue, new SignedRational(75.55));
|
|
|
|
image.Metadata.ExifProfile.SetValue(ExifTag.ShutterSpeedValue, new SignedRational(75.55)); |
|
|
|
|
|
|
|
// value = image.Metadata.ExifProfile.GetValue(ExifTag.ShutterSpeedValue);
|
|
|
|
IExifValue<SignedRational> shutterSpeed = image.Metadata.ExifProfile.GetValue(ExifTag.ShutterSpeedValue); |
|
|
|
|
|
|
|
// TestValue(value, new SignedRational(7555, 100));
|
|
|
|
Assert.Equal(new SignedRational(7555, 100), shutterSpeed.Value); |
|
|
|
Assert.False(shutterSpeed.TrySetValue(75)); |
|
|
|
|
|
|
|
// Assert.Throws<ArgumentException>(() => { value.WithValue(75); });
|
|
|
|
image.Metadata.ExifProfile.SetValue(ExifTag.XResolution, new Rational(150.0)); |
|
|
|
|
|
|
|
// image.Metadata.ExifProfile.SetValue(ExifTag.XResolution, new Rational(150.0));
|
|
|
|
// We also need to change this value because this overrides XResolution when the image is written.
|
|
|
|
image.Metadata.HorizontalResolution = 150.0; |
|
|
|
|
|
|
|
// // We also need to change this value because this overrides XResolution when the image is written.
|
|
|
|
// image.Metadata.HorizontalResolution = 150.0;
|
|
|
|
IExifValue<Rational> xResolution = image.Metadata.ExifProfile.GetValue(ExifTag.XResolution); |
|
|
|
Assert.Equal(new Rational(150, 1), xResolution.Value); |
|
|
|
|
|
|
|
// value = image.Metadata.ExifProfile.GetValue(ExifTag.XResolution);
|
|
|
|
// TestValue(value, new Rational(150, 1));
|
|
|
|
Assert.False(xResolution.TrySetValue("ImageSharp")); |
|
|
|
|
|
|
|
// Assert.Throws<ArgumentException>(() => { value.WithValue("ImageSharp"); });
|
|
|
|
image.Metadata.ExifProfile.SetValue(ExifTag.ReferenceBlackWhite, null); |
|
|
|
|
|
|
|
// image.Metadata.ExifProfile.SetValue(ExifTag.ReferenceBlackWhite, null);
|
|
|
|
IExifValue<Rational[]> referenceBlackWhite = image.Metadata.ExifProfile.GetValue(ExifTag.ReferenceBlackWhite); |
|
|
|
Assert.Null(referenceBlackWhite.Value); |
|
|
|
|
|
|
|
// value = image.Metadata.ExifProfile.GetValue(ExifTag.ReferenceBlackWhite);
|
|
|
|
// TestValue(value, (string)null);
|
|
|
|
var expectedLatitude = new Rational[] { new Rational(12.3), new Rational(4.56), new Rational(789.0) }; |
|
|
|
image.Metadata.ExifProfile.SetValue(ExifTag.GPSLatitude, expectedLatitude); |
|
|
|
|
|
|
|
// image.Metadata.ExifProfile.SetValue(ExifTag.GPSLatitude, latitude);
|
|
|
|
IExifValue<Rational[]> latitude = image.Metadata.ExifProfile.GetValue(ExifTag.GPSLatitude); |
|
|
|
Assert.Equal(expectedLatitude, latitude.Value); |
|
|
|
|
|
|
|
// value = image.Metadata.ExifProfile.GetValue(ExifTag.GPSLatitude);
|
|
|
|
// TestValue(value, latitude);
|
|
|
|
int profileCount = image.Metadata.ExifProfile.Values.Count; |
|
|
|
image = WriteAndRead(image, imageFormat); |
|
|
|
|
|
|
|
// image = WriteAndRead(image, imageFormat);
|
|
|
|
Assert.NotNull(image.Metadata.ExifProfile); |
|
|
|
|
|
|
|
// Assert.NotNull(image.Metadata.ExifProfile);
|
|
|
|
// Assert.Equal(17, image.Metadata.ExifProfile.Values.Count());
|
|
|
|
// Should be 3 less.
|
|
|
|
// 1 x due to setting of null "ReferenceBlackWhite" value.
|
|
|
|
// 2 x due to use of non-standard padding tag 0xEA1C listed in EXIF Tool. We can read those values but adhere
|
|
|
|
// strictly to the 2.3.1 specification when writing. (TODO: Support 2.3.2)
|
|
|
|
// https://exiftool.org/TagNames/EXIF.html
|
|
|
|
Assert.Equal(profileCount - 3, image.Metadata.ExifProfile.Values.Count); |
|
|
|
|
|
|
|
// value = image.Metadata.ExifProfile.GetValue(ExifTag.Software);
|
|
|
|
// TestValue(value, "ImageSharp");
|
|
|
|
software = image.Metadata.ExifProfile.GetValue(ExifTag.Software); |
|
|
|
Assert.Equal("15", software.Value); |
|
|
|
|
|
|
|
// value = image.Metadata.ExifProfile.GetValue(ExifTag.ShutterSpeedValue);
|
|
|
|
// TestValue(value, new SignedRational(75.55));
|
|
|
|
shutterSpeed = image.Metadata.ExifProfile.GetValue(ExifTag.ShutterSpeedValue); |
|
|
|
Assert.Equal(new SignedRational(75.55), shutterSpeed.Value); |
|
|
|
|
|
|
|
// value = image.Metadata.ExifProfile.GetValue(ExifTag.XResolution);
|
|
|
|
// TestValue(value, new Rational(150.0));
|
|
|
|
xResolution = image.Metadata.ExifProfile.GetValue(ExifTag.XResolution); |
|
|
|
Assert.Equal(new Rational(150.0), xResolution.Value); |
|
|
|
|
|
|
|
// value = image.Metadata.ExifProfile.GetValue(ExifTag.ReferenceBlackWhite);
|
|
|
|
// Assert.Null(value);
|
|
|
|
referenceBlackWhite = image.Metadata.ExifProfile.GetValue(ExifTag.ReferenceBlackWhite); |
|
|
|
Assert.Null(referenceBlackWhite); |
|
|
|
|
|
|
|
// value = image.Metadata.ExifProfile.GetValue(ExifTag.GPSLatitude);
|
|
|
|
// TestValue(value, latitude);
|
|
|
|
latitude = image.Metadata.ExifProfile.GetValue(ExifTag.GPSLatitude); |
|
|
|
Assert.Equal(expectedLatitude, latitude.Value); |
|
|
|
|
|
|
|
// image.Metadata.ExifProfile.Parts = ExifParts.ExifTags;
|
|
|
|
image.Metadata.ExifProfile.Parts = ExifParts.ExifTags; |
|
|
|
|
|
|
|
// image = WriteAndRead(image, imageFormat);
|
|
|
|
image = WriteAndRead(image, imageFormat); |
|
|
|
|
|
|
|
// Assert.NotNull(image.Metadata.ExifProfile);
|
|
|
|
// Assert.Equal(8, image.Metadata.ExifProfile.Values.Count());
|
|
|
|
Assert.NotNull(image.Metadata.ExifProfile); |
|
|
|
Assert.Equal(8, image.Metadata.ExifProfile.Values.Count); |
|
|
|
|
|
|
|
// Assert.NotNull(image.Metadata.ExifProfile.GetValue(ExifTag.ColorSpace));
|
|
|
|
// Assert.True(image.Metadata.ExifProfile.RemoveValue(ExifTag.ColorSpace));
|
|
|
|
// Assert.False(image.Metadata.ExifProfile.RemoveValue(ExifTag.ColorSpace));
|
|
|
|
// Assert.Null(image.Metadata.ExifProfile.GetValue(ExifTag.ColorSpace));
|
|
|
|
Assert.NotNull(image.Metadata.ExifProfile.GetValue(ExifTag.ColorSpace)); |
|
|
|
Assert.True(image.Metadata.ExifProfile.RemoveValue(ExifTag.ColorSpace)); |
|
|
|
Assert.False(image.Metadata.ExifProfile.RemoveValue(ExifTag.ColorSpace)); |
|
|
|
Assert.Null(image.Metadata.ExifProfile.GetValue(ExifTag.ColorSpace)); |
|
|
|
|
|
|
|
// Assert.Equal(7, image.Metadata.ExifProfile.Values.Count());
|
|
|
|
//}
|
|
|
|
Assert.Equal(7, image.Metadata.ExifProfile.Values.Count); |
|
|
|
} |
|
|
|
|
|
|
|
[Fact] |
|
|
|
public void Syncs() |
|
|
|
@ -308,8 +315,8 @@ namespace SixLabors.ImageSharp.Tests |
|
|
|
|
|
|
|
foreach (ExifTag expectedProfileTag in expectedProfileTags) |
|
|
|
{ |
|
|
|
IExifValue actualProfileValue = actualProfile.Values.First(x => x.Tag == expectedProfileTag); |
|
|
|
IExifValue expectedProfileValue = expectedProfile.Values.First(x => x.Tag == expectedProfileTag); |
|
|
|
IExifValue actualProfileValue = actualProfile.GetValueInternal(expectedProfileTag); |
|
|
|
IExifValue expectedProfileValue = expectedProfile.GetValueInternal(expectedProfileTag); |
|
|
|
Assert.Equal(expectedProfileValue.GetValue(), actualProfileValue.GetValue()); |
|
|
|
} |
|
|
|
|
|
|
|
@ -324,7 +331,6 @@ namespace SixLabors.ImageSharp.Tests |
|
|
|
{ |
|
|
|
// This image contains an 802 byte EXIF profile
|
|
|
|
// It has a tag with an index offset of 18,481,152 bytes (overrunning the data)
|
|
|
|
|
|
|
|
Image<Rgba32> image = TestFile.Create(TestImages.Jpeg.Progressive.Bad.ExifUndefType).CreateRgba32Image(); |
|
|
|
Assert.NotNull(image); |
|
|
|
|
|
|
|
@ -357,53 +363,52 @@ namespace SixLabors.ImageSharp.Tests |
|
|
|
Assert.Equal(525, bytes.Length); |
|
|
|
} |
|
|
|
|
|
|
|
//[Theory]
|
|
|
|
//[InlineData(TestImageWriteFormat.Jpeg)]
|
|
|
|
//[InlineData(TestImageWriteFormat.Png)]
|
|
|
|
//public void WritingImagePreservesExifProfile(TestImageWriteFormat imageFormat)
|
|
|
|
//{
|
|
|
|
// // arrange
|
|
|
|
// var image = new Image<Rgba32>(1, 1);
|
|
|
|
// ExifProfile expected = CreateExifProfile();
|
|
|
|
// image.Metadata.ExifProfile = expected;
|
|
|
|
|
|
|
|
// // act
|
|
|
|
// Image<Rgba32> reloadedImage = WriteAndRead(image, imageFormat);
|
|
|
|
|
|
|
|
// // assert
|
|
|
|
// ExifProfile actual = reloadedImage.Metadata.ExifProfile;
|
|
|
|
// Assert.NotNull(actual);
|
|
|
|
// foreach (KeyValuePair<ExifTag, object> expectedProfileValue in TestProfileValues)
|
|
|
|
// {
|
|
|
|
// ExifValue actualProfileValue = actual.GetValue(expectedProfileValue.Key);
|
|
|
|
// Assert.NotNull(actualProfileValue);
|
|
|
|
// Assert.Equal(expectedProfileValue.Value, actualProfileValue.Value);
|
|
|
|
// }
|
|
|
|
//}
|
|
|
|
|
|
|
|
//[Fact]
|
|
|
|
//public void ProfileToByteArray()
|
|
|
|
//{
|
|
|
|
// // arrange
|
|
|
|
// byte[] exifBytesWithoutExifCode = ExifConstants.LittleEndianByteOrderMarker;
|
|
|
|
// ExifProfile expectedProfile = CreateExifProfile();
|
|
|
|
// var expectedProfileTags = expectedProfile.Values.Select(x => x.Tag).ToList();
|
|
|
|
|
|
|
|
// // act
|
|
|
|
// byte[] actualBytes = expectedProfile.ToByteArray();
|
|
|
|
// var actualProfile = new ExifProfile(actualBytes);
|
|
|
|
|
|
|
|
// // assert
|
|
|
|
// Assert.NotNull(actualBytes);
|
|
|
|
// Assert.NotEmpty(actualBytes);
|
|
|
|
// Assert.Equal(exifBytesWithoutExifCode, actualBytes.Take(exifBytesWithoutExifCode.Length).ToArray());
|
|
|
|
// foreach (ExifTag expectedProfileTag in expectedProfileTags)
|
|
|
|
// {
|
|
|
|
// ExifValue actualProfileValue = actualProfile.GetValue(expectedProfileTag);
|
|
|
|
// ExifValue expectedProfileValue = expectedProfile.GetValue(expectedProfileTag);
|
|
|
|
// Assert.Equal(expectedProfileValue.Value, actualProfileValue.Value);
|
|
|
|
// }
|
|
|
|
//}
|
|
|
|
[Theory] |
|
|
|
[InlineData(TestImageWriteFormat.Jpeg)] |
|
|
|
[InlineData(TestImageWriteFormat.Png)] |
|
|
|
public void WritingImagePreservesExifProfile(TestImageWriteFormat imageFormat) |
|
|
|
{ |
|
|
|
// Arrange
|
|
|
|
var image = new Image<Rgba32>(1, 1); |
|
|
|
image.Metadata.ExifProfile = CreateExifProfile(); |
|
|
|
|
|
|
|
// Act
|
|
|
|
Image<Rgba32> reloadedImage = WriteAndRead(image, imageFormat); |
|
|
|
|
|
|
|
// Assert
|
|
|
|
ExifProfile actual = reloadedImage.Metadata.ExifProfile; |
|
|
|
Assert.NotNull(actual); |
|
|
|
foreach (KeyValuePair<ExifTag, object> expectedProfileValue in TestProfileValues) |
|
|
|
{ |
|
|
|
IExifValue actualProfileValue = actual.GetValueInternal(expectedProfileValue.Key); |
|
|
|
Assert.NotNull(actualProfileValue); |
|
|
|
Assert.Equal(expectedProfileValue.Value, actualProfileValue.GetValue()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
[Fact] |
|
|
|
public void ProfileToByteArray() |
|
|
|
{ |
|
|
|
// Arrange
|
|
|
|
byte[] exifBytesWithoutExifCode = ExifConstants.LittleEndianByteOrderMarker; |
|
|
|
ExifProfile expectedProfile = CreateExifProfile(); |
|
|
|
var expectedProfileTags = expectedProfile.Values.Select(x => x.Tag).ToList(); |
|
|
|
|
|
|
|
// Act
|
|
|
|
byte[] actualBytes = expectedProfile.ToByteArray(); |
|
|
|
var actualProfile = new ExifProfile(actualBytes); |
|
|
|
|
|
|
|
// Assert
|
|
|
|
Assert.NotNull(actualBytes); |
|
|
|
Assert.NotEmpty(actualBytes); |
|
|
|
Assert.Equal(exifBytesWithoutExifCode, actualBytes.Take(exifBytesWithoutExifCode.Length).ToArray()); |
|
|
|
foreach (ExifTag expectedProfileTag in expectedProfileTags) |
|
|
|
{ |
|
|
|
IExifValue actualProfileValue = actualProfile.GetValueInternal(expectedProfileTag); |
|
|
|
IExifValue expectedProfileValue = expectedProfile.GetValueInternal(expectedProfileTag); |
|
|
|
Assert.Equal(expectedProfileValue.GetValue(), actualProfileValue.GetValue()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private static ExifProfile CreateExifProfile() |
|
|
|
{ |
|
|
|
@ -411,12 +416,7 @@ namespace SixLabors.ImageSharp.Tests |
|
|
|
|
|
|
|
foreach (KeyValuePair<ExifTag, object> exifProfileValue in TestProfileValues) |
|
|
|
{ |
|
|
|
// Manky - Answers on a postcard for a nicer way to do this.
|
|
|
|
MethodInfo method = typeof(ExifProfile) |
|
|
|
.GetMethod("SetValue") |
|
|
|
.MakeGenericMethod(new[] { exifProfileValue.Key.GetType().GenericTypeArguments[0] }); |
|
|
|
|
|
|
|
method.Invoke(profile, new[] { exifProfileValue.Key, exifProfileValue.Value }); |
|
|
|
profile.SetValueInternal(exifProfileValue.Key, exifProfileValue.Value); |
|
|
|
} |
|
|
|
|
|
|
|
return profile; |
|
|
|
@ -434,12 +434,15 @@ namespace SixLabors.ImageSharp.Tests |
|
|
|
|
|
|
|
private static Image<Rgba32> WriteAndRead(Image<Rgba32> image, TestImageWriteFormat imageFormat) |
|
|
|
{ |
|
|
|
return imageFormat switch |
|
|
|
switch (imageFormat) |
|
|
|
{ |
|
|
|
TestImageWriteFormat.Jpeg => WriteAndReadJpeg(image), |
|
|
|
TestImageWriteFormat.Png => WriteAndReadPng(image), |
|
|
|
_ => throw new ArgumentException("Unexpected test image format, only Jpeg and Png are allowed"), |
|
|
|
}; |
|
|
|
case TestImageWriteFormat.Jpeg: |
|
|
|
return WriteAndReadJpeg(image); |
|
|
|
case TestImageWriteFormat.Png: |
|
|
|
return WriteAndReadPng(image); |
|
|
|
default: |
|
|
|
throw new ArgumentException("Unexpected test image format, only Jpeg and Png are allowed"); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private static Image<Rgba32> WriteAndReadJpeg(Image<Rgba32> image) |
|
|
|
@ -486,43 +489,5 @@ namespace SixLabors.ImageSharp.Tests |
|
|
|
IExifValue<Number> xDimension = profile.GetValue(ExifTag.PixelXDimension); |
|
|
|
Assert.Equal(2338U, xDimension.Value); |
|
|
|
} |
|
|
|
|
|
|
|
private static void TestValue(IExifValue value, string expected) |
|
|
|
{ |
|
|
|
Assert.NotNull(value); |
|
|
|
Assert.Equal(expected, value.GetValue()); |
|
|
|
} |
|
|
|
|
|
|
|
private static void TestValue(IExifValue value, Rational expected) |
|
|
|
{ |
|
|
|
Assert.NotNull(value); |
|
|
|
Assert.Equal(expected, value.GetValue()); |
|
|
|
} |
|
|
|
|
|
|
|
private static void TestValue(IExifValue value, SignedRational expected) |
|
|
|
{ |
|
|
|
Assert.NotNull(value); |
|
|
|
Assert.Equal(expected, value.GetValue()); |
|
|
|
} |
|
|
|
|
|
|
|
private static void TestValue(IExifValue value, Rational[] expected) |
|
|
|
{ |
|
|
|
Assert.NotNull(value); |
|
|
|
|
|
|
|
Assert.Equal(expected, (ICollection)value.GetValue()); |
|
|
|
} |
|
|
|
|
|
|
|
private static void TestValue(ExifValue value, double expected) |
|
|
|
{ |
|
|
|
Assert.NotNull(value); |
|
|
|
Assert.Equal(expected, value.GetValue()); |
|
|
|
} |
|
|
|
|
|
|
|
private static void TestValue(ExifValue value, double[] expected) |
|
|
|
{ |
|
|
|
Assert.NotNull(value); |
|
|
|
|
|
|
|
Assert.Equal(expected, (ICollection)value.GetValue()); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|