Skip to content

Commit ce069bc

Browse files
committed
Fix frame dispose operation handling
1 parent a58ef4b commit ce069bc

File tree

6 files changed

+25
-20
lines changed

6 files changed

+25
-20
lines changed

src/ImageSharp/Formats/Png/PngDecoderCore.cs

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -246,8 +246,13 @@ public Image<TPixel> Decode<TPixel>(BufferedReadStream stream, CancellationToken
246246
currentFrameControl.Value,
247247
cancellationToken);
248248

249-
previousFrame = currentFrame;
250-
previousFrameControl = currentFrameControl;
249+
// if current frame dispose is restore to previous, then from future frame's perspective, it never happened
250+
if (currentFrameControl.Value.DisposeOperation != PngDisposalMethod.RestoreToPrevious)
251+
{
252+
previousFrame = currentFrame;
253+
previousFrameControl = currentFrameControl;
254+
}
255+
251256
break;
252257
case PngChunkType.Data:
253258

@@ -645,18 +650,18 @@ private void InitializeFrame<TPixel>(
645650
out ImageFrame<TPixel> frame)
646651
where TPixel : unmanaged, IPixel<TPixel>
647652
{
648-
// We create a clone of the previous frame and add it.
649-
// We will overpaint the difference of pixels on the current frame to create a complete image.
650-
// This ensures that we have enough pixel data to process without distortion. #2450
651653
frame = image.Frames.AddFrame(previousFrame ?? image.Frames.RootFrame);
652654

653-
// If the first `fcTL` chunk uses a `dispose_op` of APNG_DISPOSE_OP_PREVIOUS it should be treated as APNG_DISPOSE_OP_BACKGROUND.
654-
if (previousFrameControl.DisposeOperation == PngDisposalMethod.RestoreToBackground
655-
|| (previousFrame is null && previousFrameControl.DisposeOperation == PngDisposalMethod.RestoreToPrevious))
655+
// if restoring to before first frame, restore to background
656+
if (previousFrame is null && previousFrameControl.DisposeOperation == PngDisposalMethod.RestoreToPrevious)
657+
{
658+
Buffer2DRegion<TPixel> pixelRegion = frame.PixelBuffer.GetRegion();
659+
pixelRegion.Clear();
660+
}
661+
else if (previousFrameControl.DisposeOperation == PngDisposalMethod.RestoreToBackground)
656662
{
657663
Rectangle restoreArea = previousFrameControl.Bounds;
658-
Rectangle interest = Rectangle.Intersect(frame.Bounds(), restoreArea);
659-
Buffer2DRegion<TPixel> pixelRegion = frame.PixelBuffer.GetRegion(interest);
664+
Buffer2DRegion<TPixel> pixelRegion = frame.PixelBuffer.GetRegion(restoreArea);
660665
pixelRegion.Clear();
661666
}
662667

Lines changed: 2 additions & 2 deletions
Loading
Lines changed: 2 additions & 2 deletions
Loading
Lines changed: 2 additions & 2 deletions
Loading
Lines changed: 2 additions & 2 deletions
Loading
Lines changed: 2 additions & 2 deletions
Loading

0 commit comments

Comments
 (0)