diff --git a/src/ImageSharp/Formats/Webp/AlphaEncoder.cs b/src/ImageSharp/Formats/Webp/AlphaEncoder.cs index 38497281ff..1019073d87 100644 --- a/src/ImageSharp/Formats/Webp/AlphaEncoder.cs +++ b/src/ImageSharp/Formats/Webp/AlphaEncoder.cs @@ -13,8 +13,10 @@ namespace SixLabors.ImageSharp.Formats.Webp /// /// Methods for encoding the alpha data of a VP8 image. /// - internal static class AlphaEncoder + internal class AlphaEncoder : IDisposable { + private IMemoryOwner alphaData; + /// /// Encodes the alpha channel data. /// Data is either compressed as lossless webp image or uncompressed. @@ -26,12 +28,12 @@ namespace SixLabors.ImageSharp.Formats.Webp /// Indicates, if the data should be compressed with the lossless webp compression. /// The size in bytes of the alpha data. /// The encoded alpha data. - public static IMemoryOwner EncodeAlpha(Image image, Configuration configuration, MemoryAllocator memoryAllocator, bool compress, out int size) + public IMemoryOwner EncodeAlpha(Image image, Configuration configuration, MemoryAllocator memoryAllocator, bool compress, out int size) where TPixel : unmanaged, IPixel { int width = image.Width; int height = image.Height; - IMemoryOwner alphaData = ExtractAlphaChannel(image, configuration, memoryAllocator); + this.alphaData = ExtractAlphaChannel(image, configuration, memoryAllocator); if (compress) { @@ -51,15 +53,15 @@ namespace SixLabors.ImageSharp.Formats.Webp // The transparency information will be stored in the green channel of the ARGB quadruplet. // The green channel is allowed extra transformation steps in the specification -- unlike the other channels, // that can improve compression. - using Image alphaAsImage = DispatchAlphaToGreen(image, alphaData.GetSpan()); + using Image alphaAsImage = DispatchAlphaToGreen(image, this.alphaData.GetSpan()); - size = lossLessEncoder.EncodeAlphaImageData(alphaAsImage, alphaData); + size = lossLessEncoder.EncodeAlphaImageData(alphaAsImage, this.alphaData); - return alphaData; + return this.alphaData; } size = width * height; - return alphaData; + return this.alphaData; } /// @@ -124,5 +126,8 @@ namespace SixLabors.ImageSharp.Formats.Webp return alphaDataBuffer; } + + /// + public void Dispose() => this.alphaData?.Dispose(); } } diff --git a/src/ImageSharp/Formats/Webp/Lossy/Vp8Encoder.cs b/src/ImageSharp/Formats/Webp/Lossy/Vp8Encoder.cs index 60bdee362c..927b04c0cf 100644 --- a/src/ImageSharp/Formats/Webp/Lossy/Vp8Encoder.cs +++ b/src/ImageSharp/Formats/Webp/Lossy/Vp8Encoder.cs @@ -241,11 +241,6 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy public int DqUvDc { get; private set; } - /// - /// Gets or sets the alpha data. - /// - private IMemoryOwner AlphaData { get; set; } - /// /// Gets the luma component. /// @@ -331,10 +326,13 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy // Extract and encode alpha channel data, if present. int alphaDataSize = 0; bool alphaCompressionSucceeded = false; + using var alphaEncoder = new AlphaEncoder(); + Span alphaData = Span.Empty; if (hasAlpha) { // TODO: This can potentially run in an separate task. - this.AlphaData = AlphaEncoder.EncodeAlpha(image, this.configuration, this.memoryAllocator, this.alphaCompression, out alphaDataSize); + IMemoryOwner encodedAlphaData = alphaEncoder.EncodeAlpha(image, this.configuration, this.memoryAllocator, this.alphaCompression, out alphaDataSize); + alphaData = encodedAlphaData.GetSpan(); if (alphaDataSize < pixelCount) { // Only use compressed data, if the compressed data is actually smaller then the uncompressed data. @@ -382,7 +380,7 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy (uint)width, (uint)height, hasAlpha, - hasAlpha ? this.AlphaData.GetSpan().Slice(0, alphaDataSize) : Span.Empty, + alphaData, this.alphaCompression && alphaCompressionSucceeded); } @@ -392,7 +390,6 @@ namespace SixLabors.ImageSharp.Formats.Webp.Lossy this.Y.Dispose(); this.U.Dispose(); this.V.Dispose(); - this.AlphaData?.Dispose(); } ///