diff --git a/src/ImageSharp/Formats/Tiff/Compression/Decompressors/WebpTiffCompression.cs b/src/ImageSharp/Formats/Tiff/Compression/Decompressors/WebpTiffCompression.cs
index a5ce4f8426..416472e830 100644
--- a/src/ImageSharp/Formats/Tiff/Compression/Decompressors/WebpTiffCompression.cs
+++ b/src/ImageSharp/Formats/Tiff/Compression/Decompressors/WebpTiffCompression.cs
@@ -32,7 +32,7 @@ public WebpTiffCompression(DecoderOptions options, MemoryAllocator memoryAllocat
///
protected override void Decompress(BufferedReadStream stream, int byteCount, int stripHeight, Span buffer, CancellationToken cancellationToken)
{
- using WebpDecoderCore decoder = new(this.options);
+ using WebpDecoderCore decoder = new(new WebpDecoderOptions());
using Image image = decoder.Decode(stream, cancellationToken);
CopyImageBytesToBuffer(buffer, image.Frames.RootFrame.PixelBuffer);
}
diff --git a/src/ImageSharp/Formats/Tiff/Compression/TiffDecompressorsFactory.cs b/src/ImageSharp/Formats/Tiff/Compression/TiffDecompressorsFactory.cs
index b9a1f31553..720e376b9d 100644
--- a/src/ImageSharp/Formats/Tiff/Compression/TiffDecompressorsFactory.cs
+++ b/src/ImageSharp/Formats/Tiff/Compression/TiffDecompressorsFactory.cs
@@ -4,6 +4,7 @@
using SixLabors.ImageSharp.Formats.Tiff.Compression.Decompressors;
using SixLabors.ImageSharp.Formats.Tiff.Constants;
using SixLabors.ImageSharp.Formats.Tiff.PhotometricInterpretation;
+using SixLabors.ImageSharp.Formats.Webp;
using SixLabors.ImageSharp.Memory;
namespace SixLabors.ImageSharp.Formats.Tiff.Compression;
diff --git a/src/ImageSharp/Formats/Webp/BackgroundColorHandling.cs b/src/ImageSharp/Formats/Webp/BackgroundColorHandling.cs
new file mode 100644
index 0000000000..c843311c7f
--- /dev/null
+++ b/src/ImageSharp/Formats/Webp/BackgroundColorHandling.cs
@@ -0,0 +1,21 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+namespace SixLabors.ImageSharp.Formats.Webp;
+
+///
+/// Enum to decide how to handle the background color of the Animation chunk during decoding.
+///
+public enum BackgroundColorHandling
+{
+ ///
+ /// The background color of the ANIM chunk will be used to initialize the canvas to fill the unused space on the canvas around the frame.
+ /// Also, if AnimationDisposalMethod.Dispose is used, this color will be used to restore the canvas background.
+ ///
+ Standard = 0,
+
+ ///
+ /// The background color of the ANIM chunk is ignored and instead the canvas is initialized with black, BGRA(0, 0, 0, 0).
+ ///
+ Ignore = 1
+}
diff --git a/src/ImageSharp/Formats/Webp/WebpAnimationDecoder.cs b/src/ImageSharp/Formats/Webp/WebpAnimationDecoder.cs
index 21337ce6c8..90c9c70b26 100644
--- a/src/ImageSharp/Formats/Webp/WebpAnimationDecoder.cs
+++ b/src/ImageSharp/Formats/Webp/WebpAnimationDecoder.cs
@@ -52,17 +52,24 @@ internal class WebpAnimationDecoder : IDisposable
///
private IMemoryOwner? alphaData;
+ ///
+ /// The flag to decide how to handle the background color in the Animation Chunk.
+ ///
+ private readonly BackgroundColorHandling backgroundColorHandling;
+
///
/// Initializes a new instance of the class.
///
/// The memory allocator.
/// The global configuration.
/// The maximum number of frames to decode. Inclusive.
- public WebpAnimationDecoder(MemoryAllocator memoryAllocator, Configuration configuration, uint maxFrames)
+ /// The flag to decide how to handle the background color in the Animation Chunk.
+ public WebpAnimationDecoder(MemoryAllocator memoryAllocator, Configuration configuration, uint maxFrames, BackgroundColorHandling backgroundColorHandling)
{
this.memoryAllocator = memoryAllocator;
this.configuration = configuration;
this.maxFrames = maxFrames;
+ this.backgroundColorHandling = backgroundColorHandling;
}
///
@@ -94,7 +101,10 @@ public Image Decode(BufferedReadStream stream, WebpFeatures feat
switch (chunkType)
{
case WebpChunkType.Animation:
- uint dataSize = this.ReadFrame(stream, ref image, ref previousFrame, width, height, features.AnimationBackgroundColor!.Value);
+ Color backgroundColor = this.backgroundColorHandling == BackgroundColorHandling.Ignore
+ ? new Color(new Bgra32(0, 0, 0, 0))
+ : features.AnimationBackgroundColor!.Value;
+ uint dataSize = this.ReadFrame(stream, ref image, ref previousFrame, width, height, backgroundColor);
remainingBytes -= (int)dataSize;
break;
case WebpChunkType.Xmp:
diff --git a/src/ImageSharp/Formats/Webp/WebpDecoder.cs b/src/ImageSharp/Formats/Webp/WebpDecoder.cs
index daa5eaf4fe..e23b817ccd 100644
--- a/src/ImageSharp/Formats/Webp/WebpDecoder.cs
+++ b/src/ImageSharp/Formats/Webp/WebpDecoder.cs
@@ -8,7 +8,7 @@ namespace SixLabors.ImageSharp.Formats.Webp;
///
/// Image decoder for generating an image out of a webp stream.
///
-public sealed class WebpDecoder : ImageDecoder
+public sealed class WebpDecoder : SpecializedImageDecoder
{
private WebpDecoder()
{
@@ -25,25 +25,33 @@ protected override ImageInfo Identify(DecoderOptions options, Stream stream, Can
Guard.NotNull(options, nameof(options));
Guard.NotNull(stream, nameof(stream));
- using WebpDecoderCore decoder = new(options);
+ using WebpDecoderCore decoder = new(new WebpDecoderOptions() { GeneralOptions = options });
return decoder.Identify(options.Configuration, stream, cancellationToken);
}
///
- protected override Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken)
+ protected override Image Decode(WebpDecoderOptions options, Stream stream, CancellationToken cancellationToken)
{
Guard.NotNull(options, nameof(options));
Guard.NotNull(stream, nameof(stream));
using WebpDecoderCore decoder = new(options);
- Image image = decoder.Decode(options.Configuration, stream, cancellationToken);
+ Image image = decoder.Decode(options.GeneralOptions.Configuration, stream, cancellationToken);
- ScaleToTargetSize(options, image);
+ ScaleToTargetSize(options.GeneralOptions, image);
return image;
}
+ ///
+ protected override Image Decode(WebpDecoderOptions options, Stream stream, CancellationToken cancellationToken)
+ => this.Decode(options, stream, cancellationToken);
+
///
protected override Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken)
=> this.Decode(options, stream, cancellationToken);
+
+ ///
+ protected override WebpDecoderOptions CreateDefaultSpecializedOptions(DecoderOptions options)
+ => new() { GeneralOptions = options };
}
diff --git a/src/ImageSharp/Formats/Webp/WebpDecoderCore.cs b/src/ImageSharp/Formats/Webp/WebpDecoderCore.cs
index 223e15a0e7..8832ac1068 100644
--- a/src/ImageSharp/Formats/Webp/WebpDecoderCore.cs
+++ b/src/ImageSharp/Formats/Webp/WebpDecoderCore.cs
@@ -48,16 +48,22 @@ internal sealed class WebpDecoderCore : IImageDecoderInternals, IDisposable
///
private WebpImageInfo? webImageInfo;
+ ///
+ /// The flag to decide how to handle the background color in the Animation Chunk.
+ ///
+ private BackgroundColorHandling backgroundColorHandling;
+
///
/// Initializes a new instance of the class.
///
/// The decoder options.
- public WebpDecoderCore(DecoderOptions options)
+ public WebpDecoderCore(WebpDecoderOptions options)
{
- this.Options = options;
- this.configuration = options.Configuration;
- this.skipMetadata = options.SkipMetadata;
- this.maxFrames = options.MaxFrames;
+ this.Options = options.GeneralOptions;
+ this.backgroundColorHandling = options.BackgroundColorHandling;
+ this.configuration = options.GeneralOptions.Configuration;
+ this.skipMetadata = options.GeneralOptions.SkipMetadata;
+ this.maxFrames = options.GeneralOptions.MaxFrames;
this.memoryAllocator = this.configuration.MemoryAllocator;
}
@@ -83,7 +89,7 @@ public Image Decode(BufferedReadStream stream, CancellationToken
{
if (this.webImageInfo.Features is { Animation: true })
{
- using WebpAnimationDecoder animationDecoder = new(this.memoryAllocator, this.configuration, this.maxFrames);
+ using WebpAnimationDecoder animationDecoder = new(this.memoryAllocator, this.configuration, this.maxFrames, this.backgroundColorHandling);
return animationDecoder.Decode(stream, this.webImageInfo.Features, this.webImageInfo.Width, this.webImageInfo.Height, fileSize);
}
diff --git a/src/ImageSharp/Formats/Webp/WebpDecoderOptions.cs b/src/ImageSharp/Formats/Webp/WebpDecoderOptions.cs
new file mode 100644
index 0000000000..6fb15acbb4
--- /dev/null
+++ b/src/ImageSharp/Formats/Webp/WebpDecoderOptions.cs
@@ -0,0 +1,21 @@
+// Copyright (c) Six Labors.
+// Licensed under the Six Labors Split License.
+
+namespace SixLabors.ImageSharp.Formats.Webp;
+
+///
+/// Configuration options for decoding webp images.
+///
+public sealed class WebpDecoderOptions : ISpecializedDecoderOptions
+{
+ ///
+ public DecoderOptions GeneralOptions { get; init; } = new();
+
+ ///
+ /// Gets the flag to decide how to handle the background color Animation Chunk.
+ /// The specification is vague on how to handle the background color of the animation chunk.
+ /// This option let's the user choose how to deal with it.
+ ///
+ ///
+ public BackgroundColorHandling BackgroundColorHandling { get; init; } = BackgroundColorHandling.Standard;
+}