Skip to content

Commit 8af9a80

Browse files
committed
PR comments changes
1 parent 6542476 commit 8af9a80

File tree

3 files changed

+65
-22
lines changed

3 files changed

+65
-22
lines changed

src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -523,13 +523,16 @@ public void Dispose()
523523
/// <param name="markerContentByteSize">The remaining bytes in the segment block.</param>
524524
private void ProcessComMarker(BufferedReadStream stream, int markerContentByteSize)
525525
{
526-
Span<byte> temp = new byte[markerContentByteSize];
526+
char[] temp = new char[markerContentByteSize];
527527
JpegMetadata metadata = this.Metadata.GetFormatMetadata(JpegFormat.Instance);
528528

529-
stream.Read(temp);
530-
string comment = Encoding.ASCII.GetString(temp);
529+
for (int i = 0; i < markerContentByteSize; i++)
530+
{
531+
int read = stream.ReadByte();
532+
temp[i] = (char)read;
533+
}
531534

532-
metadata.Comments.Add(JpegComData.FromString(comment));
535+
metadata.Comments.Add(new JpegComData(temp));
533536
}
534537

535538
/// <summary>

src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#nullable disable
44

55
using System.Buffers.Binary;
6+
using System.Collections;
67
using System.Text;
78
using SixLabors.ImageSharp.Common.Helpers;
89
using SixLabors.ImageSharp.Formats.Jpeg.Components;
@@ -184,39 +185,55 @@ private void WriteComment(JpegMetadata metadata)
184185
return;
185186
}
186187

187-
for (int i = 0; i < metadata.Comments.Count; i++)
188+
// We don't want to modify original metadata
189+
List<JpegComData> comments = new(metadata.Comments);
190+
191+
int totalPayloadLength = 0;
192+
for (int i = 0; i < comments.Count; i++)
188193
{
189-
string comment = metadata.Comments[i].ToString();
194+
JpegComData comment = comments[i];
195+
ReadOnlyMemory<char> currentComment = comment.Value;
190196

191-
if (comment.Length > maxCommentLength)
197+
if (comment.Value.Length > maxCommentLength)
192198
{
193-
string splitComment = comment.Substring(maxCommentLength, comment.Length - maxCommentLength);
194-
metadata.Comments.Insert(i + 1, JpegComData.FromString(splitComment));
199+
ReadOnlyMemory<char> splitComment =
200+
currentComment.Slice(maxCommentLength, currentComment.Length - maxCommentLength);
201+
comments.Insert(i + 1, new JpegComData(splitComment));
195202

196203
// We don't want to keep the extra bytes
197-
comment = comment.Substring(0, maxCommentLength);
204+
comments[i] = new JpegComData(currentComment.Slice(0, maxCommentLength));
198205
}
199206

200-
int commentLength = comment.Length + 4;
207+
totalPayloadLength += comment.Value.Length + 4;
208+
}
209+
210+
Span<byte> payload = new byte[totalPayloadLength];
211+
int currentCommentStartingIndex = 0;
201212

202-
Span<byte> commentSpan = new byte[commentLength];
203-
Span<byte> markers = commentSpan.Slice(0, 2);
204-
Span<byte> payloadSize = commentSpan.Slice(2, 2);
205-
Span<byte> payload = commentSpan.Slice(4, comment.Length);
213+
for (int i = 0; i < comments.Count; i++)
214+
{
215+
ReadOnlyMemory<char> comment = comments[i].Value;
206216

207217
// Beginning of comment ff fe
208-
markers[0] = JpegConstants.Markers.XFF;
209-
markers[1] = JpegConstants.Markers.COM;
218+
payload[currentCommentStartingIndex] = JpegConstants.Markers.XFF;
219+
payload[currentCommentStartingIndex + 1] = JpegConstants.Markers.COM;
210220

211221
// Write payload size
212-
int comWithoutMarker = commentLength - 2;
213-
payloadSize[0] = (byte)((comWithoutMarker >> 8) & 0xFF);
214-
payloadSize[1] = (byte)(comWithoutMarker & 0xFF);
222+
int comWithoutMarker = comment.Length + 2;
223+
payload[currentCommentStartingIndex + 2] = (byte)((comWithoutMarker >> 8) & 0xFF);
224+
payload[currentCommentStartingIndex + 3] = (byte)(comWithoutMarker & 0xFF);
215225

216-
Encoding.ASCII.GetBytes(comment, payload);
226+
char[] commentChars = comment.ToArray();
227+
for (int j = 0; j < commentChars.Length; j++)
228+
{
229+
// Initial 4 bytes are always reserved
230+
payload[4 + currentCommentStartingIndex + j] = (byte)commentChars[j];
231+
}
217232

218-
this.outputStream.Write(commentSpan, 0, commentSpan.Length);
233+
currentCommentStartingIndex += comment.Length + 4;
219234
}
235+
236+
this.outputStream.Write(payload, 0, payload.Length);
220237
}
221238

222239
/// <summary>

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

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,29 @@ public void Encode_SavesMultipleComments()
198198
Assert.Equal(meta.Comments.ElementAtOrDefault(1).ToString(), actual.Comments.ElementAtOrDefault(1).ToString());
199199
}
200200

201+
[Fact]
202+
public void Encode_SaveTooLongComment()
203+
{
204+
// arrange
205+
string longString = new('c', 65534);
206+
using var input = new Image<Rgba32>(1, 1);
207+
JpegMetadata meta = input.Metadata.GetJpegMetadata();
208+
using var memStream = new MemoryStream();
209+
210+
// act
211+
meta.Comments.Add(JpegComData.FromString(longString));
212+
input.Save(memStream, JpegEncoder);
213+
214+
// assert
215+
memStream.Position = 0;
216+
using Image<Rgba32> output = Image.Load<Rgba32>(memStream);
217+
JpegMetadata actual = output.Metadata.GetJpegMetadata();
218+
Assert.NotEmpty(actual.Comments);
219+
Assert.Equal(2, actual.Comments.Count);
220+
Assert.Equal(longString[..65533], actual.Comments.ElementAtOrDefault(0).ToString());
221+
Assert.Equal("c", actual.Comments.ElementAtOrDefault(1).ToString());
222+
}
223+
201224
[Theory]
202225
[WithFile(TestImages.Jpeg.Baseline.Floorplan, PixelTypes.Rgb24, JpegEncodingColor.Luminance)]
203226
[WithFile(TestImages.Jpeg.Baseline.Jpeg444, PixelTypes.Rgb24, JpegEncodingColor.YCbCrRatio444)]

0 commit comments

Comments
 (0)