diff --git a/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs b/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs
index 4560af05a..a143723e1 100644
--- a/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs
+++ b/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs
@@ -213,6 +213,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
// Write the Start Of Image marker.
this.WriteApplicationHeader((short)image.MetaData.HorizontalResolution, (short)image.MetaData.VerticalResolution);
+ // Write Exif and ICC profiles
this.WriteProfiles(image);
// Write the quantization tables.
@@ -608,27 +609,57 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
///
private void WriteExifProfile(ExifProfile exifProfile)
{
- const int Max = 65533;
+ const int MaxBytesApp1 = 65533;
+ const int MaxBytesWithExifId = 65527;
byte[] data = exifProfile?.ToByteArray(ProfileResolver.ExifMarker);
if (data == null || data.Length == 0)
{
return;
}
- if (data.Length > Max)
+ int remaining = data.Length;
+ int bytesToWrite = remaining > MaxBytesApp1 ? MaxBytesApp1 : remaining;
+ int app1Length = bytesToWrite + 2;
+
+ // write the app1 header
+ this.WriteApp1Header(app1Length);
+
+ // write the exif data
+ this.outputStream.Write(data, 0, bytesToWrite);
+ remaining -= bytesToWrite;
+
+ // if the exif data exceeds 64K, write it in multiple APP1 Markers
+ for (int idx = MaxBytesApp1; idx < data.Length; idx += MaxBytesWithExifId)
{
- throw new ImageFormatException($"Exif profile size exceeds limit of {Max} bytes.");
- }
+ bytesToWrite = remaining > MaxBytesWithExifId ? MaxBytesWithExifId : remaining;
+ app1Length = bytesToWrite + 2 + 6;
+
+ // write the app1 header
+ this.WriteApp1Header(app1Length);
+
+ // write Exif00 marker
+ ProfileResolver.ExifMarker.AsSpan().CopyTo(this.buffer.AsSpan());
+ this.outputStream.Write(this.buffer, 0, 6);
- int length = data.Length + 2;
+ // write the exif data
+ this.outputStream.Write(data, idx, bytesToWrite);
+ remaining -= bytesToWrite;
+ }
+ }
+
+ ///
+ /// Writes the App1 header.
+ ///
+ /// The length of the data the app1 marker contains
+ private void WriteApp1Header(int app1Length)
+ {
this.buffer[0] = JpegConstants.Markers.XFF;
this.buffer[1] = JpegConstants.Markers.APP1; // Application Marker
- this.buffer[2] = (byte)((length >> 8) & 0xFF);
- this.buffer[3] = (byte)(length & 0xFF);
+ this.buffer[2] = (byte)((app1Length >> 8) & 0xFF);
+ this.buffer[3] = (byte)(app1Length & 0xFF);
this.outputStream.Write(this.buffer, 0, 4);
- this.outputStream.Write(data, 0, data.Length);
}
///