diff --git a/.gitattributes b/.gitattributes index 2fdea90e17..ff4ec94087 100644 --- a/.gitattributes +++ b/.gitattributes @@ -64,18 +64,19 @@ # Set explicit file behavior to: # treat as text # normalize to Unix-style line endings and -# use a union merge when resoling conflicts +# use a union merge when resolving conflicts ############################################################################### *.csproj text eol=lf merge=union *.dbproj text eol=lf merge=union *.fsproj text eol=lf merge=union *.ncrunchproject text eol=lf merge=union *.vbproj text eol=lf merge=union +*.shproj text eol=lf merge=union ############################################################################### # Set explicit file behavior to: # treat as text # normalize to Windows-style line endings and -# use a union merge when resoling conflicts +# use a union merge when resolving conflicts ############################################################################### *.sln text eol=crlf merge=union ############################################################################### diff --git a/src/ImageSharp/Formats/Webp/AlphaDecoder.cs b/src/ImageSharp/Formats/Webp/AlphaDecoder.cs index 4a7b505363..8875ae1150 100644 --- a/src/ImageSharp/Formats/Webp/AlphaDecoder.cs +++ b/src/ImageSharp/Formats/Webp/AlphaDecoder.cs @@ -38,7 +38,7 @@ internal class AlphaDecoder : IDisposable this.LastRow = 0; int totalPixels = width * height; - var compression = (WebpAlphaCompressionMethod)(alphaChunkHeader & 0x03); + WebpAlphaCompressionMethod compression = (WebpAlphaCompressionMethod)(alphaChunkHeader & 0x03); if (compression is not WebpAlphaCompressionMethod.NoCompression and not WebpAlphaCompressionMethod.WebpLosslessCompression) { WebpThrowHelper.ThrowImageFormatException($"unexpected alpha compression method {compression} found"); @@ -59,7 +59,7 @@ internal class AlphaDecoder : IDisposable if (this.Compressed) { - var bitReader = new Vp8LBitReader(data); + Vp8LBitReader bitReader = new(data); this.LosslessDecoder = new WebpLosslessDecoder(bitReader, memoryAllocator, configuration); this.LosslessDecoder.DecodeImageStream(this.Vp8LDec, width, height, true); @@ -174,17 +174,14 @@ internal class AlphaDecoder : IDisposable dst = dst[this.Width..]; } } + else if (this.Use8BDecode) + { + this.LosslessDecoder.DecodeAlphaData(this); + } else { - if (this.Use8BDecode) - { - this.LosslessDecoder.DecodeAlphaData(this); - } - else - { - this.LosslessDecoder.DecodeImageData(this.Vp8LDec, this.Vp8LDec.Pixels.Memory.Span); - this.ExtractAlphaRows(this.Vp8LDec); - } + this.LosslessDecoder.DecodeImageData(this.Vp8LDec, this.Vp8LDec.Pixels.Memory.Span); + this.ExtractAlphaRows(this.Vp8LDec); } } @@ -262,8 +259,7 @@ internal class AlphaDecoder : IDisposable { int numRowsToProcess = dec.Height; int width = dec.Width; - Span pixels = dec.Pixels.Memory.Span; - Span input = pixels; + Span input = dec.Pixels.Memory.Span; Span output = this.Alpha.Memory.Span; // Extract alpha (which is stored in the green plane). @@ -328,7 +324,7 @@ internal class AlphaDecoder : IDisposable ref byte srcRef = ref MemoryMarshal.GetReference(input); for (i = 1; i + 8 <= width; i += 8) { - var a0 = Vector128.Create(Unsafe.As(ref Unsafe.Add(ref srcRef, i)), 0); + Vector128 a0 = Vector128.Create(Unsafe.As(ref Unsafe.Add(ref srcRef, i)), 0); Vector128 a1 = Sse2.Add(a0.AsByte(), last.AsByte()); Vector128 a2 = Sse2.ShiftLeftLogical128BitLane(a1, 1); Vector128 a3 = Sse2.Add(a1, a2); @@ -366,32 +362,29 @@ internal class AlphaDecoder : IDisposable { HorizontalUnfilter(null, input, dst, width); } - else + else if (Avx2.IsSupported) { - if (Avx2.IsSupported) + nint i; + int maxPos = width & ~31; + for (i = 0; i < maxPos; i += 32) { - nint i; - int maxPos = width & ~31; - for (i = 0; i < maxPos; i += 32) - { - Vector256 a0 = Unsafe.As>(ref Unsafe.Add(ref MemoryMarshal.GetReference(input), i)); - Vector256 b0 = Unsafe.As>(ref Unsafe.Add(ref MemoryMarshal.GetReference(prev), i)); - Vector256 c0 = Avx2.Add(a0.AsByte(), b0.AsByte()); - ref byte outputRef = ref Unsafe.Add(ref MemoryMarshal.GetReference(dst), i); - Unsafe.As>(ref outputRef) = c0; - } + Vector256 a0 = Unsafe.As>(ref Unsafe.Add(ref MemoryMarshal.GetReference(input), i)); + Vector256 b0 = Unsafe.As>(ref Unsafe.Add(ref MemoryMarshal.GetReference(prev), i)); + Vector256 c0 = Avx2.Add(a0.AsByte(), b0.AsByte()); + ref byte outputRef = ref Unsafe.Add(ref MemoryMarshal.GetReference(dst), i); + Unsafe.As>(ref outputRef) = c0; + } - for (; i < width; i++) - { - dst[(int)i] = (byte)(prev[(int)i] + input[(int)i]); - } + for (; i < width; i++) + { + dst[(int)i] = (byte)(prev[(int)i] + input[(int)i]); } - else + } + else + { + for (int i = 0; i < width; i++) { - for (int i = 0; i < width; i++) - { - dst[i] = (byte)(prev[i] + input[i]); - } + dst[i] = (byte)(prev[i] + input[i]); } } } diff --git a/src/ImageSharp/Formats/Webp/AlphaEncoder.cs b/src/ImageSharp/Formats/Webp/AlphaEncoder.cs index dd21365bc3..596715b205 100644 --- a/src/ImageSharp/Formats/Webp/AlphaEncoder.cs +++ b/src/ImageSharp/Formats/Webp/AlphaEncoder.cs @@ -12,10 +12,8 @@ namespace SixLabors.ImageSharp.Formats.Webp; /// /// Methods for encoding the alpha data of a VP8 image. /// -internal class AlphaEncoder : IDisposable +internal static class AlphaEncoder { - private IMemoryOwner? alphaData; - /// /// Encodes the alpha channel data. /// Data is either compressed as lossless webp image or uncompressed. @@ -28,12 +26,18 @@ internal class AlphaEncoder : IDisposable /// 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 IMemoryOwner EncodeAlpha(Image image, Configuration configuration, MemoryAllocator memoryAllocator, bool skipMetadata, bool compress, out int size) + public static IMemoryOwner EncodeAlpha( + Image image, + Configuration configuration, + MemoryAllocator memoryAllocator, + bool skipMetadata, + bool compress, + out int size) where TPixel : unmanaged, IPixel { int width = image.Width; int height = image.Height; - this.alphaData = ExtractAlphaChannel(image, configuration, memoryAllocator); + IMemoryOwner alphaData = ExtractAlphaChannel(image, configuration, memoryAllocator); if (compress) { @@ -54,15 +58,15 @@ internal class AlphaEncoder : IDisposable // 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, this.alphaData.GetSpan()); + using Image alphaAsImage = DispatchAlphaToGreen(image, alphaData.GetSpan()); - size = lossLessEncoder.EncodeAlphaImageData(alphaAsImage, this.alphaData); + size = lossLessEncoder.EncodeAlphaImageData(alphaAsImage, alphaData); - return this.alphaData; + return alphaData; } size = width * height; - return this.alphaData; + return alphaData; } /// @@ -127,7 +131,4 @@ internal class AlphaEncoder : IDisposable return alphaDataBuffer; } - - /// - public void Dispose() => this.alphaData?.Dispose(); } diff --git a/src/ImageSharp/Formats/Webp/BitReader/BitReaderBase.cs b/src/ImageSharp/Formats/Webp/BitReader/BitReaderBase.cs index 37997d3e29..83f9e797ab 100644 --- a/src/ImageSharp/Formats/Webp/BitReader/BitReaderBase.cs +++ b/src/ImageSharp/Formats/Webp/BitReader/BitReaderBase.cs @@ -13,14 +13,16 @@ internal abstract class BitReaderBase : IDisposable { private bool isDisposed; - protected BitReaderBase(IMemoryOwner data) => this.Data = data; + protected BitReaderBase(IMemoryOwner data) + => this.Data = data; - protected BitReaderBase(Stream inputStream, int imageDataSize, MemoryAllocator memoryAllocator) => this.Data = ReadImageDataFromStream(inputStream, imageDataSize, memoryAllocator); + protected BitReaderBase(Stream inputStream, int imageDataSize, MemoryAllocator memoryAllocator) + => this.Data = ReadImageDataFromStream(inputStream, imageDataSize, memoryAllocator); /// - /// Gets or sets the raw encoded image data. + /// Gets the raw encoded image data. /// - public IMemoryOwner Data { get; set; } + public IMemoryOwner Data { get; } /// /// Copies the raw encoded image data from the stream into a byte array. diff --git a/src/ImageSharp/Formats/Webp/Lossless/ColorCache.cs b/src/ImageSharp/Formats/Webp/Lossless/ColorCache.cs index 7e1c4e2fe1..e683fb5605 100644 --- a/src/ImageSharp/Formats/Webp/Lossless/ColorCache.cs +++ b/src/ImageSharp/Formats/Webp/Lossless/ColorCache.cs @@ -1,7 +1,6 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; namespace SixLabors.ImageSharp.Formats.Webp.Lossless; @@ -28,17 +27,17 @@ internal class ColorCache /// /// Gets the color entries. /// - public uint[] Colors { get; private set; } + public uint[] Colors { get; } /// /// Gets the hash shift: 32 - hashBits. /// - public int HashShift { get; private set; } + public int HashShift { get; } /// /// Gets the hash bits. /// - public int HashBits { get; private set; } + public int HashBits { get; } /// /// Inserts a new color into the cache. diff --git a/src/ImageSharp/Formats/Webp/Lossy/Vp8Encoder.cs b/src/ImageSharp/Formats/Webp/Lossy/Vp8Encoder.cs index a5d1900b2a..16b4c827ef 100644 --- a/src/ImageSharp/Formats/Webp/Lossy/Vp8Encoder.cs +++ b/src/ImageSharp/Formats/Webp/Lossy/Vp8Encoder.cs @@ -348,12 +348,18 @@ internal class Vp8Encoder : IDisposable // Extract and encode alpha channel data, if present. int alphaDataSize = 0; bool alphaCompressionSucceeded = false; - using AlphaEncoder alphaEncoder = new(); Span alphaData = Span.Empty; if (hasAlpha) { // TODO: This can potentially run in an separate task. - IMemoryOwner encodedAlphaData = alphaEncoder.EncodeAlpha(image, this.configuration, this.memoryAllocator, this.skipMetadata, this.alphaCompression, out alphaDataSize); + using IMemoryOwner encodedAlphaData = AlphaEncoder.EncodeAlpha( + image, + this.configuration, + this.memoryAllocator, + this.skipMetadata, + this.alphaCompression, + out alphaDataSize); + alphaData = encodedAlphaData.GetSpan(); if (alphaDataSize < pixelCount) { diff --git a/src/ImageSharp/Formats/Webp/WebpDecoderCore.cs b/src/ImageSharp/Formats/Webp/WebpDecoderCore.cs index 83298237dd..181f01632f 100644 --- a/src/ImageSharp/Formats/Webp/WebpDecoderCore.cs +++ b/src/ImageSharp/Formats/Webp/WebpDecoderCore.cs @@ -8,9 +8,7 @@ using SixLabors.ImageSharp.Formats.Webp.Lossy; using SixLabors.ImageSharp.IO; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.Metadata; -using SixLabors.ImageSharp.Metadata.Profiles.Exif; using SixLabors.ImageSharp.Metadata.Profiles.Icc; -using SixLabors.ImageSharp.Metadata.Profiles.Xmp; using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp.Formats.Webp; @@ -40,11 +38,6 @@ internal sealed class WebpDecoderCore : IImageDecoderInternals, IDisposable /// private readonly uint maxFrames; - /// - /// Gets the decoded by this decoder instance. - /// - private ImageMetadata? metadata; - /// /// Gets or sets the alpha data, if an ALPH chunk is present. /// @@ -55,11 +48,6 @@ internal sealed class WebpDecoderCore : IImageDecoderInternals, IDisposable /// private readonly MemoryAllocator memoryAllocator; - /// - /// The webp specific metadata. - /// - private WebpMetadata? webpMetadata; - /// /// Information about the webp image. /// @@ -91,15 +79,15 @@ internal sealed class WebpDecoderCore : IImageDecoderInternals, IDisposable Image? image = null; try { - this.metadata = new ImageMetadata(); + ImageMetadata metadata = new(); uint fileSize = this.ReadImageHeader(stream); - using (this.webImageInfo = this.ReadVp8Info(stream)) + using (this.webImageInfo = this.ReadVp8Info(stream, metadata)) { if (this.webImageInfo.Features is { Animation: true }) { - using var animationDecoder = new WebpAnimationDecoder(this.memoryAllocator, this.configuration, this.maxFrames); + using WebpAnimationDecoder animationDecoder = new(this.memoryAllocator, this.configuration, this.maxFrames); return animationDecoder.Decode(stream, this.webImageInfo.Features, this.webImageInfo.Width, this.webImageInfo.Height, fileSize); } @@ -108,23 +96,23 @@ internal sealed class WebpDecoderCore : IImageDecoderInternals, IDisposable WebpThrowHelper.ThrowNotSupportedException("Animations are not supported"); } - image = new Image(this.configuration, (int)this.webImageInfo.Width, (int)this.webImageInfo.Height, this.metadata); + image = new Image(this.configuration, (int)this.webImageInfo.Width, (int)this.webImageInfo.Height, metadata); Buffer2D pixels = image.GetRootFramePixelBuffer(); if (this.webImageInfo.IsLossless) { - var losslessDecoder = new WebpLosslessDecoder(this.webImageInfo.Vp8LBitReader, this.memoryAllocator, this.configuration); + WebpLosslessDecoder losslessDecoder = new(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); + WebpLossyDecoder lossyDecoder = new(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. if (this.webImageInfo.Features != null) { - this.ParseOptionalChunks(stream, this.webImageInfo.Features); + this.ParseOptionalChunks(stream, metadata, this.webImageInfo.Features); } return image; @@ -141,9 +129,11 @@ internal sealed class WebpDecoderCore : IImageDecoderInternals, IDisposable public ImageInfo Identify(BufferedReadStream stream, CancellationToken cancellationToken) { this.ReadImageHeader(stream); - using (this.webImageInfo = this.ReadVp8Info(stream, true)) + + ImageMetadata metadata = new(); + using (this.webImageInfo = this.ReadVp8Info(stream, metadata, 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, metadata); } } @@ -172,23 +162,23 @@ internal sealed class WebpDecoderCore : IImageDecoderInternals, IDisposable /// Reads information present in the image header, about the image content and how to decode the image. /// /// The stream to decode from. + /// The image metadata. /// For identify, the alpha data should not be read. /// Information about the webp image. - private WebpImageInfo ReadVp8Info(BufferedReadStream stream, bool ignoreAlpha = false) + private WebpImageInfo ReadVp8Info(BufferedReadStream stream, ImageMetadata metadata, bool ignoreAlpha = false) { - this.metadata = new ImageMetadata(); - this.webpMetadata = this.metadata.GetFormatMetadata(WebpFormat.Instance); + WebpMetadata webpMetadata = metadata.GetFormatMetadata(WebpFormat.Instance); WebpChunkType chunkType = WebpChunkParsingUtils.ReadChunkType(stream, this.buffer); - var features = new WebpFeatures(); + WebpFeatures features = new(); switch (chunkType) { case WebpChunkType.Vp8: - this.webpMetadata.FileFormat = WebpFileFormatType.Lossy; + webpMetadata.FileFormat = WebpFileFormatType.Lossy; return WebpChunkParsingUtils.ReadVp8Header(this.memoryAllocator, stream, this.buffer, features); case WebpChunkType.Vp8L: - this.webpMetadata.FileFormat = WebpFileFormatType.Lossless; + webpMetadata.FileFormat = WebpFileFormatType.Lossless; return WebpChunkParsingUtils.ReadVp8LHeader(this.memoryAllocator, stream, this.buffer, features); case WebpChunkType.Vp8X: WebpImageInfo webpInfos = WebpChunkParsingUtils.ReadVp8XHeader(stream, this.buffer, features); @@ -197,17 +187,17 @@ internal sealed class WebpDecoderCore : IImageDecoderInternals, IDisposable chunkType = WebpChunkParsingUtils.ReadChunkType(stream, this.buffer); if (chunkType == WebpChunkType.Vp8) { - this.webpMetadata.FileFormat = WebpFileFormatType.Lossy; + webpMetadata.FileFormat = WebpFileFormatType.Lossy; webpInfos = WebpChunkParsingUtils.ReadVp8Header(this.memoryAllocator, stream, this.buffer, features); } else if (chunkType == WebpChunkType.Vp8L) { - this.webpMetadata.FileFormat = WebpFileFormatType.Lossless; + webpMetadata.FileFormat = WebpFileFormatType.Lossless; webpInfos = WebpChunkParsingUtils.ReadVp8LHeader(this.memoryAllocator, stream, this.buffer, features); } else if (WebpChunkParsingUtils.IsOptionalVp8XChunk(chunkType)) { - bool isAnimationChunk = this.ParseOptionalExtendedChunks(stream, chunkType, features, ignoreAlpha); + bool isAnimationChunk = this.ParseOptionalExtendedChunks(stream, metadata, chunkType, features, ignoreAlpha); if (isAnimationChunk) { return webpInfos; @@ -233,24 +223,30 @@ internal sealed class WebpDecoderCore : IImageDecoderInternals, IDisposable /// Parses optional VP8X chunks, which can be ICCP, XMP, ANIM or ALPH chunks. /// /// The stream to decode from. + /// The image metadata. /// The chunk type. /// The webp image features. /// For identify, the alpha data should not be read. /// true, if its a alpha chunk. - private bool ParseOptionalExtendedChunks(BufferedReadStream stream, WebpChunkType chunkType, WebpFeatures features, bool ignoreAlpha) + private bool ParseOptionalExtendedChunks( + BufferedReadStream stream, + ImageMetadata metadata, + WebpChunkType chunkType, + WebpFeatures features, + bool ignoreAlpha) { switch (chunkType) { case WebpChunkType.Iccp: - this.ReadIccProfile(stream); + this.ReadIccProfile(stream, metadata); break; case WebpChunkType.Exif: - this.ReadExifProfile(stream); + this.ReadExifProfile(stream, metadata); break; case WebpChunkType.Xmp: - this.ReadXmpProfile(stream); + this.ReadXmpProfile(stream, metadata); break; case WebpChunkType.AnimationParameter: @@ -272,8 +268,9 @@ internal sealed class WebpDecoderCore : IImageDecoderInternals, IDisposable /// Reads the optional metadata EXIF of XMP profiles, which can follow the image data. /// /// The stream to decode from. + /// The image metadata. /// The webp features. - private void ParseOptionalChunks(BufferedReadStream stream, WebpFeatures features) + private void ParseOptionalChunks(BufferedReadStream stream, ImageMetadata metadata, WebpFeatures features) { if (this.skipMetadata || (!features.ExifProfile && !features.XmpMetaData)) { @@ -285,13 +282,13 @@ internal sealed class WebpDecoderCore : IImageDecoderInternals, IDisposable { // Read chunk header. WebpChunkType chunkType = this.ReadChunkType(stream); - if (chunkType == WebpChunkType.Exif && this.metadata!.ExifProfile == null) + if (chunkType == WebpChunkType.Exif && metadata.ExifProfile == null) { - this.ReadExifProfile(stream); + this.ReadExifProfile(stream, metadata); } - else if (chunkType == WebpChunkType.Xmp && this.metadata!.XmpProfile == null) + else if (chunkType == WebpChunkType.Xmp && metadata.XmpProfile == null) { - this.ReadXmpProfile(stream); + this.ReadXmpProfile(stream, metadata); } else { @@ -306,7 +303,8 @@ internal sealed class WebpDecoderCore : IImageDecoderInternals, IDisposable /// Reads the EXIF profile from the stream. /// /// The stream to decode from. - private void ReadExifProfile(BufferedReadStream stream) + /// The image metadata. + private void ReadExifProfile(BufferedReadStream stream, ImageMetadata metadata) { uint exifChunkSize = this.ReadChunkSize(stream); if (this.skipMetadata) @@ -323,8 +321,7 @@ internal sealed class WebpDecoderCore : IImageDecoderInternals, IDisposable return; } - var profile = new ExifProfile(exifData); - this.metadata!.ExifProfile = profile; + metadata.ExifProfile = new(exifData); } } @@ -332,7 +329,8 @@ internal sealed class WebpDecoderCore : IImageDecoderInternals, IDisposable /// Reads the XMP profile the stream. /// /// The stream to decode from. - private void ReadXmpProfile(BufferedReadStream stream) + /// The image metadata. + private void ReadXmpProfile(BufferedReadStream stream, ImageMetadata metadata) { uint xmpChunkSize = this.ReadChunkSize(stream); if (this.skipMetadata) @@ -349,8 +347,7 @@ internal sealed class WebpDecoderCore : IImageDecoderInternals, IDisposable return; } - var profile = new XmpProfile(xmpData); - this.metadata!.XmpProfile = profile; + metadata.XmpProfile = new(xmpData); } } @@ -358,7 +355,8 @@ internal sealed class WebpDecoderCore : IImageDecoderInternals, IDisposable /// Reads the ICCP chunk from the stream. /// /// The stream to decode from. - private void ReadIccProfile(BufferedReadStream stream) + /// The image metadata. + private void ReadIccProfile(BufferedReadStream stream, ImageMetadata metadata) { uint iccpChunkSize = this.ReadChunkSize(stream); if (this.skipMetadata) @@ -374,10 +372,10 @@ internal sealed class WebpDecoderCore : IImageDecoderInternals, IDisposable WebpThrowHelper.ThrowInvalidImageContentException("Not enough data to read the iccp chunk"); } - var profile = new IccProfile(iccpData); + IccProfile profile = new(iccpData); if (profile.CheckIsValid()) { - this.metadata!.IccProfile = profile; + metadata.IccProfile = profile; } } } @@ -442,8 +440,7 @@ internal sealed class WebpDecoderCore : IImageDecoderInternals, IDisposable { if (stream.Read(this.buffer, 0, 4) == 4) { - var chunkType = (WebpChunkType)BinaryPrimitives.ReadUInt32BigEndian(this.buffer); - return chunkType; + return (WebpChunkType)BinaryPrimitives.ReadUInt32BigEndian(this.buffer); } throw new ImageFormatException("Invalid Webp data."); @@ -455,6 +452,7 @@ internal sealed class WebpDecoderCore : IImageDecoderInternals, IDisposable /// /// The stream to decode from. /// The chunk size in bytes. + /// Invalid data. private uint ReadChunkSize(BufferedReadStream stream) { if (stream.Read(this.buffer, 0, 4) == 4) diff --git a/src/ImageSharp/Formats/Webp/WebpEncoder.cs b/src/ImageSharp/Formats/Webp/WebpEncoder.cs index e314d38017..bd8303f1c8 100644 --- a/src/ImageSharp/Formats/Webp/WebpEncoder.cs +++ b/src/ImageSharp/Formats/Webp/WebpEncoder.cs @@ -82,7 +82,7 @@ public sealed class WebpEncoder : ImageEncoder /// protected override void Encode(Image image, Stream stream, CancellationToken cancellationToken) { - WebpEncoderCore encoder = new(this, image.GetMemoryAllocator()); + WebpEncoderCore encoder = new(this, image.GetConfiguration()); encoder.Encode(image, stream, cancellationToken); } } diff --git a/src/ImageSharp/Formats/Webp/WebpEncoderCore.cs b/src/ImageSharp/Formats/Webp/WebpEncoderCore.cs index 8d707fed92..33189ba845 100644 --- a/src/ImageSharp/Formats/Webp/WebpEncoderCore.cs +++ b/src/ImageSharp/Formats/Webp/WebpEncoderCore.cs @@ -1,7 +1,6 @@ // Copyright (c) Six Labors. // Licensed under the Six Labors Split License. -using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Formats.Webp.Lossless; using SixLabors.ImageSharp.Formats.Webp.Lossy; using SixLabors.ImageSharp.Memory; @@ -80,16 +79,17 @@ internal sealed class WebpEncoderCore : IImageEncoderInternals /// /// The global configuration. /// - private Configuration? configuration; + private readonly Configuration configuration; /// /// Initializes a new instance of the class. /// /// The encoder with options. - /// The memory manager. - public WebpEncoderCore(WebpEncoder encoder, MemoryAllocator memoryAllocator) + /// The global configuration. + public WebpEncoderCore(WebpEncoder encoder, Configuration configuration) { - this.memoryAllocator = memoryAllocator; + this.configuration = configuration; + this.memoryAllocator = configuration.MemoryAllocator; this.alphaCompression = encoder.UseAlphaCompression; this.fileFormat = encoder.FileFormat; this.quality = encoder.Quality; @@ -116,7 +116,6 @@ internal sealed class WebpEncoderCore : IImageEncoderInternals Guard.NotNull(image, nameof(image)); Guard.NotNull(stream, nameof(stream)); - this.configuration = image.GetConfiguration(); bool lossless; if (this.fileFormat is not null) {