Browse Source

Add option to decode just one frame

pull/1985/head
Brian Popow 4 years ago
parent
commit
ab8a1ba564
  1. 7
      src/ImageSharp/Formats/Webp/IWebpDecoderOptions.cs
  2. 11
      src/ImageSharp/Formats/Webp/WebpAnimationDecoder.cs
  3. 7
      src/ImageSharp/Formats/Webp/WebpDecoder.cs
  4. 14
      src/ImageSharp/Formats/Webp/WebpDecoderCore.cs
  5. 16
      tests/ImageSharp.Tests/Formats/WebP/WebpDecoderTests.cs

7
src/ImageSharp/Formats/Webp/IWebpDecoderOptions.cs

@ -1,6 +1,8 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.Metadata;
namespace SixLabors.ImageSharp.Formats.Webp
{
/// <summary>
@ -12,5 +14,10 @@ namespace SixLabors.ImageSharp.Formats.Webp
/// Gets a value indicating whether the metadata should be ignored when the image is being decoded.
/// </summary>
bool IgnoreMetadata { get; }
/// <summary>
/// Gets the decoding mode for multi-frame images.
/// </summary>
FrameDecodingMode DecodingMode { get; }
}
}

11
src/ImageSharp/Formats/Webp/WebpAnimationDecoder.cs

@ -53,10 +53,12 @@ namespace SixLabors.ImageSharp.Formats.Webp
/// </summary>
/// <param name="memoryAllocator">The memory allocator.</param>
/// <param name="configuration">The global configuration.</param>
public WebpAnimationDecoder(MemoryAllocator memoryAllocator, Configuration configuration)
/// <param name="decodingMode">The frame decoding mode.</param>
public WebpAnimationDecoder(MemoryAllocator memoryAllocator, Configuration configuration, FrameDecodingMode decodingMode)
{
this.memoryAllocator = memoryAllocator;
this.configuration = configuration;
this.DecodingMode = decodingMode;
}
/// <summary>
@ -64,6 +66,11 @@ namespace SixLabors.ImageSharp.Formats.Webp
/// </summary>
public IMemoryOwner<byte> AlphaData { get; set; }
/// <summary>
/// Gets the decoding mode for multi-frame images.
/// </summary>
public FrameDecodingMode DecodingMode { get; }
/// <summary>
/// Decodes the animated webp image from the specified stream.
/// </summary>
@ -103,7 +110,7 @@ namespace SixLabors.ImageSharp.Formats.Webp
break;
}
if (stream.Position == stream.Length)
if (stream.Position == stream.Length || this.DecodingMode is FrameDecodingMode.First)
{
break;
}

7
src/ImageSharp/Formats/Webp/WebpDecoder.cs

@ -6,6 +6,7 @@ using System.Threading;
using System.Threading.Tasks;
using SixLabors.ImageSharp.IO;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.Metadata;
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Formats.Webp
@ -20,6 +21,12 @@ namespace SixLabors.ImageSharp.Formats.Webp
/// </summary>
public bool IgnoreMetadata { get; set; }
/// <summary>
/// Gets or sets the decoding mode for multi-frame images.
/// Defaults to All.
/// </summary>
public FrameDecodingMode DecodingMode { get; set; } = FrameDecodingMode.All;
/// <inheritdoc/>
public Image<TPixel> Decode<TPixel>(Configuration configuration, Stream stream)
where TPixel : unmanaged, IPixel<TPixel>

14
src/ImageSharp/Formats/Webp/WebpDecoderCore.cs

@ -56,10 +56,19 @@ namespace SixLabors.ImageSharp.Formats.Webp
public WebpDecoderCore(Configuration configuration, IWebpDecoderOptions options)
{
this.Configuration = configuration;
this.DecodingMode = options.DecodingMode;
this.memoryAllocator = configuration.MemoryAllocator;
this.IgnoreMetadata = options.IgnoreMetadata;
}
/// <inheritdoc/>
public Configuration Configuration { get; }
/// <summary>
/// Gets the decoding mode for multi-frame images.
/// </summary>
public FrameDecodingMode DecodingMode { get; }
/// <summary>
/// Gets a value indicating whether the metadata should be ignored when the image is being decoded.
/// </summary>
@ -70,9 +79,6 @@ namespace SixLabors.ImageSharp.Formats.Webp
/// </summary>
public ImageMetadata Metadata { get; private set; }
/// <inheritdoc/>
public Configuration Configuration { get; }
/// <summary>
/// Gets the dimensions of the image.
/// </summary>
@ -96,7 +102,7 @@ namespace SixLabors.ImageSharp.Formats.Webp
{
if (this.webImageInfo.Features is { Animation: true })
{
using var animationDecoder = new WebpAnimationDecoder(this.memoryAllocator, this.Configuration);
using var animationDecoder = new WebpAnimationDecoder(this.memoryAllocator, this.Configuration, this.DecodingMode);
return animationDecoder.Decode<TPixel>(stream, this.webImageInfo.Features, this.webImageInfo.Width, this.webImageInfo.Height, fileSize);
}

16
tests/ImageSharp.Tests/Formats/WebP/WebpDecoderTests.cs

@ -3,6 +3,7 @@
using System.IO;
using SixLabors.ImageSharp.Formats.Webp;
using SixLabors.ImageSharp.Metadata;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Tests.TestUtilities;
using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison;
@ -234,7 +235,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
// TODO: Reference decoder throws here MagickCorruptImageErrorException, webpinfo also indicates an error here, but decoding the image seems to work.
// [WithFile(Lossless.GreenTransform5, PixelTypes.Rgba32)]
public void WebpDecoder_CanDecode_Lossless_WithSubstractGreenTransform<TPixel>(
public void WebpDecoder_CanDecode_Lossless_WithSubtractGreenTransform<TPixel>(
TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
@ -345,6 +346,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
Assert.Equal(0, webpMetaData.AnimationLoopCount);
Assert.Equal(150U, frameMetaData.FrameDuration);
Assert.Equal(12, image.Frames.Count);
}
}
@ -363,6 +365,18 @@ namespace SixLabors.ImageSharp.Tests.Formats.Webp
Assert.Equal(0, webpMetaData.AnimationLoopCount);
Assert.Equal(150U, frameMetaData.FrameDuration);
Assert.Equal(12, image.Frames.Count);
}
}
[Theory]
[WithFile(Lossless.Animated, PixelTypes.Rgba32)]
public void Decode_AnimatedLossless_WithFrameDecodingModeFirst_OnlyDecodesOneFrame<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage(new WebpDecoder() { DecodingMode = FrameDecodingMode.First }))
{
Assert.Equal(1, image.Frames.Count);
}
}

Loading…
Cancel
Save