diff --git a/src/ImageSharp/Formats/Png/Chunks/FrameControl.cs b/src/ImageSharp/Formats/Png/Chunks/FrameControl.cs
index b912e9b09a..fb2ca473c2 100644
--- a/src/ImageSharp/Formats/Png/Chunks/FrameControl.cs
+++ b/src/ImageSharp/Formats/Png/Chunks/FrameControl.cs
@@ -91,6 +91,8 @@ internal readonly struct FrameControl
///
public PngBlendMethod BlendOperation { get; }
+ public Rectangle Bounds => new((int)this.XOffset, (int)this.YOffset, (int)this.Width, (int)this.Height);
+
///
/// Validates the APng fcTL.
///
diff --git a/src/ImageSharp/Formats/Png/PngDecoderCore.cs b/src/ImageSharp/Formats/Png/PngDecoderCore.cs
index 317207da0f..8c7c7c30d7 100644
--- a/src/ImageSharp/Formats/Png/PngDecoderCore.cs
+++ b/src/ImageSharp/Formats/Png/PngDecoderCore.cs
@@ -225,7 +225,7 @@ internal sealed class PngDecoderCore : IImageDecoderInternals
PngFrameMetadata pngFrameMetadata = currentFrame.Metadata.GetPngFrameMetadata();
if (previousFrame != null && pngFrameMetadata.BlendMethod == PngBlendMethod.Over)
{
- this.AlphaBlend(previousFrame, currentFrame);
+ this.AlphaBlend(previousFrame, currentFrame, previousFrameControl.Value.Bounds);
}
previousFrame = currentFrame;
@@ -630,7 +630,7 @@ internal sealed class PngDecoderCore : IImageDecoderInternals
if (frameControl.DisposeOperation == PngDisposalMethod.Background
|| (previousFrame is null && frameControl.DisposeOperation == PngDisposalMethod.Previous))
{
- Rectangle restoreArea = new((int)frameControl.XOffset, (int)frameControl.YOffset, (int)frameControl.Width, (int)frameControl.Height);
+ Rectangle restoreArea = frameControl.Bounds;
Rectangle interest = Rectangle.Intersect(frame.Bounds(), restoreArea);
Buffer2DRegion pixelRegion = frame.PixelBuffer.GetRegion(interest);
pixelRegion.Clear();
@@ -1895,15 +1895,15 @@ internal sealed class PngDecoderCore : IImageDecoderInternals
private void SwapScanlineBuffers()
=> (this.scanline, this.previousScanline) = (this.previousScanline, this.scanline);
- private void AlphaBlend(ImageFrame src, ImageFrame dst)
+ private void AlphaBlend(ImageFrame src, ImageFrame dst, Rectangle restoreArea)
where TPixel : unmanaged, IPixel
{
- Buffer2D srcPixels = src.PixelBuffer;
- Buffer2D dstPixels = dst.PixelBuffer;
+ Buffer2DRegion srcPixels = src.PixelBuffer.GetRegion(restoreArea);
+ Buffer2DRegion dstPixels = dst.PixelBuffer.GetRegion(restoreArea);
PixelBlender blender =
PixelOperations.Instance.GetPixelBlender(PixelColorBlendingMode.Normal, PixelAlphaCompositionMode.SrcOver);
- for (int y = 0; y < src.Height; y++)
+ for (int y = 0; y < srcPixels.Height; y++)
{
Span srcPixelRow = srcPixels.DangerousGetRowSpan(y);
Span dstPixelRow = dstPixels.DangerousGetRowSpan(y);