Skip to content

Commit 9260be9

Browse files
committed
Add com character limit, comment as IList, remove unnecessary extension methods
1 parent 5127202 commit 9260be9

File tree

5 files changed

+34
-60
lines changed

5 files changed

+34
-60
lines changed

src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -177,39 +177,46 @@ private void WriteJfifApplicationHeader(ImageMetadata meta, Span<byte> buffer)
177177
/// <param name="metadata">The image metadata.</param>
178178
private void WriteComment(JpegMetadata metadata)
179179
{
180-
if (metadata.Comments is { Count: 0 })
180+
int maxCommentLength = 65533;
181+
182+
if (metadata.Comments.Count == 0)
181183
{
182184
return;
183185
}
184186

185-
// Length (comment strings lengths) + (comments markers with payload sizes)
186-
int commentsBytes = metadata.Comments.Sum(x => x.Length) + (metadata.Comments.Count * 4);
187-
int commentStart = 0;
188-
Span<byte> commentBuffer = new byte[commentsBytes];
189-
190-
foreach (Memory<char> comment in metadata.Comments)
187+
for (int i = 0; i < metadata.Comments.Count; i++)
191188
{
192-
int totalComLength = comment.Length + 4;
189+
Memory<char> chars = metadata.Comments[i];
190+
191+
if (chars.Length > maxCommentLength)
192+
{
193+
Memory<char> splitComment = chars.Slice(maxCommentLength, chars.Length - maxCommentLength);
194+
metadata.Comments.Insert(i + 1, splitComment);
193195

194-
Span<byte> commentData = commentBuffer.Slice(commentStart, totalComLength);
195-
Span<byte> markers = commentData.Slice(0, 2);
196-
Span<byte> payloadSize = commentData.Slice(2, 2);
197-
Span<byte> payload = commentData.Slice(4, comment.Length);
196+
// We don't want to keep the extra bytes
197+
chars = chars.Slice(0, maxCommentLength);
198+
}
199+
200+
int commentLength = chars.Length + 4;
201+
202+
Span<byte> comment = new byte[commentLength];
203+
Span<byte> markers = comment.Slice(0, 2);
204+
Span<byte> payloadSize = comment.Slice(2, 2);
205+
Span<byte> payload = comment.Slice(4, chars.Length);
198206

199207
// Beginning of comment ff fe
200208
markers[0] = JpegConstants.Markers.XFF;
201209
markers[1] = JpegConstants.Markers.COM;
202210

203211
// Write payload size
204-
BinaryPrimitives.WriteInt16BigEndian(payloadSize, (short)(commentData.Length - 2));
212+
int comWithoutMarker = commentLength - 2;
213+
payloadSize[0] = (byte)((comWithoutMarker >> 8) & 0xFF);
214+
payloadSize[1] = (byte)(comWithoutMarker & 0xFF);
205215

206-
Encoding.ASCII.GetBytes(comment.Span, payload);
216+
Encoding.ASCII.GetBytes(chars.Span, payload);
207217

208-
// Indicate begin of next comment in buffer
209-
commentStart += totalComLength;
218+
this.outputStream.Write(comment, 0, comment.Length);
210219
}
211-
212-
this.outputStream.Write(commentBuffer, 0, commentBuffer.Length);
213220
}
214221

215222
/// <summary>

src/ImageSharp/Formats/Jpeg/JpegMetadata.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ public int Quality
106106
/// <summary>
107107
/// Gets the comments.
108108
/// </summary>
109-
public ICollection<Memory<char>>? Comments { get; }
109+
public IList<Memory<char>> Comments { get; }
110110

111111
/// <inheritdoc/>
112112
public IDeepCloneable DeepClone() => new JpegMetadata(this);

