Skip to content

Commit 5649128

Browse files
correct reading UCS-2 encoded string tags
1 parent cbb4514 commit 5649128

File tree

3 files changed

+65
-47
lines changed

3 files changed

+65
-47
lines changed

src/ImageSharp/Metadata/Profiles/Exif/ExifEncodedStringHelpers.cs

Lines changed: 41 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -27,34 +27,6 @@ internal static class ExifEncodedStringHelpers
2727

2828
private static Encoding JIS0208Encoding => Encoding.GetEncoding(932);
2929

30-
private static bool TryDetect(ReadOnlySpan<byte> buffer, out CharacterCode code)
31-
{
32-
if (buffer.Length >= CharacterCodeBytesLength)
33-
{
34-
ulong test = BinaryPrimitives.ReadUInt64LittleEndian(buffer);
35-
switch (test)
36-
{
37-
case AsciiCode:
38-
code = CharacterCode.ASCII;
39-
return true;
40-
case JISCode:
41-
code = CharacterCode.JIS;
42-
return true;
43-
case UnicodeCode:
44-
code = CharacterCode.Unicode;
45-
return true;
46-
case UndefinedCode:
47-
code = CharacterCode.Undefined;
48-
return true;
49-
default:
50-
break;
51-
}
52-
}
53-
54-
code = default;
55-
return false;
56-
}
57-
5830
public static ReadOnlySpan<byte> GetCodeBytes(CharacterCode code) => code switch
5931
{
6032
CharacterCode.ASCII => AsciiCodeBytes,
@@ -88,5 +60,46 @@ public static bool TryCreate(ReadOnlySpan<byte> buffer, out EncodedString encode
8860

8961
public static uint GetDataLength(EncodedString encodedString) =>
9062
(uint)GetEncoding(encodedString.Code).GetByteCount(encodedString.Text) + CharacterCodeBytesLength;
63+
64+
public static bool IsEncodedString(ExifTagValue tag)
65+
{
66+
switch (tag)
67+
{
68+
case ExifTagValue.UserComment:
69+
case ExifTagValue.GPSProcessingMethod:
70+
case ExifTagValue.GPSAreaInformation:
71+
return true;
72+
default:
73+
return false;
74+
}
75+
}
76+
77+
private static bool TryDetect(ReadOnlySpan<byte> buffer, out CharacterCode code)
78+
{
79+
if (buffer.Length >= CharacterCodeBytesLength)
80+
{
81+
ulong test = BinaryPrimitives.ReadUInt64LittleEndian(buffer);
82+
switch (test)
83+
{
84+
case AsciiCode:
85+
code = CharacterCode.ASCII;
86+
return true;
87+
case JISCode:
88+
code = CharacterCode.JIS;
89+
return true;
90+
case UnicodeCode:
91+
code = CharacterCode.Unicode;
92+
return true;
93+
case UndefinedCode:
94+
code = CharacterCode.Undefined;
95+
return true;
96+
default:
97+
break;
98+
}
99+
}
100+
101+
code = default;
102+
return false;
103+
}
91104
}
92105
}

