diff --git a/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs b/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs
index 32f4d22878..4791a04a0e 100644
--- a/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs
+++ b/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs
@@ -4,6 +4,7 @@
using System;
using System.Buffers.Binary;
using System.IO;
+using System.Linq;
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Common.Helpers;
using SixLabors.ImageSharp.Formats.Jpeg.Components;
@@ -13,6 +14,7 @@ using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.Metadata;
using SixLabors.ImageSharp.Metadata.Profiles.Exif;
using SixLabors.ImageSharp.Metadata.Profiles.Icc;
+using SixLabors.ImageSharp.Metadata.Profiles.Iptc;
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Formats.Jpeg
@@ -647,9 +649,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
/// Writes the EXIF profile.
///
/// The exif profile.
- ///
- /// Thrown if the EXIF profile size exceeds the limit
- ///
private void WriteExifProfile(ExifProfile exifProfile)
{
if (exifProfile is null || exifProfile.Values.Count == 0)
@@ -697,16 +696,56 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
}
}
+ ///
+ /// Writes the IPTC metadata.
+ ///
+ /// The iptc metadata to write.
+ private void WriteIptcProfile(IptcProfile iptcProfile)
+ {
+ if (iptcProfile is null || !iptcProfile.Values.Any())
+ {
+ return;
+ }
+
+ iptcProfile.UpdateData();
+ var data = iptcProfile.Data;
+ if (data.Length == 0)
+ {
+ return;
+ }
+
+ var app13length = data.Length + ProfileResolver.AdobeImageResourceBlockMarker.Length + ProfileResolver.AdobeIptcMarker.Length + 2 + 4;
+ this.WriteAppHeader(app13length, JpegConstants.Markers.APP13);
+ this.outputStream.Write(this.buffer, 0, 4);
+ this.outputStream.Write(ProfileResolver.AdobeImageResourceBlockMarker);
+ this.outputStream.Write(ProfileResolver.AdobeIptcMarker);
+ this.outputStream.WriteByte(0); // a null name consists of two bytes of 0.
+ this.outputStream.WriteByte(0);
+ BinaryPrimitives.WriteInt32BigEndian(this.buffer, data.Length);
+ this.outputStream.Write(this.buffer, 0, 4);
+ this.outputStream.Write(data, 0, data.Length);
+ }
+
///
/// Writes the App1 header.
///
- /// The length of the data the app1 marker contains
+ /// The length of the data the app1 marker contains.
private void WriteApp1Header(int app1Length)
+ {
+ this.WriteAppHeader(app1Length, JpegConstants.Markers.APP1);
+ }
+
+ ///
+ /// Writes a AppX header.
+ ///
+ /// The length of the data the app marker contains.
+ /// The app marker to write.
+ private void WriteAppHeader(int length, byte appMarker)
{
this.buffer[0] = JpegConstants.Markers.XFF;
- this.buffer[1] = JpegConstants.Markers.APP1; // Application Marker
- this.buffer[2] = (byte)((app1Length >> 8) & 0xFF);
- this.buffer[3] = (byte)(app1Length & 0xFF);
+ this.buffer[1] = appMarker;
+ this.buffer[2] = (byte)((length >> 8) & 0xFF);
+ this.buffer[3] = (byte)(length & 0xFF);
this.outputStream.Write(this.buffer, 0, 4);
}
@@ -805,6 +844,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
metadata.SyncProfiles();
this.WriteExifProfile(metadata.ExifProfile);
this.WriteIccProfile(metadata.IccProfile);
+ this.WriteIptcProfile(metadata.IptcProfile);
}
///