src/ImageSharp/Formats/Jpeg/MetadataExtensions.cs

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -18,37 +18,4 @@ public static partial class MetadataExtensions
1818
/// <param name="metadata">The metadata this method extends.</param>
1919
/// <returns>The <see cref="JpegMetadata"/>.</returns>
2020
public static JpegMetadata GetJpegMetadata(this ImageMetadata metadata) => metadata.GetFormatMetadata(JpegFormat.Instance);
21-
22-
/// <summary>
23-
/// Sets the comment in <see cref="JpegMetadata"/>
24-
/// </summary>
25-
/// <param name="metadata">The metadata this method extends.</param>
26-
/// <param name="index">The index of comment to be inserted to.</param>
27-
/// <param name="comment">The comment string.</param>
28-
public static void SetComment(this JpegMetadata metadata, int index, string comment)
29-
{
30-
if (metadata.Comments == null)
31-
{
32-
return;
33-
}
34-
35-
ASCIIEncoding encoding = new();
36-
byte[] bytes = encoding.GetBytes(comment);
37-
List<Memory<char>>? comments = metadata.Comments as List<Memory<char>>;
38-
comments?.Insert(index, encoding.GetChars(bytes));
39-
}
40-
41-
/// <summary>
42-
/// Gets the comments from <see cref="JpegMetadata"/>
43-
/// </summary>
44-
/// <param name="metadata">The metadata this method extends.</param>
45-
/// <param name="index">The index of comment.</param>
46-
/// <returns>The IEnumerable string of comments.</returns>
47-
public static string? GetComment(this JpegMetadata metadata, int index) => metadata.Comments?.ElementAtOrDefault(index).ToString();
48-
49-
/// <summary>
50-
/// Clears comments
51-
/// </summary>
52-
/// <param name="metadata">The <see cref="JpegMetadata"/>.</param>
53-
public static void ClearComments(this JpegMetadata metadata) => metadata.Comments?.Clear();
5421
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -434,8 +434,8 @@ public void JpegDecoder_DecodeMetadataComment<TPixel>(TestImageProvider<TPixel>
434434
using Image<TPixel> image = provider.GetImage(JpegDecoder.Instance);
435435
JpegMetadata metadata = image.Metadata.GetJpegMetadata();
436436

437-
Assert.Equal(1, metadata.Comments?.Count);
438-
Assert.Equal(expectedComment, metadata.GetComment(0));
437+
Assert.Equal(1, metadata.Comments.Count);
438+
Assert.Equal(expectedComment.ToCharArray(), metadata.Comments.ElementAtOrDefault(0));
439439
image.DebugSave(provider);
440440
image.CompareToOriginal(provider);
441441
}

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ public void Encode_PreservesComments<TPixel>(TestImageProvider<TPixel> provider)
172172
JpegMetadata actual = output.Metadata.GetJpegMetadata();
173173
Assert.NotEmpty(actual.Comments);
174174
Assert.Equal(1, actual.Comments.Count);
175-
Assert.Equal("TEST COMMENT", actual.Comments.ElementAt(0).ToString());
175+
Assert.Equal("TEST COMMENT", actual.Comments.ElementAtOrDefault(0).ToString());
176176
}
177177

178178
[Fact]
@@ -184,18 +184,18 @@ public void Encode_SavesMultipleComments()
184184
using var memStream = new MemoryStream();
185185

186186
// act
187-
meta.SetComment(0, "First comment");
188-
meta.SetComment(1, "Second Comment");
187+
meta.Comments.Add("First comment".ToCharArray());
188+
meta.Comments.Add("Second Comment".ToCharArray());
189189
input.Save(memStream, JpegEncoder);
190190

191191
// assert
192192
memStream.Position = 0;
193193
using Image<Rgba32> output = Image.Load<Rgba32>(memStream);
194194
JpegMetadata actual = output.Metadata.GetJpegMetadata();
195195
Assert.NotEmpty(actual.Comments);
196-
Assert.Equal(2, actual.Comments?.Count);
197-
Assert.Equal(meta.Comments?.ElementAt(0).ToString(), actual.Comments?.ElementAt(0).ToString());
198-
Assert.Equal(meta.Comments?.ElementAt(1).ToString(), actual.Comments?.ElementAt(1).ToString());
196+
Assert.Equal(2, actual.Comments.Count);
197+
Assert.Equal(meta.Comments.ElementAtOrDefault(0).ToString(), actual.Comments.ElementAtOrDefault(0).ToString());
198+
Assert.Equal(meta.Comments.ElementAtOrDefault(1).ToString(), actual.Comments.ElementAtOrDefault(1).ToString());
199199
}
200200

201201
[Theory]

0 commit comments

Comments
 (0)