Browse Source

Port WebP and cleanup options

pull/2180/head
James Jackson-South 4 years ago
parent
commit
48a81062c3
  1. 6
      src/ImageSharp/Formats/DecoderOptions.cs
  2. 6
      src/ImageSharp/Formats/Gif/GifDecoderCore.cs
  3. 2
      src/ImageSharp/Formats/Png/PngDecoderOptions.cs
  4. 2
      src/ImageSharp/Formats/Tga/TgaDecoderOptions.cs
  5. 23
      src/ImageSharp/Formats/Tiff/ITiffDecoderOptions.cs
  6. 8
      src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs
  7. 2
      src/ImageSharp/Formats/Tiff/TiffDecoderOptions.cs
  8. 23
      src/ImageSharp/Formats/Webp/IWebpDecoderOptions.cs
  9. 39
      src/ImageSharp/Formats/Webp/WebpAnimationDecoder.cs
  10. 44
      src/ImageSharp/Formats/Webp/WebpDecoder.cs
  11. 110
      src/ImageSharp/Formats/Webp/WebpDecoderCore.cs
  12. 14
      src/ImageSharp/Formats/Webp/WebpDecoderOptions.cs

6
src/ImageSharp/Formats/DecoderOptions.cs

@ -1,6 +1,8 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using System;
namespace SixLabors.ImageSharp.Formats
{
/// <summary>
@ -8,6 +10,8 @@ namespace SixLabors.ImageSharp.Formats
/// </summary>
public sealed class DecoderOptions
{
private uint maxFrames = uint.MaxValue;
/// <summary>
/// Gets or sets a custom Configuration instance to be used by the image processing pipeline.
/// </summary>
@ -26,6 +30,6 @@ namespace SixLabors.ImageSharp.Formats
/// <summary>
/// Gets or sets the maximum number of image frames to decode, inclusive.
/// </summary>
public int MaxFrames { get; set; } = int.MaxValue;
public uint MaxFrames { get => this.maxFrames; set => this.maxFrames = Math.Min(Math.Max(value, 1), uint.MaxValue); }
}
}

6
src/ImageSharp/Formats/Gif/GifDecoderCore.cs

