Skip to content

Commit aae2c47

Browse files
Reimplement #2869
1 parent 4a8ff2b commit aae2c47

File tree

4 files changed

+60
-5
lines changed

4 files changed

+60
-5
lines changed

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

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using System.Diagnostics;
88
using System.Globalization;
99
using System.Runtime.CompilerServices;
10+
using System.Runtime.InteropServices;
1011
using System.Text;
1112
using SixLabors.ImageSharp.Memory;
1213

@@ -187,11 +188,21 @@ protected void ReadValues(List<IExifValue> values, uint offset)
187188

188189
protected void ReadSubIfd(List<IExifValue> values)
189190
{
190-
if (this.subIfds is not null)
191+
if (this.subIfds != null)
191192
{
192-
foreach (ulong subIfdOffset in this.subIfds)
193+
const int maxSubIfds = 8;
194+
const int maxNestingLevel = 8;
195+
Span<ulong> buf = stackalloc ulong[maxSubIfds];
196+
for (int i = 0; i < maxNestingLevel && this.subIfds.Count > 0; i++)
193197
{
194-
this.ReadValues(values, (uint)subIfdOffset);
198+
int sz = Math.Min(this.subIfds.Count, maxSubIfds);
199+
CollectionsMarshal.AsSpan(this.subIfds)[..sz].CopyTo(buf);
200+
201+
this.subIfds.Clear();
202+
foreach (ulong subIfdOffset in buf[..sz])
203+
{
204+
this.ReadValues(values, (uint)subIfdOffset);
205+
}
195206
}
196207
}
197208
}
@@ -481,8 +492,9 @@ private void Add(IList<IExifValue> values, IExifValue exif, object? value)
481492

482493
foreach (IExifValue val in values)
483494
{
484-
// Sometimes duplicates appear, can compare val.Tag == exif.Tag
485-
if (val == exif)
495+
// to skip duplicates must be used Equals method,
496+
// == operator not defined for ExifValue and IExifValue
497+
if (exif.Equals(val))
486498
{
487499
Debug.WriteLine($"Duplicate Exif tag: tag={exif.Tag}, dataType={exif.DataType}");
488500
return;

tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Metadata.cs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,45 @@ public void Issue2758_DecodeWorks<TPixel>(TestImageProvider<TPixel> provider)
452452
image.Save(ms, new JpegEncoder());
453453
}
454454

455+
// https://github.com/SixLabors/ImageSharp/issues/2857
456+
[Theory]
457+
[WithFile(TestImages.Jpeg.Issues.Issue2857, PixelTypes.Rgb24)]
458+
public void Issue2857_SubSubIfds<TPixel>(TestImageProvider<TPixel> provider)
459+
where TPixel : unmanaged, IPixel<TPixel>
460+
{
461+
using Image<TPixel> image = provider.GetImage(JpegDecoder.Instance);
462+
463+
Assert.Equal(5616, image.Width);
464+
Assert.Equal(3744, image.Height);
465+
466+
JpegMetadata meta = image.Metadata.GetJpegMetadata();
467+
Assert.Equal(92, meta.LuminanceQuality);
468+
Assert.Equal(93, meta.ChrominanceQuality);
469+
470+
ExifProfile exifProfile = image.Metadata.ExifProfile;
471+
Assert.NotNull(exifProfile);
472+
473+
using MemoryStream ms = new();
474+
bool hasThumbnail = exifProfile.TryCreateThumbnail(out _);
475+
Assert.False(hasThumbnail);
476+
477+
Assert.Equal("BilderBox - Erwin Wodicka / [email protected]", exifProfile.GetValue(ExifTag.Copyright).Value);
478+
Assert.Equal("Adobe Photoshop CS3 Windows", exifProfile.GetValue(ExifTag.Software).Value);
479+
480+
Assert.Equal("Carers; seniors; caregiver; senior care; retirement home; hands; old; elderly; elderly caregiver; elder care; elderly care; geriatric care; nursing home; age; old age care; outpatient; needy; health care; home nurse; home care; sick; retirement; medical; mobile; the elderly; nursing department; nursing treatment; nursing; care services; nursing services; nursing care; nursing allowance; nursing homes; home nursing; care category; nursing class; care; nursing shortage; nursing patient care staff\0", exifProfile.GetValue(ExifTag.XPKeywords).Value);
481+
482+
Assert.Equal(
483+
new EncodedString(EncodedString.CharacterCode.ASCII, "StockSubmitter|Miscellaneous||Miscellaneous$|00|0000330000000110000000000000000|22$@NA_1005010.460@[email protected]$$@$@26$$@$@$@$@205$@$@$@$@$@$@$@$@$@43$@$@$@[email protected]$$@90$$@22$@$@$@$@$@$@$|||"),
484+
exifProfile.GetValue(ExifTag.UserComment).Value);
485+
486+
// the profile contains 4 duplicated UserComment
487+
Assert.Equal(1, exifProfile.Values.Count(t => t.Tag == ExifTag.UserComment));
488+
489+
image.Mutate(x => x.Crop(new(0, 0, 100, 100)));
490+
491+
image.Save(ms, new JpegEncoder());
492+
}
493+
455494
private static void VerifyEncodedStrings(ExifProfile exif)
456495
{
457496
Assert.NotNull(exif);

tests/ImageSharp.Tests/TestImages.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,7 @@ public static class Issues
325325
public const string Issue2517 = "Jpg/issues/issue2517-bad-d7.jpg";
326326
public const string Issue2638 = "Jpg/issues/Issue2638.jpg";
327327
public const string Issue2758 = "Jpg/issues/issue-2758.jpg";
328+
public const string Issue2857 = "Jpg/issues/issue-2857-subsub-ifds.jpg";
328329

329330
public static class Fuzz
330331
{
Lines changed: 3 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)