Browse Source

Fix handling of case where default image isn't animated

pull/2713/head
SpaceCheetah 2 years ago
parent
commit
9b8ef108d4
No known key found for this signature in database GPG Key ID: A60F20D29141DFF9
  1. 22
      src/ImageSharp/Formats/Png/PngDecoderCore.cs
  2. 5
      src/ImageSharp/Formats/Png/PngMetadata.cs

22
src/ImageSharp/Formats/Png/PngDecoderCore.cs

@ -228,8 +228,7 @@ internal sealed class PngDecoderCore : IImageDecoderInternals
PngThrowHelper.ThrowMissingFrameControl();
}
previousFrameControl ??= new((uint)this.header.Width, (uint)this.header.Height);
this.InitializeFrame(previousFrameControl.Value, currentFrameControl.Value, image, previousFrame, out currentFrame);
this.InitializeFrame(previousFrameControl, currentFrameControl.Value, image, previousFrame, out currentFrame);
this.currentStream.Position += 4;
this.ReadScanlines(
@ -249,7 +248,7 @@ internal sealed class PngDecoderCore : IImageDecoderInternals
break;
case PngChunkType.Data:
pngMetadata.DefaultImageAnimated = currentFrameControl != null;
currentFrameControl ??= new((uint)this.header.Width, (uint)this.header.Height);
if (image is null)
{
@ -266,9 +265,12 @@ internal sealed class PngDecoderCore : IImageDecoderInternals
this.ReadNextDataChunk,
currentFrameControl.Value,
cancellationToken);
if (pngMetadata.DefaultImageAnimated)
{
previousFrame = currentFrame;
previousFrameControl = currentFrameControl;
}
previousFrame = currentFrame;
previousFrameControl = currentFrameControl;
break;
case PngChunkType.Palette:
this.palette = chunk.Data.GetSpan().ToArray();
@ -637,7 +639,7 @@ internal sealed class PngDecoderCore : IImageDecoderInternals
/// <param name="previousFrame">The previous frame.</param>
/// <param name="frame">The created frame</param>
private void InitializeFrame<TPixel>(
FrameControl previousFrameControl,
FrameControl? previousFrameControl,
FrameControl currentFrameControl,
Image<TPixel> image,
ImageFrame<TPixel>? previousFrame,
@ -646,15 +648,15 @@ internal sealed class PngDecoderCore : IImageDecoderInternals
{
frame = image.Frames.AddFrame(previousFrame ?? image.Frames.RootFrame);
// if restoring to before first frame, restore to background
if (previousFrame is null && previousFrameControl.DisposeOperation == PngDisposalMethod.RestoreToPrevious)
// If restoring to before first frame, restore to background. Same if first frame (previousFrameControl null).
if (previousFrameControl == null || (previousFrame is null && previousFrameControl.Value.DisposeOperation == PngDisposalMethod.RestoreToPrevious))
{
Buffer2DRegion<TPixel> pixelRegion = frame.PixelBuffer.GetRegion();
pixelRegion.Clear();
}
else if (previousFrameControl.DisposeOperation == PngDisposalMethod.RestoreToBackground)
else if (previousFrameControl.Value.DisposeOperation == PngDisposalMethod.RestoreToBackground)
{
Rectangle restoreArea = previousFrameControl.Bounds;
Rectangle restoreArea = previousFrameControl.Value.Bounds;
Buffer2DRegion<TPixel> pixelRegion = frame.PixelBuffer.GetRegion(restoreArea);
pixelRegion.Clear();
}

5
src/ImageSharp/Formats/Png/PngMetadata.cs

@ -83,6 +83,11 @@ public class PngMetadata : IDeepCloneable
/// </summary>
public uint RepeatCount { get; set; } = 1;
/// <summary>
/// Gets or sets a value indicating whether the default image is shown as part of the animated sequence
/// </summary>
public bool DefaultImageAnimated { get; set; }
/// <inheritdoc/>
public IDeepCloneable DeepClone() => new PngMetadata(this);

Loading…
Cancel
Save