@ -69,7 +69,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// <summary>
/// The maximum number of frames to decode. Inclusive.
/// </summary>
private readonly int maxFrames;
private readonly uint maxFrames;
/// <summary>
/// Whether to skip metadata during decode.
@ -109,7 +109,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
public Image<TPixel> Decode<TPixel>(BufferedReadStream stream, CancellationToken cancellationToken)
where TPixel : unmanaged, IPixel<TPixel>
{
int frameCount = 0;
uint frameCount = 0;
Image<TPixel> image = null;
ImageFrame<TPixel> previousFrame = null;
try
@ -122,7 +122,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
{
if (nextFlag == GifConstants.ImageLabel)
{
if (previousFrame != null && frameCount++ <= this.maxFrames)
if (previousFrame != null && frameCount++ > this.maxFrames)
{
break;
}

2
src/ImageSharp/Formats/Png/PngDecoderOptions.cs

@ -6,7 +6,7 @@ namespace SixLabors.ImageSharp.Formats.Png
/// <summary>
/// Configuration options for decoding Png images.
/// </summary>
public class PngDecoderOptions : ISpecializedDecoderOptions
public sealed class PngDecoderOptions : ISpecializedDecoderOptions
{
/// <inheritdoc/>
public DecoderOptions GeneralOptions { get; set; } = new();

2
src/ImageSharp/Formats/Tga/TgaDecoderOptions.cs

@ -6,7 +6,7 @@ namespace SixLabors.ImageSharp.Formats.Tga
/// <summary>
/// Configuration options for decoding Tga images.
/// </summary>
public class TgaDecoderOptions : ISpecializedDecoderOptions
public sealed class TgaDecoderOptions : ISpecializedDecoderOptions
{
/// <inheritdoc/>
public DecoderOptions GeneralOptions { get; set; } = new();

23
src/ImageSharp/Formats/Tiff/ITiffDecoderOptions.cs

@ -1,23 +0,0 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.Metadata;
namespace SixLabors.ImageSharp.Formats.Tiff
{
/// <summary>
/// Encapsulates the options for the <see cref="TiffDecoder"/>.
/// </summary>
internal interface ITiffDecoderOptions
{
/// <summary>
/// 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; }
}
}

8
src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs

@ -33,14 +33,14 @@ namespace SixLabors.ImageSharp.Formats.Tiff
private readonly MemoryAllocator memoryAllocator;
/// <summary>
/// Gets or sets a value indicating whether the metadata should be ignored when the image is being decoded.
/// A value indicating whether the metadata should be ignored when the image is being decoded.
/// </summary>
private readonly bool skipMetadata;
/// <summary>
/// The maximum number of frames to decode. Inclusive.
/// </summary>
private readonly int maxFrames;
private readonly uint maxFrames;
/// <summary>
/// The stream to decode from.
@ -170,14 +170,14 @@ namespace SixLabors.ImageSharp.Formats.Tiff
this.byteOrder = reader.ByteOrder;
this.isBigTiff = reader.IsBigTiff;
int frameCount = 0;
uint frameCount = 0;
foreach (ExifProfile ifd in directories)
{
cancellationToken.ThrowIfCancellationRequested();
ImageFrame<TPixel> frame = this.DecodeFrame<TPixel>(ifd, cancellationToken);
frames.Add(frame);
if (frameCount++ <= this.maxFrames)
if (frameCount++ > this.maxFrames)
{
break;
}

2
src/ImageSharp/Formats/Tiff/TiffDecoderOptions.cs

@ -6,7 +6,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff
/// <summary>
/// Configuration options for decoding Tiff images.
/// </summary>
public class TiffDecoderOptions : ISpecializedDecoderOptions
public sealed class TiffDecoderOptions : ISpecializedDecoderOptions
{
/// <inheritdoc/>
public DecoderOptions GeneralOptions { get; set; } = new();

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

@ -1,23 +0,0 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.Metadata;
namespace SixLabors.ImageSharp.Formats.Webp
{
/// <summary>
/// Image decoder options for generating an image out of a webp stream.
/// </summary>
internal interface IWebpDecoderOptions
{
/// <summary>
/// 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; }
}
}

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

@ -33,6 +33,11 @@ namespace SixLabors.ImageSharp.Formats.Webp
/// </summary>
private readonly Configuration configuration;
/// <summary>
/// The maximum number of frames to decode. Inclusive.
/// </summary>
private readonly uint maxFrames;
/// <summary>
/// The area to restore.
/// </summary>
@ -48,29 +53,24 @@ namespace SixLabors.ImageSharp.Formats.Webp
/// </summary>
private WebpMetadata webpMetadata;
/// <summary>
/// The alpha data, if an ALPH chunk is present.
/// </summary>
private IMemoryOwner<byte> alphaData;
/// <summary>
/// Initializes a new instance of the <see cref="WebpAnimationDecoder"/> class.
/// </summary>
/// <param name="memoryAllocator">The memory allocator.</param>
/// <param name="configuration">The global configuration.</param>
/// <param name="decodingMode">The frame decoding mode.</param>
public WebpAnimationDecoder(MemoryAllocator memoryAllocator, Configuration configuration, FrameDecodingMode decodingMode)
/// <param name="maxFrames">The maximum number of frames to decode. Inclusive.</param>
public WebpAnimationDecoder(MemoryAllocator memoryAllocator, Configuration configuration, uint maxFrames)
{
this.memoryAllocator = memoryAllocator;
this.configuration = configuration;
this.DecodingMode = decodingMode;
this.maxFrames = maxFrames;
}
/// <summary>
/// Gets or sets the alpha data, if an ALPH chunk is present.
/// </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>
@ -90,6 +90,7 @@ namespace SixLabors.ImageSharp.Formats.Webp
this.webpMetadata = this.metadata.GetWebpMetadata();
this.webpMetadata.AnimationLoopCount = features.AnimationLoopCount;
uint frameCount = 0;
int remainingBytes = (int)completeDataSize;
while (remainingBytes > 0)
{
@ -110,7 +111,7 @@ namespace SixLabors.ImageSharp.Formats.Webp
break;
}
if (stream.Position == stream.Length || this.DecodingMode is FrameDecodingMode.First)
if (stream.Position == stream.Length || frameCount++ > this.maxFrames)
{
break;
}
@ -224,14 +225,14 @@ namespace SixLabors.ImageSharp.Formats.Webp
/// <param name="stream">The stream to read from.</param>
private byte ReadAlphaData(BufferedReadStream stream)
{
this.AlphaData?.Dispose();
this.alphaData?.Dispose();
uint alphaChunkSize = WebpChunkParsingUtils.ReadChunkSize(stream, this.buffer);
int alphaDataSize = (int)(alphaChunkSize - 1);
this.AlphaData = this.memoryAllocator.Allocate<byte>(alphaDataSize);
this.alphaData = this.memoryAllocator.Allocate<byte>(alphaDataSize);
byte alphaChunkHeader = (byte)stream.ReadByte();
Span<byte> alphaData = this.AlphaData.GetSpan();
Span<byte> alphaData = this.alphaData.GetSpan();
stream.Read(alphaData, 0, alphaDataSize);
return alphaChunkHeader;
@ -260,7 +261,7 @@ namespace SixLabors.ImageSharp.Formats.Webp
else
{
var lossyDecoder = new WebpLossyDecoder(webpInfo.Vp8BitReader, this.memoryAllocator, this.configuration);
lossyDecoder.Decode(pixelBufferDecoded, (int)webpInfo.Width, (int)webpInfo.Height, webpInfo, this.AlphaData);
lossyDecoder.Decode(pixelBufferDecoded, (int)webpInfo.Width, (int)webpInfo.Height, webpInfo, this.alphaData);
}
return pixelBufferDecoded;
@ -381,6 +382,6 @@ namespace SixLabors.ImageSharp.Formats.Webp
}
/// <inheritdoc/>
public void Dispose() => this.AlphaData?.Dispose();
public void Dispose() => this.alphaData?.Dispose();
}
}

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

@ -3,8 +3,6 @@
using System.IO;
using System.Threading;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.Metadata;
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Formats.Webp
@ -12,49 +10,29 @@ namespace SixLabors.ImageSharp.Formats.Webp
/// <summary>
/// Image decoder for generating an image out of a webp stream.
/// </summary>
public sealed class WebpDecoder : IImageDecoder, IWebpDecoderOptions, IImageInfoDetector
public sealed class WebpDecoder : ImageDecoder<WebpDecoderOptions>
{
/// <summary>
/// Gets or sets a value indicating whether the metadata should be ignored when the image is being decoded.
/// </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, CancellationToken cancellationToken)
where TPixel : unmanaged, IPixel<TPixel>
public override Image<TPixel> DecodeSpecialized<TPixel>(WebpDecoderOptions options, Stream stream, CancellationToken cancellationToken)
{
Guard.NotNull(stream, nameof(stream));
WebpDecoderCore decoder = new(options);
Image<TPixel> image = decoder.Decode<WebpDecoderOptions, TPixel>(options.GeneralOptions.Configuration, stream, cancellationToken);
using var decoder = new WebpDecoderCore(configuration, this);
Resize(options.GeneralOptions, image);
try
{
return decoder.Decode<TPixel>(configuration, stream, cancellationToken);
}
catch (InvalidMemoryOperationException ex)
{
Size dims = decoder.Dimensions;
throw new InvalidImageContentException($"Cannot decode image. Failed to allocate buffers for possibly degenerate dimensions: {dims.Width}x{dims.Height}.", ex);
}
return image;
}
/// <inheritdoc />
public Image Decode(Configuration configuration, Stream stream, CancellationToken cancellationToken)
=> this.Decode<Rgba32>(configuration, stream, cancellationToken);
/// <inheritdoc/>
public override Image DecodeSpecialized(WebpDecoderOptions options, Stream stream, CancellationToken cancellationToken)
=> this.DecodeSpecialized<Rgba32>(options, stream, cancellationToken);
/// <inheritdoc/>
public IImageInfo Identify(Configuration configuration, Stream stream, CancellationToken cancellationToken)
public override IImageInfo IdentifySpecialized(WebpDecoderOptions options, Stream stream, CancellationToken cancellationToken)
{
Guard.NotNull(stream, nameof(stream));
return new WebpDecoderCore(configuration, this).Identify(configuration, stream, cancellationToken);
return new WebpDecoderCore(options).Identify(options.GeneralOptions.Configuration, stream, cancellationToken);
}
}
}

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

@ -4,7 +4,6 @@
using System;
using System.Buffers;
using System.Buffers.Binary;
using System.IO;
using System.Threading;
using SixLabors.ImageSharp.Formats.Webp.Lossless;
using SixLabors.ImageSharp.Formats.Webp.Lossy;
@ -21,7 +20,7 @@ namespace SixLabors.ImageSharp.Formats.Webp
/// <summary>
/// Performs the webp decoding operation.
/// </summary>
internal sealed class WebpDecoderCore : IImageDecoderInternals, IDisposable
internal sealed class WebpDecoderCore : IImageDecoderInternals<WebpDecoderOptions>, IDisposable
{
/// <summary>
/// Reusable buffer.
@ -29,65 +28,68 @@ namespace SixLabors.ImageSharp.Formats.Webp
private readonly byte[] buffer = new byte[4];
/// <summary>
/// Used for allocating memory during the decoding operations.
/// General configuration options.
/// </summary>
private readonly MemoryAllocator memoryAllocator;
private readonly Configuration configuration;
/// <summary>
/// The stream to decode from.
/// A value indicating whether the metadata should be ignored when the image is being decoded.
/// </summary>
private BufferedReadStream currentStream;
private readonly bool skipMetadata;
/// <summary>
/// The webp specific metadata.
/// The maximum number of frames to decode. Inclusive.
/// </summary>
private WebpMetadata webpMetadata;
private readonly uint maxFrames;
/// <summary>
/// Information about the webp image.
/// Gets the <see cref="ImageMetadata"/> decoded by this decoder instance.
/// </summary>
private WebpImageInfo webImageInfo;
private ImageMetadata metadata;
/// <summary>
/// Initializes a new instance of the <see cref="WebpDecoderCore"/> class.
/// Gets or sets the alpha data, if an ALPH chunk is present.
/// </summary>
/// <param name="configuration">The configuration.</param>
/// <param name="options">The options.</param>
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; }
private IMemoryOwner<byte> alphaData;
/// <summary>
/// Gets the decoding mode for multi-frame images.
/// Used for allocating memory during the decoding operations.
/// </summary>
public FrameDecodingMode DecodingMode { get; }
private readonly MemoryAllocator memoryAllocator;
/// <summary>
/// Gets a value indicating whether the metadata should be ignored when the image is being decoded.
/// The stream to decode from.
/// </summary>
public bool IgnoreMetadata { get; }
private BufferedReadStream currentStream;
/// <summary>
/// Gets the <see cref="ImageMetadata"/> decoded by this decoder instance.
/// The webp specific metadata.
/// </summary>
public ImageMetadata Metadata { get; private set; }
private WebpMetadata webpMetadata;
/// <summary>
/// Gets the dimensions of the image.
/// Information about the webp image.
/// </summary>
public Size Dimensions => new((int)this.webImageInfo.Width, (int)this.webImageInfo.Height);
private WebpImageInfo webImageInfo;
/// <summary>
/// Gets or sets the alpha data, if an ALPH chunk is present.
/// Initializes a new instance of the <see cref="WebpDecoderCore"/> class.
/// </summary>
public IMemoryOwner<byte> AlphaData { get; set; }
/// <param name="options">The decoder options.</param>
public WebpDecoderCore(WebpDecoderOptions options)
{
this.Options = options;
this.configuration = options.GeneralOptions.Configuration;
this.skipMetadata = options.GeneralOptions.SkipMetadata;
this.maxFrames = options.GeneralOptions.MaxFrames;
this.memoryAllocator = this.configuration.MemoryAllocator;
}
/// <inheritdoc/>
public WebpDecoderOptions Options { get; }
/// <inheritdoc/>
public Size Dimensions => new((int)this.webImageInfo.Width, (int)this.webImageInfo.Height);
/// <inheritdoc />
public Image<TPixel> Decode<TPixel>(BufferedReadStream stream, CancellationToken cancellationToken)
@ -96,7 +98,7 @@ namespace SixLabors.ImageSharp.Formats.Webp
Image<TPixel> image = null;
try
{
this.Metadata = new ImageMetadata();
this.metadata = new ImageMetadata();
this.currentStream = stream;
uint fileSize = this.ReadImageHeader();
@ -105,7 +107,7 @@ namespace SixLabors.ImageSharp.Formats.Webp
{
if (this.webImageInfo.Features is { Animation: true })
{
using var animationDecoder = new WebpAnimationDecoder(this.memoryAllocator, this.Configuration, this.DecodingMode);
using var animationDecoder = new WebpAnimationDecoder(this.memoryAllocator, this.configuration, this.maxFrames);
return animationDecoder.Decode<TPixel>(stream, this.webImageInfo.Features, this.webImageInfo.Width, this.webImageInfo.Height, fileSize);
}
@ -114,17 +116,17 @@ namespace SixLabors.ImageSharp.Formats.Webp
WebpThrowHelper.ThrowNotSupportedException("Animations are not supported");
}
image = new Image<TPixel>(this.Configuration, (int)this.webImageInfo.Width, (int)this.webImageInfo.Height, this.Metadata);
image = new Image<TPixel>(this.configuration, (int)this.webImageInfo.Width, (int)this.webImageInfo.Height, this.metadata);
Buffer2D<TPixel> pixels = image.GetRootFramePixelBuffer();
if (this.webImageInfo.IsLossless)
{
var losslessDecoder = new WebpLosslessDecoder(this.webImageInfo.Vp8LBitReader, this.memoryAllocator, this.Configuration);
var losslessDecoder = new WebpLosslessDecoder(this.webImageInfo.Vp8LBitReader, this.memoryAllocator, this.configuration);
losslessDecoder.Decode(pixels, image.Width, image.Height);
}
else
{
var lossyDecoder = new WebpLossyDecoder(this.webImageInfo.Vp8BitReader, this.memoryAllocator, this.Configuration);
lossyDecoder.Decode(pixels, image.Width, image.Height, this.webImageInfo, this.AlphaData);
var lossyDecoder = new WebpLossyDecoder(this.webImageInfo.Vp8BitReader, this.memoryAllocator, this.configuration);
lossyDecoder.Decode(pixels, image.Width, image.Height, this.webImageInfo, this.alphaData);
}
// There can be optional chunks after the image data, like EXIF and XMP.
@ -151,7 +153,7 @@ namespace SixLabors.ImageSharp.Formats.Webp
this.ReadImageHeader();
using (this.webImageInfo = this.ReadVp8Info(true))
{
return new ImageInfo(new PixelTypeInfo((int)this.webImageInfo.BitsPerPixel), (int)this.webImageInfo.Width, (int)this.webImageInfo.Height, this.Metadata);
return new ImageInfo(new PixelTypeInfo((int)this.webImageInfo.BitsPerPixel), (int)this.webImageInfo.Width, (int)this.webImageInfo.Height, this.metadata);
}
}
@ -182,8 +184,8 @@ namespace SixLabors.ImageSharp.Formats.Webp
/// <returns>Information about the webp image.</returns>
private WebpImageInfo ReadVp8Info(bool ignoreAlpha = false)
{
this.Metadata = new ImageMetadata();
this.webpMetadata = this.Metadata.GetFormatMetadata(WebpFormat.Instance);
this.metadata = new ImageMetadata();
this.webpMetadata = this.metadata.GetFormatMetadata(WebpFormat.Instance);
WebpChunkType chunkType = WebpChunkParsingUtils.ReadChunkType(this.currentStream, this.buffer);
@ -277,7 +279,7 @@ namespace SixLabors.ImageSharp.Formats.Webp
/// <param name="features">The webp features.</param>
private void ParseOptionalChunks(WebpFeatures features)
{
if (this.IgnoreMetadata || (features.ExifProfile == false && features.XmpMetaData == false))
if (this.skipMetadata || (features.ExifProfile == false && features.XmpMetaData == false))
{
return;
}
@ -287,11 +289,11 @@ namespace SixLabors.ImageSharp.Formats.Webp
{
// Read chunk header.
WebpChunkType chunkType = this.ReadChunkType();
if (chunkType == WebpChunkType.Exif && this.Metadata.ExifProfile == null)
if (chunkType == WebpChunkType.Exif && this.metadata.ExifProfile == null)
{
this.ReadExifProfile();
}
else if (chunkType == WebpChunkType.Xmp && this.Metadata.XmpProfile == null)
else if (chunkType == WebpChunkType.Xmp && this.metadata.XmpProfile == null)
{
this.ReadXmpProfile();
}
@ -310,7 +312,7 @@ namespace SixLabors.ImageSharp.Formats.Webp
private void ReadExifProfile()
{
uint exifChunkSize = this.ReadChunkSize();
if (this.IgnoreMetadata)
if (this.skipMetadata)
{
this.currentStream.Skip((int)exifChunkSize);
}
@ -325,7 +327,7 @@ namespace SixLabors.ImageSharp.Formats.Webp
}
var profile = new ExifProfile(exifData);
this.Metadata.ExifProfile = profile;
this.metadata.ExifProfile = profile;
}
}
@ -335,7 +337,7 @@ namespace SixLabors.ImageSharp.Formats.Webp
private void ReadXmpProfile()
{
uint xmpChunkSize = this.ReadChunkSize();
if (this.IgnoreMetadata)
if (this.skipMetadata)
{
this.currentStream.Skip((int)xmpChunkSize);
}
@ -350,7 +352,7 @@ namespace SixLabors.ImageSharp.Formats.Webp
}
var profile = new XmpProfile(xmpData);
this.Metadata.XmpProfile = profile;
this.metadata.XmpProfile = profile;
}
}
@ -360,7 +362,7 @@ namespace SixLabors.ImageSharp.Formats.Webp
private void ReadIccProfile()
{
uint iccpChunkSize = this.ReadChunkSize();
if (this.IgnoreMetadata)
if (this.skipMetadata)
{
this.currentStream.Skip((int)iccpChunkSize);
}
@ -376,7 +378,7 @@ namespace SixLabors.ImageSharp.Formats.Webp
var profile = new IccProfile(iccpData);
if (profile.CheckIsValid())
{
this.Metadata.IccProfile = profile;
this.metadata.IccProfile = profile;
}
}
}
@ -419,8 +421,8 @@ namespace SixLabors.ImageSharp.Formats.Webp
features.AlphaChunkHeader = (byte)this.currentStream.ReadByte();
int alphaDataSize = (int)(alphaChunkSize - 1);
this.AlphaData = this.memoryAllocator.Allocate<byte>(alphaDataSize);
Span<byte> alphaData = this.AlphaData.GetSpan();
this.alphaData = this.memoryAllocator.Allocate<byte>(alphaDataSize);
Span<byte> alphaData = this.alphaData.GetSpan();
int bytesRead = this.currentStream.Read(alphaData, 0, alphaDataSize);
if (bytesRead != alphaDataSize)
{
@ -462,6 +464,6 @@ namespace SixLabors.ImageSharp.Formats.Webp
}
/// <inheritdoc/>
public void Dispose() => this.AlphaData?.Dispose();
public void Dispose() => this.alphaData?.Dispose();
}
}

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

@ -0,0 +1,14 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
namespace SixLabors.ImageSharp.Formats.Webp
{
/// <summary>
/// Configuration options for decoding Webp images.
/// </summary>
public sealed class WebpDecoderOptions : ISpecializedDecoderOptions
{
/// <inheritdoc/>
public DecoderOptions GeneralOptions { get; set; } = new();
}
}
Loading…
Cancel
Save