src/ImageSharp/Metadata/Profiles/Exif/ExifReader.cs

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ protected void ReadBigValue(IList<IExifValue> values, (ulong Offset, ExifDataTyp
219219
this.Seek(tag.Offset);
220220
if (this.TryReadSpan(buffer))
221221
{
222-
object value = this.ConvertValue(tag.DataType, buffer, tag.NumberOfComponents > 1 || tag.Exif.IsArray);
222+
object value = this.ConvertValue(tag.Exif, tag.DataType, buffer, tag.NumberOfComponents > 1 || tag.Exif.IsArray);
223223
if (value is EncodedString)
224224
{
225225
// Console.WriteLine("EncodedString tag: " + (ushort)tag.Exif.Tag);
@@ -260,20 +260,34 @@ private string ConvertToString(ReadOnlySpan<byte> buffer)
260260
return ExifConstants.DefaultEncoding.GetString(buffer);
261261
}
262262

263-
private object ConvertValue(ExifDataType dataType, ReadOnlySpan<byte> buffer, bool isArray)
263+
private object ConvertValue(ExifValue exifValue, ExifDataType dataType, ReadOnlySpan<byte> buffer, bool isArray)
264264
{
265265
if (buffer.Length == 0)
266266
{
267267
return null;
268268
}
269269

270+
var tagValue = (ExifTagValue)(ushort)exifValue.Tag;
271+
if (ExifUcs2StringHelpers.IsUcs2Tag(tagValue))
272+
{
273+
return ExifUcs2StringHelpers.ConvertToString(buffer);
274+
}
275+
else if (ExifEncodedStringHelpers.IsEncodedString(tagValue))
276+
{
277+
if (ExifEncodedStringHelpers.TryCreate(buffer, out EncodedString encodedString))
278+
{
279+
return encodedString;
280+
}
281+
}
282+
270283
switch (dataType)
271284
{
272285
case ExifDataType.Unknown:
273286
return null;
274287
case ExifDataType.Ascii:
275288
return this.ConvertToString(buffer);
276289
case ExifDataType.Byte:
290+
case ExifDataType.Undefined:
277291
{
278292
if (!isArray)
279293
{
@@ -362,15 +376,6 @@ private object ConvertValue(ExifDataType dataType, ReadOnlySpan<byte> buffer, bo
362376
}
363377

364378
return ToArray(dataType, buffer, this.ConvertToUInt64);
365-
case ExifDataType.Undefined:
366-
{
367-
if (!isArray)
368-
{
369-
return this.ConvertToByte(buffer);
370-
}
371-
372-
return ExifEncodedStringHelpers.TryCreate(buffer, out EncodedString encodedString) ? encodedString : buffer.ToArray();
373-
}
374379

375380
default:
376381
throw new NotSupportedException($"Data type {dataType} is not supported.");
@@ -430,7 +435,7 @@ private void ReadValue(List<IExifValue> values, Span<byte> offsetBuffer)
430435
}
431436
else
432437
{
433-
object value = this.ConvertValue(dataType, offsetBuffer.Slice(0, (int)size), numberOfComponents > 1 || exifValue.IsArray);
438+
object value = this.ConvertValue(exifValue, dataType, offsetBuffer.Slice(0, (int)size), numberOfComponents > 1 || exifValue.IsArray);
434439
this.Add(values, exifValue, value);
435440
}
436441
}
@@ -504,7 +509,7 @@ private void ReadValue64(List<IExifValue> values, Span<byte> offsetBuffer)
504509
}
505510
else
506511
{
507-
object value = this.ConvertValue(dataType, offsetBuffer.Slice(0, (int)size), numberOfComponents > 1 || exifValue.IsArray);
512+
object value = this.ConvertValue(exifValue, dataType, offsetBuffer.Slice(0, (int)size), numberOfComponents > 1 || exifValue.IsArray);
508513
this.Add(values, exifValue, value);
509514
}
510515
}

tests/ImageSharp.Tests/Metadata/Profiles/Exif/Values/ExifValuesTests.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,6 @@ public class ExifValuesTests
2323
{ ExifTag.XMP },
2424
{ ExifTag.CFAPattern2 },
2525
{ ExifTag.TIFFEPStandardID },
26-
{ ExifTag.XPTitle },
27-
{ ExifTag.XPComment },
28-
{ ExifTag.XPAuthor },
29-
{ ExifTag.XPKeywords },
30-
{ ExifTag.XPSubject },
3126
{ ExifTag.GPSVersionID },
3227
};
3328

@@ -295,7 +290,12 @@ public class ExifValuesTests
295290
{ ExifTag.GPSDestLongitudeRef },
296291
{ ExifTag.GPSDestBearingRef },
297292
{ ExifTag.GPSDestDistanceRef },
298-
{ ExifTag.GPSDateStamp }
293+
{ ExifTag.GPSDateStamp },
294+
{ ExifTag.XPTitle },
295+
{ ExifTag.XPComment },
296+
{ ExifTag.XPAuthor },
297+
{ ExifTag.XPKeywords },
298+
{ ExifTag.XPSubject },
299299
};
300300

301301
public static TheoryData<ExifTag> UndefinedTags => new TheoryData<ExifTag>

0 commit comments

Comments
 (0)