Skip to content

Commit 564c3d1

Browse files
Fix encoding
1 parent aada974 commit 564c3d1

File tree

3 files changed

+22
-6
lines changed

3 files changed

+22
-6
lines changed

src/ImageSharp/Formats/Png/PngEncoderCore.cs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ public void Encode<TPixel>(Image<TPixel> image, Stream stream, CancellationToken
189189
ReadOnlyMemory<TPixel>? previousPalette = quantized?.Palette.ToArray();
190190

191191
// Write following frames.
192+
uint increment = 0;
192193
for (int i = 1; i < image.Frames.Count; i++)
193194
{
194195
currentFrame = image.Frames[i];
@@ -200,12 +201,14 @@ public void Encode<TPixel>(Image<TPixel> image, Stream stream, CancellationToken
200201
ClearTransparentPixels(currentFrame);
201202
}
202203

203-
frameControl = this.WriteFrameControlChunk(stream, currentFrame, (uint)i);
204+
// Each frame control sequence number must be incremented by the
205+
// number of frame data chunks that follow.
206+
frameControl = this.WriteFrameControlChunk(stream, currentFrame, (uint)i + increment);
204207

205208
// Dispose of previous quantized frame and reassign.
206209
quantized?.Dispose();
207210
quantized = this.CreateQuantizedImageAndUpdateBitDepth(pngMetadata, currentFrame, previousPalette);
208-
this.WriteDataChunks(frameControl, currentFrame, quantized, stream, true);
211+
increment += this.WriteDataChunks(frameControl, currentFrame, quantized, stream, true);
209212
}
210213
}
211214
else
@@ -1013,7 +1016,7 @@ private FrameControl WriteFrameControlChunk(Stream stream, ImageFrame imageFrame
10131016
/// <param name="quantized">The quantized pixel data. Can be null.</param>
10141017
/// <param name="stream">The stream.</param>
10151018
/// <param name="isFrame">Is writing fdAT or IDAT.</param>
1016-
private int WriteDataChunks<TPixel>(FrameControl frameControl, ImageFrame<TPixel> pixels, IndexedImageFrame<TPixel>? quantized, Stream stream, bool isFrame)
1019+
private uint WriteDataChunks<TPixel>(FrameControl frameControl, ImageFrame<TPixel> pixels, IndexedImageFrame<TPixel>? quantized, Stream stream, bool isFrame)
10171020
where TPixel : unmanaged, IPixel<TPixel>
10181021
{
10191022
byte[] buffer;
@@ -1070,7 +1073,9 @@ private int WriteDataChunks<TPixel>(FrameControl frameControl, ImageFrame<TPixel
10701073

10711074
if (isFrame)
10721075
{
1073-
uint sequenceNumber = (uint)(frameControl.SequenceNumber + i);
1076+
// We increment the sequence number for each frame chunk.
1077+
// '1' is added to the sequence number to account for the preceding frame control chunk.
1078+
uint sequenceNumber = (uint)(frameControl.SequenceNumber + 1 + i);
10741079
this.WriteFrameDataChunk(stream, sequenceNumber, buffer, i * maxBlockSize, length);
10751080
}
10761081
else
@@ -1079,7 +1084,7 @@ private int WriteDataChunks<TPixel>(FrameControl frameControl, ImageFrame<TPixel
10791084
}
10801085
}
10811086

1082-
return numChunks;
1087+
return (uint)numChunks;
10831088
}
10841089

10851090
/// <summary>

tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,12 @@ public void Decode<TPixel>(TestImageProvider<TPixel> provider)
111111
public void Decode_APng<TPixel>(TestImageProvider<TPixel> provider)
112112
where TPixel : unmanaged, IPixel<TPixel>
113113
{
114-
using Image<TPixel> image = provider.GetImage(PngDecoder.Instance); // MagickReferenceDecoder cannot decode APNGs
114+
using Image<TPixel> image = provider.GetImage(PngDecoder.Instance);
115+
116+
Assert.Equal(5, image.Frames.Count);
117+
118+
// TODO: Assertations.
119+
// MagickReferenceDecoder cannot decode APNGs (Though ImageMagick can, we likely need to update our mapping implementation)
115120
}
116121

117122
[Theory]

tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -451,8 +451,14 @@ public void Encode_APng<TPixel>(TestImageProvider<TPixel> provider)
451451
using MemoryStream memStream = new();
452452
image.Save(memStream, PngEncoder);
453453
memStream.Position = 0;
454+
455+
image.DebugSave(provider: provider, encoder: PngEncoder, null, false);
456+
454457
using Image<Rgba32> output = Image.Load<Rgba32>(memStream);
455458
ImageComparer.Exact.VerifySimilarity(output, image);
459+
460+
// TODO: Additional assertations regarding metadata.
461+
Assert.Equal(5, image.Frames.Count);
456462
}
457463

458464
[Theory]

0 commit comments

Comments
 (0)