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;