Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for decoding webp images with animations #1985

Merged
merged 22 commits into from
May 17, 2022
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
9cc92b8
Decode animated lossless webp
brianpopow Feb 8, 2022
00e91cb
Add alpha blending for animated webp
brianpopow Feb 9, 2022
2b8af22
Add decoding animated lossy webp
brianpopow Feb 9, 2022
71460c7
Merge branch 'master' into bp/webpanimation
brianpopow Feb 9, 2022
7d0dd42
Replace broken webp image with exif data
brianpopow Feb 9, 2022
c93007c
Fix identify webp with alpha
brianpopow Feb 9, 2022
54a4390
Add tests for animated webp
brianpopow Feb 10, 2022
4c30ccd
Add loopcount and duration to the webp metadata
brianpopow Feb 10, 2022
ab8a1ba
Add option to decode just one frame
brianpopow Feb 10, 2022
8a115af
Merge branch 'main' into bp/webpanimation
brianpopow Feb 10, 2022
8b177f8
Merge branch 'main' into bp/webpanimation
brianpopow Feb 14, 2022
e2b33eb
Merge branch 'main' into bp/webpanimation
brianpopow Feb 22, 2022
cf20723
Merge branch 'main' into bp/webpanimation
brianpopow Mar 4, 2022
599d6a1
Merge branch 'main' into bp/webpanimation
JimBobSquarePants Mar 7, 2022
5a1ad2f
Merge remote-tracking branch 'origin/main' into bp/webpanimation
brianpopow Mar 15, 2022
51160a4
Merge remote-tracking branch 'origin/main' into bp/webpanimation
brianpopow Apr 28, 2022
89d1582
Add missing dispose of webpInfo
brianpopow Apr 28, 2022
e81d973
Merge branch 'main' into bp/webpanimation
JimBobSquarePants May 7, 2022
2a8418f
Review changes
brianpopow May 15, 2022
4dd0dc9
Merge branch 'main' into bp/webpanimation
brianpopow May 15, 2022
8528f1a
Optimize RestoreToBackground
JimBobSquarePants May 17, 2022
980a1f0
Use bulk conversion in AlphaBlend
brianpopow May 17, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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