Browse Source

Fix handling of case where default image isn't animated

pull/2710/head
SpaceCheetah 2 years ago
parent
commit
5cd98723dc
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

@ -234,8 +234,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(
@ -255,7 +254,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)
{
@ -272,9 +271,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();
@ -643,7 +645,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,
@ -652,15 +654,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