diff --git a/src/ImageSharp/Metadata/Profiles/Exif/ExifEncodedStringHelpers.cs b/src/ImageSharp/Metadata/Profiles/Exif/ExifEncodedStringHelpers.cs index c519fb23d..6c95780d8 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/ExifEncodedStringHelpers.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/ExifEncodedStringHelpers.cs @@ -27,34 +27,6 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif private static Encoding JIS0208Encoding => Encoding.GetEncoding(932); - private static bool TryDetect(ReadOnlySpan buffer, out CharacterCode code) - { - if (buffer.Length >= CharacterCodeBytesLength) - { - ulong test = BinaryPrimitives.ReadUInt64LittleEndian(buffer); - switch (test) - { - case AsciiCode: - code = CharacterCode.ASCII; - return true; - case JISCode: - code = CharacterCode.JIS; - return true; - case UnicodeCode: - code = CharacterCode.Unicode; - return true; - case UndefinedCode: - code = CharacterCode.Undefined; - return true; - default: - break; - } - } - - code = default; - return false; - } - public static ReadOnlySpan GetCodeBytes(CharacterCode code) => code switch { CharacterCode.ASCII => AsciiCodeBytes, @@ -88,5 +60,46 @@ 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) + { + switch (tag) + { + case ExifTagValue.UserComment: + case ExifTagValue.GPSProcessingMethod: + case ExifTagValue.GPSAreaInformation: + return true; + default: + return false; + } + } + + private static bool TryDetect(ReadOnlySpan buffer, out CharacterCode code) + { + if (buffer.Length >= CharacterCodeBytesLength) + { + ulong test = BinaryPrimitives.ReadUInt64LittleEndian(buffer); + switch (test) + { + case AsciiCode: + code = CharacterCode.ASCII; + return true; + case JISCode: + code = CharacterCode.JIS; + return true; + case UnicodeCode: + code = CharacterCode.Unicode; + return true; + case UndefinedCode: + code = CharacterCode.Undefined; + return true; + default: + break; + } + } + + code = default; + return false; + } } } diff --git a/src/ImageSharp/Metadata/Profiles/Exif/ExifReader.cs b/src/ImageSharp/Metadata/Profiles/Exif/ExifReader.cs index f50ecbad8..323c73c9a 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/ExifReader.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/ExifReader.cs @@ -219,7 +219,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif this.Seek(tag.Offset); if (this.TryReadSpan(buffer)) { - object value = this.ConvertValue(tag.DataType, buffer, tag.NumberOfComponents > 1 || tag.Exif.IsArray); + 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); @@ -260,13 +260,26 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif return ExifConstants.DefaultEncoding.GetString(buffer); } - private object ConvertValue(ExifDataType dataType, ReadOnlySpan buffer, bool isArray) + private object ConvertValue(ExifValue exifValue, ExifDataType dataType, ReadOnlySpan buffer, bool isArray) { if (buffer.Length == 0) { 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: @@ -274,6 +287,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif case ExifDataType.Ascii: return this.ConvertToString(buffer); case ExifDataType.Byte: + case ExifDataType.Undefined: { if (!isArray) { @@ -362,15 +376,6 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif } return ToArray(dataType, buffer, this.ConvertToUInt64); - case ExifDataType.Undefined: - { - if (!isArray) - { - return this.ConvertToByte(buffer); - } - - return ExifEncodedStringHelpers.TryCreate(buffer, out EncodedString encodedString) ? encodedString : buffer.ToArray(); - } default: throw new NotSupportedException($"Data type {dataType} is not supported."); @@ -430,7 +435,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif } else { - object value = this.ConvertValue(dataType, offsetBuffer.Slice(0, (int)size), numberOfComponents > 1 || exifValue.IsArray); + object value = this.ConvertValue(exifValue, dataType, offsetBuffer.Slice(0, (int)size), numberOfComponents > 1 || exifValue.IsArray); this.Add(values, exifValue, value); } } @@ -504,7 +509,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif } else { - object value = this.ConvertValue(dataType, offsetBuffer.Slice(0, (int)size), numberOfComponents > 1 || exifValue.IsArray); + object value = this.ConvertValue(exifValue, dataType, offsetBuffer.Slice(0, (int)size), numberOfComponents > 1 || exifValue.IsArray); this.Add(values, exifValue, value); } } diff --git a/tests/ImageSharp.Tests/Metadata/Profiles/Exif/Values/ExifValuesTests.cs b/tests/ImageSharp.Tests/Metadata/Profiles/Exif/Values/ExifValuesTests.cs index a121941e5..b668a2a1f 100644 --- a/tests/ImageSharp.Tests/Metadata/Profiles/Exif/Values/ExifValuesTests.cs +++ b/tests/ImageSharp.Tests/Metadata/Profiles/Exif/Values/ExifValuesTests.cs @@ -23,11 +23,6 @@ namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.Exif.Values { ExifTag.XMP }, { ExifTag.CFAPattern2 }, { ExifTag.TIFFEPStandardID }, - { ExifTag.XPTitle }, - { ExifTag.XPComment }, - { ExifTag.XPAuthor }, - { ExifTag.XPKeywords }, - { ExifTag.XPSubject }, { ExifTag.GPSVersionID }, }; @@ -295,7 +290,12 @@ namespace SixLabors.ImageSharp.Tests.Metadata.Profiles.Exif.Values { ExifTag.GPSDestLongitudeRef }, { ExifTag.GPSDestBearingRef }, { ExifTag.GPSDestDistanceRef }, - { ExifTag.GPSDateStamp } + { ExifTag.GPSDateStamp }, + { ExifTag.XPTitle }, + { ExifTag.XPComment }, + { ExifTag.XPAuthor }, + { ExifTag.XPKeywords }, + { ExifTag.XPSubject }, }; public static TheoryData UndefinedTags => new TheoryData