diff --git a/src/ImageSharp/ImageSharp.csproj b/src/ImageSharp/ImageSharp.csproj
index 1b3a8e27f..7dac3c283 100644
--- a/src/ImageSharp/ImageSharp.csproj
+++ b/src/ImageSharp/ImageSharp.csproj
@@ -49,6 +49,7 @@
+
diff --git a/src/ImageSharp/Metadata/Profiles/Exif/ExifEncodedStringHelpers.cs b/src/ImageSharp/Metadata/Profiles/Exif/ExifEncodedStringHelpers.cs
index 6c95780d8..d14c0c47d 100644
--- a/src/ImageSharp/Metadata/Profiles/Exif/ExifEncodedStringHelpers.cs
+++ b/src/ImageSharp/Metadata/Profiles/Exif/ExifEncodedStringHelpers.cs
@@ -12,9 +12,9 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
{
public const int CharacterCodeBytesLength = 8;
- private const ulong AsciiCode = 0x_41_53_43_49_49_00_00_00;
- private const ulong JISCode = 0x_4A_49_53_00_00_00_00_00;
- private const ulong UnicodeCode = 0x_55_4E_49_43_4F_44_45_00;
+ private const ulong AsciiCode = 0x_00_00_00_49_49_43_53_41;
+ private const ulong JISCode = 0x_00_00_00_00_00_53_49_4A;
+ private const ulong UnicodeCode = 0x_45_44_4F_43_49_4E_55;
private const ulong UndefinedCode = 0x_00_00_00_00_00_00_00_00;
private static ReadOnlySpan AsciiCodeBytes => new byte[] { 0x41, 0x53, 0x43, 0x49, 0x49, 0, 0, 0 };
@@ -25,7 +25,13 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
private static ReadOnlySpan UndefinedCodeBytes => new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 };
- private static Encoding JIS0208Encoding => Encoding.GetEncoding(932);
+ private static Encoding JIS0208Encoding => CodePagesEncodingProvider.Instance.GetEncoding(932);
+
+ public static bool IsEncodedString(ExifTagValue tag) => tag switch
+ {
+ ExifTagValue.UserComment or ExifTagValue.GPSProcessingMethod or ExifTagValue.GPSAreaInformation => true,
+ _ => false
+ };
public static ReadOnlySpan GetCodeBytes(CharacterCode code) => code switch
{
@@ -45,7 +51,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
_ => Encoding.UTF8
};
- public static bool TryCreate(ReadOnlySpan buffer, out EncodedString encodedString)
+ public static bool TryParse(ReadOnlySpan buffer, out EncodedString encodedString)
{
if (TryDetect(buffer, out CharacterCode code))
{
@@ -61,17 +67,17 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
public static uint GetDataLength(EncodedString encodedString) =>
(uint)GetEncoding(encodedString.Code).GetByteCount(encodedString.Text) + CharacterCodeBytesLength;
- public static bool IsEncodedString(ExifTagValue tag)
+ public static byte[] GetData(EncodedString encodedString)
{
- switch (tag)
- {
- case ExifTagValue.UserComment:
- case ExifTagValue.GPSProcessingMethod:
- case ExifTagValue.GPSAreaInformation:
- return true;
- default:
- return false;
- }
+ int length = (int)GetDataLength(encodedString);
+ byte[] buffer = new byte[length];
+
+ GetCodeBytes(encodedString.Code).CopyTo(buffer);
+
+ string text = encodedString.Text;
+ GetEncoding(encodedString.Code).GetBytes(text, 0, text.Length, buffer, CharacterCodeBytesLength);
+
+ return buffer;
}
private static bool TryDetect(ReadOnlySpan buffer, out CharacterCode code)
diff --git a/src/ImageSharp/Metadata/Profiles/Exif/ExifReader.cs b/src/ImageSharp/Metadata/Profiles/Exif/ExifReader.cs
index 323c73c9a..23ead7d66 100644
--- a/src/ImageSharp/Metadata/Profiles/Exif/ExifReader.cs
+++ b/src/ImageSharp/Metadata/Profiles/Exif/ExifReader.cs
@@ -220,10 +220,6 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
if (this.TryReadSpan(buffer))
{
object value = this.ConvertValue(tag.Exif, tag.DataType, buffer, tag.NumberOfComponents > 1 || tag.Exif.IsArray);
- if (value is EncodedString)
- {
- // Console.WriteLine("EncodedString tag: " + (ushort)tag.Exif.Tag);
- }
this.Add(values, tag.Exif, value);
}
@@ -248,7 +244,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
private byte ConvertToByte(ReadOnlySpan buffer) => buffer[0];
- private string ConvertToString(ReadOnlySpan buffer)
+ private string ConvertToString(Encoding encoding, ReadOnlySpan buffer)
{
int nullCharIndex = buffer.IndexOf((byte)0);
@@ -257,7 +253,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
buffer = buffer.Slice(0, nullCharIndex);
}
- return ExifConstants.DefaultEncoding.GetString(buffer);
+ return encoding.GetString(buffer);
}
private object ConvertValue(ExifValue exifValue, ExifDataType dataType, ReadOnlySpan buffer, bool isArray)
@@ -267,35 +263,20 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
return null;
}
- var tagValue = (ExifTagValue)(ushort)exifValue.Tag;
- if (ExifUcs2StringHelpers.IsUcs2Tag(tagValue))
- {
- return ExifUcs2StringHelpers.ConvertToString(buffer);
- }
- else if (ExifEncodedStringHelpers.IsEncodedString(tagValue))
- {
- if (ExifEncodedStringHelpers.TryCreate(buffer, out EncodedString encodedString))
- {
- return encodedString;
- }
- }
-
switch (dataType)
{
case ExifDataType.Unknown:
return null;
case ExifDataType.Ascii:
- return this.ConvertToString(buffer);
+ return this.ConvertToString(ExifConstants.DefaultEncoding, buffer);
case ExifDataType.Byte:
case ExifDataType.Undefined:
- {
if (!isArray)
{
return this.ConvertToByte(buffer);
}
- return ExifEncodedStringHelpers.TryCreate(buffer, out EncodedString encodedString) ? encodedString : buffer.ToArray();
- }
+ return buffer.ToArray();
case ExifDataType.DoubleFloat:
if (!isArray)
diff --git a/src/ImageSharp/Metadata/Profiles/Exif/ExifUcs2StringHelpers.cs b/src/ImageSharp/Metadata/Profiles/Exif/ExifUcs2StringHelpers.cs
index cff6fe612..82ea0eaba 100644
--- a/src/ImageSharp/Metadata/Profiles/Exif/ExifUcs2StringHelpers.cs
+++ b/src/ImageSharp/Metadata/Profiles/Exif/ExifUcs2StringHelpers.cs
@@ -10,21 +10,10 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
{
public static Encoding Ucs2Encoding => Encoding.GetEncoding("UCS-2");
- public static bool IsUcs2Tag(ExifTagValue tag)
+ public static bool IsUcs2Tag(ExifTagValue tag) => tag switch
{
- switch (tag)
- {
- case ExifTagValue.XPAuthor:
- case ExifTagValue.XPComment:
- case ExifTagValue.XPKeywords:
- case ExifTagValue.XPSubject:
- case ExifTagValue.XPTitle:
- return true;
- default:
- return false;
- }
- }
-
- public static string ConvertToString(ReadOnlySpan buffer) => Ucs2Encoding.GetString(buffer);
+ ExifTagValue.XPAuthor or ExifTagValue.XPComment or ExifTagValue.XPKeywords or ExifTagValue.XPSubject or ExifTagValue.XPTitle => true,
+ _ => false,
+ };
}
}
diff --git a/src/ImageSharp/Metadata/Profiles/Exif/ExifWriter.cs b/src/ImageSharp/Metadata/Profiles/Exif/ExifWriter.cs
index f52d2a314..2f1846a82 100644
--- a/src/ImageSharp/Metadata/Profiles/Exif/ExifWriter.cs
+++ b/src/ImageSharp/Metadata/Profiles/Exif/ExifWriter.cs
@@ -274,9 +274,9 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
{
object value = exifValue.GetValue();
- if (exifValue.DataType == ExifDataType.Ascii)
+ if (ExifUcs2StringHelpers.IsUcs2Tag((ExifTagValue)(ushort)exifValue.Tag))
{
- return (uint)(ExifUcs2StringHelpers.IsUcs2Tag((ExifTagValue)(ushort)exifValue.Tag) ? ExifUcs2StringHelpers.Ucs2Encoding : ExifConstants.DefaultEncoding).GetByteCount((string)value) + 1;
+ return (uint)ExifUcs2StringHelpers.Ucs2Encoding.GetByteCount((string)value);
}
if (value is EncodedString encodedString)
@@ -284,6 +284,11 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
return ExifEncodedStringHelpers.GetDataLength(encodedString);
}
+ if (exifValue.DataType == ExifDataType.Ascii)
+ {
+ return (uint)ExifConstants.DefaultEncoding.GetByteCount((string)value) + 1;
+ }
+
if (value is Array arrayValue)
{
return (uint)arrayValue.Length;
@@ -378,21 +383,14 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
switch (dataType)
{
case ExifDataType.Ascii:
- offset = Write((ExifUcs2StringHelpers.IsUcs2Tag((ExifTagValue)(ushort)exifValue.Tag) ? ExifUcs2StringHelpers.Ucs2Encoding : ExifConstants.DefaultEncoding).GetBytes((string)value), destination, offset);
+ offset = Write(ExifConstants.DefaultEncoding.GetBytes((string)value), destination, offset);
destination[offset] = 0;
return offset + 1;
case ExifDataType.Byte:
case ExifDataType.Undefined:
- if (value is EncodedString encodedString)
+ if (value is byte[] array)
{
- ReadOnlySpan codeBytes = ExifEncodedStringHelpers.GetCodeBytes(encodedString.Code);
- codeBytes.CopyTo(destination.Slice(offset));
- offset += codeBytes.Length;
-
- ReadOnlySpan dataBytes = ExifEncodedStringHelpers.GetEncoding(encodedString.Code).GetBytes(encodedString.Text);
- dataBytes.CopyTo(destination.Slice(offset));
- offset += dataBytes.Length;
-
+ offset = Write(array, destination, offset);
return offset;
}
else
@@ -441,14 +439,25 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
}
}
- internal static int WriteValue(IExifValue value, Span destination, int offset)
+ internal static int WriteValue(IExifValue exifValue, Span destination, int offset)
{
- if (value.IsArray)
+ object value = exifValue.GetValue();
+
+ if (ExifUcs2StringHelpers.IsUcs2Tag((ExifTagValue)(ushort)exifValue.Tag))
+ {
+ value = ExifUcs2StringHelpers.Ucs2Encoding.GetBytes((string)value);
+ }
+ else if (value is EncodedString encodedString)
+ {
+ value = ExifEncodedStringHelpers.GetData(encodedString);
+ }
+
+ if (exifValue.IsArray)
{
- return WriteArray(value, destination, offset);
+ return WriteArray(exifValue, destination, offset);
}
- return WriteValue(value, value.DataType, value.GetValue(), destination, offset);
+ return WriteValue(exifValue, exifValue.DataType, value, destination, offset);
}
}
}
diff --git a/src/ImageSharp/Metadata/Profiles/Exif/Tags/ExifTag.String.cs b/src/ImageSharp/Metadata/Profiles/Exif/Tags/ExifTag.String.cs
index 10d50dc6a..3fc353211 100644
--- a/src/ImageSharp/Metadata/Profiles/Exif/Tags/ExifTag.String.cs
+++ b/src/ImageSharp/Metadata/Profiles/Exif/Tags/ExifTag.String.cs
@@ -275,30 +275,5 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
/// Gets the GPSDateStamp exif tag.
///
public static ExifTag GPSDateStamp { get; } = new ExifTag(ExifTagValue.GPSDateStamp);
-
- ///
- /// Gets the title tag used by Windows (encoded in UCS2).
- ///
- public static ExifTag XPTitle => new ExifTag(ExifTagValue.XPTitle);
-
- ///
- /// Gets the comment tag used by Windows (encoded in UCS2).
- ///
- public static ExifTag XPComment => new ExifTag(ExifTagValue.XPComment);
-
- ///
- /// Gets the author tag used by Windows (encoded in UCS2).
- ///
- public static ExifTag XPAuthor => new ExifTag(ExifTagValue.XPAuthor);
-
- ///
- /// Gets the keywords tag used by Windows (encoded in UCS2).
- ///
- public static ExifTag XPKeywords => new ExifTag(ExifTagValue.XPKeywords);
-
- ///
- /// Gets the subject tag used by Windows (encoded in UCS2).
- ///
- public static ExifTag XPSubject => new ExifTag(ExifTagValue.XPSubject);
}
}
diff --git a/src/ImageSharp/Metadata/Profiles/Exif/Tags/ExifTag.Ucs2String.cs b/src/ImageSharp/Metadata/Profiles/Exif/Tags/ExifTag.Ucs2String.cs
new file mode 100644
index 000000000..a6911d76d
--- /dev/null
+++ b/src/ImageSharp/Metadata/Profiles/Exif/Tags/ExifTag.Ucs2String.cs
@@ -0,0 +1,34 @@
+// Copyright (c) Six Labors.
+// Licensed under the Apache License, Version 2.0.
+
+namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
+{
+ ///
+ public abstract partial class ExifTag
+ {
+ ///
+ /// Gets the title tag used by Windows (encoded in UCS2).
+ ///
+ public static ExifTag XPTitle => new ExifTag(ExifTagValue.XPTitle);
+
+ ///
+ /// Gets the comment tag used by Windows (encoded in UCS2).
+ ///
+ public static ExifTag XPComment => new ExifTag(ExifTagValue.XPComment);
+
+ ///
+ /// Gets the author tag used by Windows (encoded in UCS2).
+ ///
+ public static ExifTag XPAuthor => new ExifTag(ExifTagValue.XPAuthor);
+
+ ///
+ /// Gets the keywords tag used by Windows (encoded in UCS2).
+ ///
+ public static ExifTag XPKeywords => new ExifTag(ExifTagValue.XPKeywords);
+
+ ///
+ /// Gets the subject tag used by Windows (encoded in UCS2).
+ ///
+ public static ExifTag XPSubject => new ExifTag(ExifTagValue.XPSubject);
+ }
+}
diff --git a/src/ImageSharp/Metadata/Profiles/Exif/Values/EncodedString.cs b/src/ImageSharp/Metadata/Profiles/Exif/Values/EncodedString.cs
index 08181fc1f..910a7e06f 100644
--- a/src/ImageSharp/Metadata/Profiles/Exif/Values/EncodedString.cs
+++ b/src/ImageSharp/Metadata/Profiles/Exif/Values/EncodedString.cs
@@ -66,6 +66,18 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
///
public string Text { get; }
+ ///
+ /// Converts the specified to an instance of this type.
+ ///
+ /// The text value.
+ public static implicit operator EncodedString(string text) => new(text);
+
+ ///
+ /// Converts the specified to a .
+ ///
+ /// The to convert.
+ public static explicit operator string(EncodedString encodedString) => encodedString.Text;
+
///
public override bool Equals(object obj) => obj is EncodedString other && this.Equals(other);
diff --git a/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifEncodedString.cs b/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifEncodedString.cs
index 4055573c5..ba9fca5c8 100644
--- a/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifEncodedString.cs
+++ b/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifEncodedString.cs
@@ -38,6 +38,14 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
this.Value = new EncodedString(stringValue);
return true;
}
+ else if (value is byte[] buffer)
+ {
+ if (ExifEncodedStringHelpers.TryParse(buffer, out EncodedString encodedString))
+ {
+ this.Value = encodedString;
+ return true;
+ }
+ }
return false;
}
diff --git a/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifUcs2String.cs b/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifUcs2String.cs
new file mode 100644
index 000000000..42637925c
--- /dev/null
+++ b/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifUcs2String.cs
@@ -0,0 +1,47 @@
+// Copyright (c) Six Labors.
+// Licensed under the Apache License, Version 2.0.
+
+namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
+{
+ internal sealed class ExifUcs2String : ExifValue
+ {
+ public ExifUcs2String(ExifTag tag)
+ : base(tag)
+ {
+ }
+
+ public ExifUcs2String(ExifTagValue tag)
+ : base(tag)
+ {
+ }
+
+ private ExifUcs2String(ExifUcs2String value)
+ : base(value)
+ {
+ }
+
+ public override ExifDataType DataType => ExifDataType.Byte;
+
+ protected override string StringValue => this.Value;
+
+ public override object GetValue() => this.Value;
+
+ public override bool TrySetValue(object value)
+ {
+ if (base.TrySetValue(value))
+ {
+ return true;
+ }
+
+ if (value is byte[] buffer)
+ {
+ this.Value = ExifUcs2StringHelpers.Ucs2Encoding.GetString(buffer);
+ return true;
+ }
+
+ return false;
+ }
+
+ public override IExifValue DeepClone() => new ExifUcs2String(this);
+ }
+}
diff --git a/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifValues.cs b/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifValues.cs
index 54e809ba9..3795e47a4 100644
--- a/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifValues.cs
+++ b/src/ImageSharp/Metadata/Profiles/Exif/Values/ExifValues.cs
@@ -280,11 +280,6 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
case ExifTagValue.GPSDestBearingRef: return new ExifString(ExifTag.GPSDestBearingRef);
case ExifTagValue.GPSDestDistanceRef: return new ExifString(ExifTag.GPSDestDistanceRef);
case ExifTagValue.GPSDateStamp: return new ExifString(ExifTag.GPSDateStamp);
- case ExifTagValue.XPTitle: return new ExifString(ExifTag.XPTitle);
- case ExifTagValue.XPComment: return new ExifString(ExifTag.XPComment);
- case ExifTagValue.XPAuthor: return new ExifString(ExifTag.XPAuthor);
- case ExifTagValue.XPKeywords: return new ExifString(ExifTag.XPKeywords);
- case ExifTagValue.XPSubject: return new ExifString(ExifTag.XPSubject);
case ExifTagValue.FileSource: return new ExifByte(ExifTag.FileSource, ExifDataType.Undefined);
case ExifTagValue.SceneType: return new ExifByte(ExifTag.SceneType, ExifDataType.Undefined);
@@ -302,6 +297,12 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
case ExifTagValue.DeviceSettingDescription: return new ExifByteArray(ExifTag.DeviceSettingDescription, ExifDataType.Undefined);
case ExifTagValue.ImageSourceData: return new ExifByteArray(ExifTag.ImageSourceData, ExifDataType.Undefined);
+ case ExifTagValue.XPTitle: return new ExifUcs2String(ExifTag.XPTitle);
+ case ExifTagValue.XPComment: return new ExifUcs2String(ExifTag.XPComment);
+ case ExifTagValue.XPAuthor: return new ExifUcs2String(ExifTag.XPAuthor);
+ case ExifTagValue.XPKeywords: return new ExifUcs2String(ExifTag.XPKeywords);
+ case ExifTagValue.XPSubject: return new ExifUcs2String(ExifTag.XPSubject);
+
case ExifTagValue.UserComment: return new ExifEncodedString(ExifTag.UserComment);
case ExifTagValue.GPSProcessingMethod: return new ExifEncodedString(ExifTag.GPSProcessingMethod);
case ExifTagValue.GPSAreaInformation: return new ExifEncodedString(ExifTag.GPSAreaInformation);
diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Metadata.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Metadata.cs
index 6e0a79db0..85e5a54bf 100644
--- a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Metadata.cs
+++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Metadata.cs
@@ -303,32 +303,56 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
}
[Fact]
- public void ExifIfdStructure()
+ public void EncodedStringTags()
{
byte[] exifBytes;
using var memoryStream = new MemoryStream();
using (var image = Image.Load(TestFile.GetInputFileFullPath(TestImages.Jpeg.Baseline.Calliphora)))
{
var exif = new ExifProfile();
- exif.SetValue(ExifTag.XPAuthor, "Dan Petitt");
-
- exif.SetValue(ExifTag.XPTitle, "A bit of test metadata for image title");
- exif.SetValue(ExifTag.UserComment, new EncodedString(EncodedString.CharacterCode.ASCII, "A bit of normal comment text"));
exif.SetValue(ExifTag.GPSDateStamp, "2022-01-06");
- exif.SetValue(ExifTag.XPKeywords, "Keywords");
- image.Metadata.ExifProfile = exif;
+ exif.SetValue(ExifTag.XPTitle, "A bit of test metadata for image title");
+ exif.SetValue(ExifTag.XPComment, "A bit of test metadata for image comment");
+ exif.SetValue(ExifTag.XPAuthor, "Dan Petitt");
+ exif.SetValue(ExifTag.XPKeywords, "Keyword1;Keyword2");
+ exif.SetValue(ExifTag.XPSubject, "This is a subject");
+
+ exif.SetValue(ExifTag.UserComment, new EncodedString(EncodedString.CharacterCode.ASCII, "user comment (ASCII)"));
+ exif.SetValue(ExifTag.GPSProcessingMethod, new EncodedString(EncodedString.CharacterCode.JIS, "GPS processing method (JIS)"));
+ exif.SetValue(ExifTag.GPSAreaInformation, new EncodedString(EncodedString.CharacterCode.Unicode, "GPS area info (Unicode)"));
exifBytes = exif.ToByteArray();
+ image.Metadata.ExifProfile = exif;
+
+ image.Save(@"c:\\temp\1.jpeg");
image.Save(memoryStream, new JpegEncoder());
}
memoryStream.Seek(0, SeekOrigin.Begin);
using (var image = Image.Load(memoryStream))
{
- Assert.NotNull(image.Metadata.ExifProfile);
+ ExifProfile exif = image.Metadata.ExifProfile;
+ Assert.NotNull(exif);
+
+ Assert.Equal("2022-01-06", exif.GetValue(ExifTag.GPSDateStamp).Value);
+
+ Assert.Equal("A bit of test metadata for image title", exif.GetValue(ExifTag.XPTitle).Value);
+ Assert.Equal("A bit of test metadata for image comment", exif.GetValue(ExifTag.XPComment).Value);
+ Assert.Equal("Dan Petitt", exif.GetValue(ExifTag.XPAuthor).Value);
+ Assert.Equal("Keyword1;Keyword2", exif.GetValue(ExifTag.XPKeywords).Value);
+ Assert.Equal("This is a subject", exif.GetValue(ExifTag.XPSubject).Value);
+
+ Assert.Equal("user comment (ASCII)", exif.GetValue(ExifTag.UserComment).Value.Text);
+ Assert.Equal(EncodedString.CharacterCode.ASCII, exif.GetValue(ExifTag.UserComment).Value.Code);
+
+ Assert.Equal("GPS processing method (JIS)", exif.GetValue(ExifTag.GPSProcessingMethod).Value.Text);
+ Assert.Equal(EncodedString.CharacterCode.JIS, exif.GetValue(ExifTag.GPSProcessingMethod).Value.Code);
+
+ Assert.Equal("GPS area info (Unicode)", exif.GetValue(ExifTag.GPSAreaInformation).Value.Text);
+ Assert.Equal(EncodedString.CharacterCode.Unicode, exif.GetValue(ExifTag.GPSAreaInformation).Value.Code);
}
}
}
diff --git a/tests/ImageSharp.Tests/Metadata/Profiles/Exif/ExifProfileTests.cs b/tests/ImageSharp.Tests/Metadata/Profiles/Exif/ExifProfileTests.cs
index 2b68d2fd1..9b589e58e 100644
--- a/tests/ImageSharp.Tests/Metadata/Profiles/Exif/ExifProfileTests.cs
+++ b/tests/ImageSharp.Tests/Metadata/Profiles/Exif/ExifProfileTests.cs
@@ -591,7 +591,7 @@ namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.Exif
foreach (IExifValue value in profile.Values)
{
Assert.NotNull(value.GetValue());
- }
+ }
IExifValue software = profile.GetValue(ExifTag.Software);
Assert.Equal("Windows Photo Editor 10.0.10011.16384", software.Value);
diff --git a/tests/ImageSharp.Tests/Metadata/Profiles/Exif/Values/ExifValuesTests.cs b/tests/ImageSharp.Tests/Metadata/Profiles/Exif/Values/ExifValuesTests.cs
index b668a2a1f..acb614c61 100644
--- a/tests/ImageSharp.Tests/Metadata/Profiles/Exif/Values/ExifValuesTests.cs
+++ b/tests/ImageSharp.Tests/Metadata/Profiles/Exif/Values/ExifValuesTests.cs
@@ -1,6 +1,8 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
+using System;
+using System.Text;
using SixLabors.ImageSharp.Metadata.Profiles.Exif;
using Xunit;
@@ -291,11 +293,6 @@ namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.Exif.Values
{ ExifTag.GPSDestBearingRef },
{ ExifTag.GPSDestDistanceRef },
{ ExifTag.GPSDateStamp },
- { ExifTag.XPTitle },
- { ExifTag.XPComment },
- { ExifTag.XPAuthor },
- { ExifTag.XPKeywords },
- { ExifTag.XPSubject },
};
public static TheoryData UndefinedTags => new TheoryData
@@ -327,6 +324,15 @@ namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.Exif.Values
{ ExifTag.GPSAreaInformation }
};
+ public static TheoryData Ucs2StringTags => new TheoryData
+ {
+ { ExifTag.XPTitle },
+ { ExifTag.XPComment },
+ { ExifTag.XPAuthor },
+ { ExifTag.XPKeywords },
+ { ExifTag.XPSubject },
+ };
+
[Theory]
[MemberData(nameof(ByteTags))]
public void ExifByteTests(ExifTag tag)
@@ -602,13 +608,38 @@ namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.Exif.Values
[MemberData(nameof(EncodedStringTags))]
public void ExifEncodedStringTests(ExifTag tag)
{
- var expected = new EncodedString(EncodedString.CharacterCode.JIS, "test string");
+ foreach (object code in Enum.GetValues(typeof(EncodedString.CharacterCode)))
+ {
+ var charCode = (EncodedString.CharacterCode)code;
+
+ const string expectedText = "test string";
+ var expected = new EncodedString(charCode, expectedText);
+ ExifValue value = ExifValues.Create(tag);
+
+ Assert.False(value.TrySetValue(123));
+ Assert.True(value.TrySetValue(expected));
+
+ var typed = (ExifEncodedString)value;
+ Assert.Equal(expected, typed.Value);
+ Assert.Equal(expectedText, (string)typed.Value);
+ Assert.Equal(charCode, typed.Value.Code);
+ }
+ }
+
+ [Theory]
+ [MemberData(nameof(Ucs2StringTags))]
+ public void ExifUcs2StringTests(ExifTag tag)
+ {
+ const string expected = "Dan Petitt";
ExifValue value = ExifValues.Create(tag);
Assert.False(value.TrySetValue(123));
Assert.True(value.TrySetValue(expected));
- var typed = (ExifEncodedString)value;
+ var typed = (ExifUcs2String)value;
+ Assert.Equal(expected, typed.Value);
+
+ Assert.True(value.TrySetValue(Encoding.GetEncoding("UCS-2").GetBytes(expected)));
Assert.Equal(expected, typed.Value);
}
}