Browse Source

correct reading UCS-2 encoded string tags

pull/1935/head
Ildar Khayrutdinov 4 years ago
parent
commit
564912843d
  1. 69
      src/ImageSharp/Metadata/Profiles/Exif/ExifEncodedStringHelpers.cs
  2. 31
      src/ImageSharp/Metadata/Profiles/Exif/ExifReader.cs
  3. 12
      tests/ImageSharp.Tests/Metadata/Profiles/Exif/Values/ExifValuesTests.cs

69
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<byte> 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<byte> 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<byte> 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;
}
}
}

31
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<byte> buffer, bool isArray)
private object ConvertValue(ExifValue exifValue, ExifDataType dataType, ReadOnlySpan<byte> 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);
}
}

12
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<ExifTag> UndefinedTags => new TheoryData<ExifTag>

Loading…
Cancel
Save