diff --git a/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs b/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs
index 1b2b4cbb1..4dc920207 100644
--- a/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs
+++ b/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs
@@ -177,39 +177,46 @@ internal sealed unsafe partial class JpegEncoderCore : IImageEncoderInternals
/// The image metadata.
private void WriteComment(JpegMetadata metadata)
{
- if (metadata.Comments is { Count: 0 })
+ int maxCommentLength = 65533;
+
+ if (metadata.Comments.Count == 0)
{
return;
}
- // Length (comment strings lengths) + (comments markers with payload sizes)
- int commentsBytes = metadata.Comments.Sum(x => x.Length) + (metadata.Comments.Count * 4);
- int commentStart = 0;
- Span commentBuffer = new byte[commentsBytes];
-
- foreach (Memory comment in metadata.Comments)
+ for (int i = 0; i < metadata.Comments.Count; i++)
{
- int totalComLength = comment.Length + 4;
+ Memory chars = metadata.Comments[i];
+
+ if (chars.Length > maxCommentLength)
+ {
+ Memory splitComment = chars.Slice(maxCommentLength, chars.Length - maxCommentLength);
+ metadata.Comments.Insert(i + 1, splitComment);
- Span commentData = commentBuffer.Slice(commentStart, totalComLength);
- Span markers = commentData.Slice(0, 2);
- Span payloadSize = commentData.Slice(2, 2);
- Span payload = commentData.Slice(4, comment.Length);
+ // We don't want to keep the extra bytes
+ chars = chars.Slice(0, maxCommentLength);
+ }
+
+ int commentLength = chars.Length + 4;
+
+ Span comment = new byte[commentLength];
+ Span markers = comment.Slice(0, 2);
+ Span payloadSize = comment.Slice(2, 2);
+ Span payload = comment.Slice(4, chars.Length);
// Beginning of comment ff fe
markers[0] = JpegConstants.Markers.XFF;
markers[1] = JpegConstants.Markers.COM;
// Write payload size
- BinaryPrimitives.WriteInt16BigEndian(payloadSize, (short)(commentData.Length - 2));
+ int comWithoutMarker = commentLength - 2;
+ payloadSize[0] = (byte)((comWithoutMarker >> 8) & 0xFF);
+ payloadSize[1] = (byte)(comWithoutMarker & 0xFF);
- Encoding.ASCII.GetBytes(comment.Span, payload);
+ Encoding.ASCII.GetBytes(chars.Span, payload);
- // Indicate begin of next comment in buffer
- commentStart += totalComLength;
+ this.outputStream.Write(comment, 0, comment.Length);
}
-
- this.outputStream.Write(commentBuffer, 0, commentBuffer.Length);
}
///
diff --git a/src/ImageSharp/Formats/Jpeg/JpegMetadata.cs b/src/ImageSharp/Formats/Jpeg/JpegMetadata.cs
index 61fe3b214..bf758dfd0 100644
--- a/src/ImageSharp/Formats/Jpeg/JpegMetadata.cs
+++ b/src/ImageSharp/Formats/Jpeg/JpegMetadata.cs
@@ -106,7 +106,7 @@ public class JpegMetadata : IDeepCloneable
///
/// Gets the comments.
///
- public ICollection>? Comments { get; }
+ public IList> Comments { get; }
///
public IDeepCloneable DeepClone() => new JpegMetadata(this);
diff --git a/src/ImageSharp/Formats/Jpeg/MetadataExtensions.cs b/src/ImageSharp/Formats/Jpeg/MetadataExtensions.cs
index 0c66fcbdd..7330e74b7 100644
--- a/src/ImageSharp/Formats/Jpeg/MetadataExtensions.cs
+++ b/src/ImageSharp/Formats/Jpeg/MetadataExtensions.cs
@@ -18,37 +18,4 @@ public static partial class MetadataExtensions
/// The metadata this method extends.
/// The .
public static JpegMetadata GetJpegMetadata(this ImageMetadata metadata) => metadata.GetFormatMetadata(JpegFormat.Instance);
-
- ///
- /// Sets the comment in
- ///
- /// The metadata this method extends.
- /// The index of comment to be inserted to.
- /// The comment string.
- public static void SetComment(this JpegMetadata metadata, int index, string comment)
- {
- if (metadata.Comments == null)
- {
- return;
- }
-
- ASCIIEncoding encoding = new();
- byte[] bytes = encoding.GetBytes(comment);
- List>? comments = metadata.Comments as List>;
- comments?.Insert(index, encoding.GetChars(bytes));
- }
-
- ///
- /// Gets the comments from
- ///
- /// The metadata this method extends.
- /// The index of comment.
- /// The IEnumerable string of comments.
- public static string? GetComment(this JpegMetadata metadata, int index) => metadata.Comments?.ElementAtOrDefault(index).ToString();
-
- ///
- /// Clears comments
- ///
- /// The .
- public static void ClearComments(this JpegMetadata metadata) => metadata.Comments?.Clear();
}
diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Metadata.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Metadata.cs
index fb37a956d..369e71abf 100644
--- a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Metadata.cs
+++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Metadata.cs
@@ -434,8 +434,8 @@ public partial class JpegDecoderTests
using Image image = provider.GetImage(JpegDecoder.Instance);
JpegMetadata metadata = image.Metadata.GetJpegMetadata();
- Assert.Equal(1, metadata.Comments?.Count);
- Assert.Equal(expectedComment, metadata.GetComment(0));
+ Assert.Equal(1, metadata.Comments.Count);
+ Assert.Equal(expectedComment.ToCharArray(), metadata.Comments.ElementAtOrDefault(0));
image.DebugSave(provider);
image.CompareToOriginal(provider);
}
diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.Metadata.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.Metadata.cs
index bd68eaf20..8cc64acea 100644
--- a/tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.Metadata.cs
+++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.Metadata.cs
@@ -172,7 +172,7 @@ public partial class JpegEncoderTests
JpegMetadata actual = output.Metadata.GetJpegMetadata();
Assert.NotEmpty(actual.Comments);
Assert.Equal(1, actual.Comments.Count);
- Assert.Equal("TEST COMMENT", actual.Comments.ElementAt(0).ToString());
+ Assert.Equal("TEST COMMENT", actual.Comments.ElementAtOrDefault(0).ToString());
}
[Fact]
@@ -184,8 +184,8 @@ public partial class JpegEncoderTests
using var memStream = new MemoryStream();
// act
- meta.SetComment(0, "First comment");
- meta.SetComment(1, "Second Comment");
+ meta.Comments.Add("First comment".ToCharArray());
+ meta.Comments.Add("Second Comment".ToCharArray());
input.Save(memStream, JpegEncoder);
// assert
@@ -193,9 +193,9 @@ public partial class JpegEncoderTests
using Image output = Image.Load(memStream);
JpegMetadata actual = output.Metadata.GetJpegMetadata();
Assert.NotEmpty(actual.Comments);
- Assert.Equal(2, actual.Comments?.Count);
- Assert.Equal(meta.Comments?.ElementAt(0).ToString(), actual.Comments?.ElementAt(0).ToString());
- Assert.Equal(meta.Comments?.ElementAt(1).ToString(), actual.Comments?.ElementAt(1).ToString());
+ Assert.Equal(2, actual.Comments.Count);
+ Assert.Equal(meta.Comments.ElementAtOrDefault(0).ToString(), actual.Comments.ElementAtOrDefault(0).ToString());
+ Assert.Equal(meta.Comments.ElementAtOrDefault(1).ToString(), actual.Comments.ElementAtOrDefault(1).ToString());
}
[Theory]