diff --git a/src/ImageSharp/Metadata/Profiles/Exif/ExifWriter.cs b/src/ImageSharp/Metadata/Profiles/Exif/ExifWriter.cs index 732e3eab2..659df01a6 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/ExifWriter.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/ExifWriter.cs @@ -403,6 +403,13 @@ internal sealed class ExifWriter return WriteUInt32((uint)longNumber, destination, offset); } + // ExifLong8Array retains ulong storage but reports Long when every value fits + // in 32 bits, allowing BigTIFF offsets to be serialized by classic EXIF writers. + if (value is ulong long8Value) + { + return WriteUInt32((uint)long8Value, destination, offset); + } + return WriteUInt32((uint)value, destination, offset); case ExifDataType.Long8: return WriteUInt64((ulong)value, destination, offset); diff --git a/tests/ImageSharp.Tests/Formats/Tiff/BigTiffMetadataTests.cs b/tests/ImageSharp.Tests/Formats/Tiff/BigTiffMetadataTests.cs index d19f27807..6aebf7b9c 100644 --- a/tests/ImageSharp.Tests/Formats/Tiff/BigTiffMetadataTests.cs +++ b/tests/ImageSharp.Tests/Formats/Tiff/BigTiffMetadataTests.cs @@ -88,6 +88,21 @@ public class BigTiffMetadataTests Assert.Equal(ExifDataType.Long8, long8.DataType); } + [Fact] + public void ExifLong8Array_CanWriteValuesAsLong() + { + ExifLong8Array long8 = new(ExifTagValue.StripOffsets); + Assert.True(long8.TrySetValue(new long[] { 1, uint.MaxValue })); + Assert.Equal(ExifDataType.Long, long8.DataType); + + byte[] buffer = new byte[8]; + int written = ExifWriter.WriteValue(long8, buffer, 0); + + Assert.Equal(buffer.Length, written); + Assert.Equal(1U, BinaryPrimitives.ReadUInt32LittleEndian(buffer)); + Assert.Equal(uint.MaxValue, BinaryPrimitives.ReadUInt32LittleEndian(buffer.AsSpan(4))); + } + [Fact] public void ExifSignedLong8Array() {