@@ -210,7 +210,7 @@ public Image<TPixel> Decode<TPixel>(BufferedReadStream stream, CancellationToken
210210
211211 if ( currentFrame is null )
212212 {
213- this . InitializeFrame ( previousFrameControl . Value , image , out currentFrame ) ;
213+ this . InitializeFrame ( previousFrameControl . Value , image , previousFrame , out currentFrame ) ;
214214 }
215215
216216 this . currentStream . Position += 4 ;
@@ -612,14 +612,31 @@ private void InitializeImage<TPixel>(ImageMetadata metadata, FrameControl? frame
612612 /// <typeparam name="TPixel">The type the pixels will be</typeparam>
613613 /// <param name="frameControl">The frame control information for the frame</param>
614614 /// <param name="image">The image that we will populate</param>
615+ /// <param name="previousFrame">The previous frame.</param>
615616 /// <param name="frame">The created frame</param>
616- private void InitializeFrame < TPixel > ( FrameControl frameControl , Image < TPixel > image , out ImageFrame < TPixel > frame )
617+ private void InitializeFrame < TPixel > (
618+ FrameControl frameControl ,
619+ Image < TPixel > image ,
620+ ImageFrame < TPixel > ? previousFrame ,
621+ out ImageFrame < TPixel > frame )
617622 where TPixel : unmanaged, IPixel < TPixel >
618623 {
619- frame = image . Frames . CreateFrame ( ) ;
624+ // We create a clone of the previous frame and add it.
625+ // We will overpaint the difference of pixels on the current frame to create a complete image.
626+ // This ensures that we have enough pixel data to process without distortion. #2450
627+ frame = image . Frames . AddFrame ( previousFrame ?? image . Frames . RootFrame ) ;
620628
621- PngFrameMetadata frameMetadata = frame . Metadata . GetPngFrameMetadata ( ) ;
629+ // If the first `fcTL` chunk uses a `dispose_op` of APNG_DISPOSE_OP_PREVIOUS it should be treated as APNG_DISPOSE_OP_BACKGROUND.
630+ if ( frameControl . DisposeOperation == PngDisposalMethod . Background
631+ || ( previousFrame is null && frameControl . DisposeOperation == PngDisposalMethod . Previous ) )
632+ {
633+ Rectangle restoreArea = new ( ( int ) frameControl . XOffset , ( int ) frameControl . YOffset , ( int ) frameControl . Width , ( int ) frameControl . Height ) ;
634+ Rectangle interest = Rectangle . Intersect ( frame . Bounds ( ) , restoreArea ) ;
635+ Buffer2DRegion < TPixel > pixelRegion = frame . PixelBuffer . GetRegion ( interest ) ;
636+ pixelRegion . Clear ( ) ;
637+ }
622638
639+ PngFrameMetadata frameMetadata = frame . Metadata . GetPngFrameMetadata ( ) ;
623640 frameMetadata . FromChunk ( frameControl ) ;
624641
625642 this . previousScanline ? . Dispose ( ) ;
0 commit comments