diff --git a/src/ImageSharp/Formats/Png/Zlib/Deflater.cs b/src/ImageSharp/Formats/Png/Zlib/Deflater.cs index ef1d0e116..d1560eb4b 100644 --- a/src/ImageSharp/Formats/Png/Zlib/Deflater.cs +++ b/src/ImageSharp/Formats/Png/Zlib/Deflater.cs @@ -50,7 +50,6 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib /// private int state; - private DeflaterPendingBuffer pending; private DeflaterEngine engine; private bool isDisposed; @@ -80,10 +79,8 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib throw new ArgumentOutOfRangeException(nameof(level)); } - this.pending = new DeflaterPendingBuffer(memoryAllocator); - // TODO: Possibly provide DeflateStrategy as an option. - this.engine = new DeflaterEngine(memoryAllocator, this.pending, DeflateStrategy.Default); + this.engine = new DeflaterEngine(memoryAllocator, DeflateStrategy.Default); this.SetLevel(level); this.Reset(); @@ -126,7 +123,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib /// Gets a value indicating whetherthe stream was finished and no more output bytes /// are available. /// - public bool IsFinished => (this.state == FinishedState) && this.pending.IsFlushed; + public bool IsFinished => (this.state == FinishedState) && this.engine.Pending.IsFlushed; /// /// Gets a value indicating whether the input buffer is empty. @@ -145,7 +142,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib public void Reset() { this.state = BusyState; - this.pending.Reset(); + this.engine.Pending.Reset(); this.engine.Reset(); } @@ -236,7 +233,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib while (true) { - int count = this.pending.Flush(output, offset, length); + int count = this.engine.Pending.Flush(output, offset, length); offset += count; length -= count; @@ -259,11 +256,11 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib // We have to supply some lookahead. 8 bit lookahead // is needed by the zlib inflater, and we must fill // the next byte, so that all bits are flushed. - int neededbits = 8 + ((-this.pending.BitCount) & 7); + int neededbits = 8 + ((-this.engine.Pending.BitCount) & 7); while (neededbits > 0) { // Write a static tree block consisting solely of an EOF: - this.pending.WriteBits(2, 10); + this.engine.Pending.WriteBits(2, 10); neededbits -= 10; } } @@ -272,7 +269,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib break; case FinishingState: - this.pending.AlignToByte(); + this.engine.Pending.AlignToByte(); this.state = FinishedState; break; } @@ -296,10 +293,8 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib if (disposing) { this.engine.Dispose(); - this.pending.Dispose(); } - this.pending = null; this.engine = null; this.isDisposed = true; } diff --git a/src/ImageSharp/Formats/Png/Zlib/DeflaterEngine.cs b/src/ImageSharp/Formats/Png/Zlib/DeflaterEngine.cs index b14682501..8f57f51f9 100644 --- a/src/ImageSharp/Formats/Png/Zlib/DeflaterEngine.cs +++ b/src/ImageSharp/Formats/Png/Zlib/DeflaterEngine.cs @@ -100,7 +100,6 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib private int inputEnd; private readonly DeflateStrategy strategy; - private readonly DeflaterPendingBuffer pending; private DeflaterHuffman huffman; private bool isDisposed; @@ -145,12 +144,11 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib /// Initializes a new instance of the class. /// /// The memory allocator to use for buffer allocations. - /// The pending buffer to use. /// The deflate strategy to use. - public DeflaterEngine(MemoryAllocator memoryAllocator, DeflaterPendingBuffer pending, DeflateStrategy strategy) + public DeflaterEngine(MemoryAllocator memoryAllocator, DeflateStrategy strategy) { - this.pending = pending; - this.huffman = new DeflaterHuffman(pending); + this.huffman = new DeflaterHuffman(memoryAllocator); + this.Pending = this.huffman.Pending; this.strategy = strategy; // Create pinned pointers to the various buffers to allow indexing @@ -175,6 +173,11 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib this.blockStart = this.strstart = 1; } + /// + /// Gets the pending buffer to use. + /// + public DeflaterPendingBuffer Pending { get; } + /// /// Deflate drives actual compression of data /// @@ -208,7 +211,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib break; } } - while (this.pending.IsFlushed && progress); // repeat while we have no pending output and progress was made + while (this.Pending.IsFlushed && progress); // repeat while we have no pending output and progress was made return progress; } @@ -834,6 +837,8 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib { if (disposing) { + this.huffman.Dispose(); + this.windowBufferHandle.Dispose(); this.windowBuffer.Dispose(); @@ -844,6 +849,8 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib this.prevBuffer.Dispose(); } + this.huffman = null; + this.isDisposed = true; } } diff --git a/src/ImageSharp/Formats/Png/Zlib/DeflaterHuffman.cs b/src/ImageSharp/Formats/Png/Zlib/DeflaterHuffman.cs index bc7ad7a38..1a2d661c1 100644 --- a/src/ImageSharp/Formats/Png/Zlib/DeflaterHuffman.cs +++ b/src/ImageSharp/Formats/Png/Zlib/DeflaterHuffman.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Text; +using SixLabors.Memory; namespace SixLabors.ImageSharp.Formats.Png.Zlib { @@ -15,7 +16,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib /// /// author of the original java version : Jochen Hoenicke /// - public class DeflaterHuffman + public sealed class DeflaterHuffman : IDisposable { private const int BufferSize = 1 << (DeflaterConstants.DEFAULT_MEM_LEVEL + 6); @@ -60,6 +61,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib private byte[] literalBuffer; private int lastLiteral; private int extraBits; + private bool isDisposed; static DeflaterHuffman() { @@ -106,10 +108,10 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib /// /// Initializes a new instance of the class. /// - /// Pending buffer to use - public DeflaterHuffman(DeflaterPendingBuffer pending) + /// The memory allocator to use for buffer allocations. + public DeflaterHuffman(MemoryAllocator memoryAllocator) { - this.Pending = pending; + this.Pending = new DeflaterPendingBuffer(memoryAllocator); this.literalTree = new Tree(this, LiteralNumber, 257, 15); this.distTree = new Tree(this, DistanceNumber, 1, 15); @@ -122,7 +124,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib /// /// Gets the pending buffer to use. /// - public DeflaterPendingBuffer Pending { get; } + public DeflaterPendingBuffer Pending { get; private set; } /// /// Reset internal state @@ -351,6 +353,13 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib Bit4Reverse[toReverse >> 12]); } + /// + public void Dispose() + { + this.Dispose(true); + GC.SuppressFinalize(this); + } + private static int Lcode(int length) { if (length == 255) @@ -380,6 +389,20 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib return code + distance; } + private void Dispose(bool disposing) + { + if (!this.isDisposed) + { + if (disposing) + { + this.Pending.Dispose(); + } + + this.Pending = null; + this.isDisposed = true; + } + } + private class Tree { private readonly int minNumCodes;