Skip to content

Commit

Permalink
Merge pull request #1985 from SixLabors/bp/webpanimation
Browse files Browse the repository at this point in the history
Add support for decoding webp images with animations
  • Loading branch information
brianpopow authored May 17, 2022
2 parents 5634228 + 980a1f0 commit c661ab1
Show file tree
Hide file tree
Showing 57 changed files with 1,292 additions and 399 deletions.
2 changes: 1 addition & 1 deletion src/ImageSharp/Formats/Gif/GifDecoderCore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ public GifDecoderCore(Configuration configuration, IGifDecoderOptions options)
/// <summary>
/// Gets the dimensions of the image.
/// </summary>
public Size Dimensions => new Size(this.imageDescriptor.Width, this.imageDescriptor.Height);
public Size Dimensions => new(this.imageDescriptor.Width, this.imageDescriptor.Height);

private MemoryAllocator MemoryAllocator => this.Configuration.MemoryAllocator;

Expand Down
8 changes: 4 additions & 4 deletions src/ImageSharp/Formats/Gif/GifFormat.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) Six Labors.
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.

using System.Collections.Generic;
Expand All @@ -17,7 +17,7 @@ private GifFormat()
/// <summary>
/// Gets the current instance.
/// </summary>
public static GifFormat Instance { get; } = new GifFormat();
public static GifFormat Instance { get; } = new();

/// <inheritdoc/>
public string Name => "GIF";
Expand All @@ -32,9 +32,9 @@ private GifFormat()
public IEnumerable<string> FileExtensions => GifConstants.FileExtensions;

/// <inheritdoc/>
public GifMetadata CreateDefaultFormatMetadata() => new GifMetadata();
public GifMetadata CreateDefaultFormatMetadata() => new();

/// <inheritdoc/>
public GifFrameMetadata CreateDefaultFormatFrameMetadata() => new GifFrameMetadata();
public GifFrameMetadata CreateDefaultFormatFrameMetadata() => new();
}
}
23 changes: 23 additions & 0 deletions src/ImageSharp/Formats/Webp/AnimationBlendingMethod.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.

namespace SixLabors.ImageSharp.Formats.Webp
{
/// <summary>
/// Indicates how transparent pixels of the current frame are to be blended with corresponding pixels of the previous canvas.
/// </summary>
internal enum AnimationBlendingMethod
{
/// <summary>
/// Use alpha blending. After disposing of the previous frame, render the current frame on the canvas using alpha-blending.
/// If the current frame does not have an alpha channel, assume alpha value of 255, effectively replacing the rectangle.
/// </summary>
AlphaBlending = 0,

/// <summary>
/// Do not blend. After disposing of the previous frame,
/// render the current frame on the canvas by overwriting the rectangle covered by the current frame.
/// </summary>
DoNotBlend = 1
}
}
21 changes: 21 additions & 0 deletions src/ImageSharp/Formats/Webp/AnimationDisposalMethod.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.

namespace SixLabors.ImageSharp.Formats.Webp
{
/// <summary>
/// Indicates how the current frame is to be treated after it has been displayed (before rendering the next frame) on the canvas.
/// </summary>
internal enum AnimationDisposalMethod
{
/// <summary>
/// Do not dispose. Leave the canvas as is.
/// </summary>
DoNotDispose = 0,

/// <summary>
/// Dispose to background color. Fill the rectangle on the canvas covered by the current frame with background color specified in the ANIM chunk.
/// </summary>
Dispose = 1
}
}
49 changes: 49 additions & 0 deletions src/ImageSharp/Formats/Webp/AnimationFrameData.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.

namespace SixLabors.ImageSharp.Formats.Webp
{
internal struct AnimationFrameData
{
/// <summary>
/// The animation chunk size.
/// </summary>
public uint DataSize;

/// <summary>
/// The X coordinate of the upper left corner of the frame is Frame X * 2.
/// </summary>
public uint X;

/// <summary>
/// The Y coordinate of the upper left corner of the frame is Frame Y * 2.
/// </summary>
public uint Y;

/// <summary>
/// The width of the frame.
/// </summary>
public uint Width;

/// <summary>
/// The height of the frame.
/// </summary>
public uint Height;

/// <summary>
/// The time to wait before displaying the next frame, in 1 millisecond units.
/// Note the interpretation of frame duration of 0 (and often smaller then 10) is implementation defined.
/// </summary>
public uint Duration;

/// <summary>
/// Indicates how transparent pixels of the current frame are to be blended with corresponding pixels of the previous canvas.
/// </summary>
public AnimationBlendingMethod BlendingMethod;

/// <summary>
/// Indicates how the current frame is to be treated after it has been displayed (before rendering the next frame) on the canvas.
/// </summary>
public AnimationDisposalMethod DisposalMethod;
}
}
7 changes: 7 additions & 0 deletions src/ImageSharp/Formats/Webp/IWebpDecoderOptions.cs
Original file line number Diff line number Diff line change
@@ -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>
Expand All @@ -12,5 +14,10 @@ internal interface IWebpDecoderOptions
/// 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; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ public WebpLosslessDecoder(Vp8LBitReader bitReader, MemoryAllocator memoryAlloca
private static ReadOnlySpan<byte> LiteralMap => new byte[] { 0, 1, 1, 1, 0 };

/// <summary>
/// Decodes the image from the stream using the bitreader.
/// Decodes the lossless webp image from the stream.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="pixels">The pixel buffer to store the decoded data.</param>
Expand Down
13 changes: 11 additions & 2 deletions src/ImageSharp/Formats/Webp/Lossy/WebpLossyDecoder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,16 @@ public WebpLossyDecoder(Vp8BitReader bitReader, MemoryAllocator memoryAllocator,
this.configuration = configuration;
}

public void Decode<TPixel>(Buffer2D<TPixel> pixels, int width, int height, WebpImageInfo info)
/// <summary>
/// Decodes the lossless webp image from the stream.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="pixels">The pixel buffer to store the decoded data.</param>
/// <param name="width">The width of the image.</param>
/// <param name="height">The height of the image.</param>
/// <param name="info">Information about the image.</param>
/// <param name="alphaData">The ALPH chunk data.</param>
public void Decode<TPixel>(Buffer2D<TPixel> pixels, int width, int height, WebpImageInfo info, IMemoryOwner<byte> alphaData)
where TPixel : unmanaged, IPixel<TPixel>
{
// Paragraph 9.2: color space and clamp type follow.
Expand Down Expand Up @@ -105,7 +114,7 @@ public void Decode<TPixel>(Buffer2D<TPixel> pixels, int width, int height, WebpI
using (var alphaDecoder = new AlphaDecoder(
width,
height,
info.Features.AlphaData,
alphaData,
info.Features.AlphaChunkHeader,
this.memoryAllocator,
this.configuration))
Expand Down
7 changes: 7 additions & 0 deletions src/ImageSharp/Formats/Webp/MetadataExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,12 @@ public static partial class MetadataExtensions
/// <param name="metadata">The metadata this method extends.</param>
/// <returns>The <see cref="WebpMetadata"/>.</returns>
public static WebpMetadata GetWebpMetadata(this ImageMetadata metadata) => metadata.GetFormatMetadata(WebpFormat.Instance);

/// <summary>
/// Gets the webp format specific metadata for the image frame.
/// </summary>
/// <param name="metadata">The metadata this method extends.</param>
/// <returns>The <see cref="WebpFrameMetadata"/>.</returns>
public static WebpFrameMetadata GetWebpMetadata(this ImageFrameMetadata metadata) => metadata.GetFormatMetadata(WebpFormat.Instance);
}
}
Loading

0 comments on commit c661ab1

Please sign in to comment.