Browse Source

Use pinned buffers for distances

pull/1054/head
James Jackson-South 7 years ago
parent
commit
d4155c7365
  1. 7
      src/ImageSharp/Formats/Png/Zlib/DeflateThrowHelper.cs
  2. 205
      src/ImageSharp/Formats/Png/Zlib/DeflaterHuffman.cs
  3. 1
      src/ImageSharp/Formats/Png/Zlib/DeflaterPendingBuffer.cs

7
src/ImageSharp/Formats/Png/Zlib/DeflateThrowHelper.cs

@ -17,6 +17,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
[MethodImpl(InliningOptions.ColdPath)] [MethodImpl(InliningOptions.ColdPath)]
public static void ThrowUnknownCompression() => throw new InvalidOperationException("Unknown compression function."); public static void ThrowUnknownCompression() => throw new InvalidOperationException("Unknown compression function.");
[MethodImpl(InliningOptions.ColdPath)]
public static void ThrowNotProcessed() => throw new InvalidOperationException("Old input was not completely processed."); public static void ThrowNotProcessed() => throw new InvalidOperationException("Old input was not completely processed.");
[MethodImpl(InliningOptions.ColdPath)] [MethodImpl(InliningOptions.ColdPath)]
@ -24,5 +25,11 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
[MethodImpl(InliningOptions.ColdPath)] [MethodImpl(InliningOptions.ColdPath)]
public static void ThrowOutOfRange(string name) => throw new ArgumentOutOfRangeException(name); public static void ThrowOutOfRange(string name) => throw new ArgumentOutOfRangeException(name);
[MethodImpl(InliningOptions.ColdPath)]
public static void ThrowFrequencyNotEmpty() => throw new InvalidOperationException("Huffman frequency entry non empty.");
[MethodImpl(InliningOptions.ColdPath)]
public static void ThrowHeapViolated() => throw new InvalidOperationException("Huffman heap invariant violated.");
} }
} }

205
src/ImageSharp/Formats/Png/Zlib/DeflaterHuffman.cs

@ -2,8 +2,8 @@
// Licensed under the Apache License, Version 2.0. // Licensed under the Apache License, Version 2.0.
using System; using System;
using System.Collections.Generic; using System.Buffers;
using System.Text; using System.Runtime.CompilerServices;
using SixLabors.Memory; using SixLabors.Memory;
namespace SixLabors.ImageSharp.Formats.Png.Zlib namespace SixLabors.ImageSharp.Formats.Png.Zlib
@ -16,7 +16,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
/// ///
/// author of the original java version : Jochen Hoenicke /// author of the original java version : Jochen Hoenicke
/// </summary> /// </summary>
public sealed class DeflaterHuffman : IDisposable public sealed unsafe class DeflaterHuffman : IDisposable
{ {
private const int BufferSize = 1 << (DeflaterConstants.DEFAULT_MEM_LEVEL + 6); private const int BufferSize = 1 << (DeflaterConstants.DEFAULT_MEM_LEVEL + 6);
@ -29,13 +29,13 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
// Number of codes used to transfer bit lengths // Number of codes used to transfer bit lengths
private const int BitLengthNumber = 19; private const int BitLengthNumber = 19;
// repeat previous bit length 3-6 times (2 bits of repeat count) // Repeat previous bit length 3-6 times (2 bits of repeat count)
private const int Repeat3To6 = 16; private const int Repeat3To6 = 16;
// repeat a zero length 3-10 times (3 bits of repeat count) // Repeat a zero length 3-10 times (3 bits of repeat count)
private const int Repeat3To10 = 17; private const int Repeat3To10 = 17;
// repeat a zero length 11-138 times (7 bits of repeat count) // Repeat a zero length 11-138 times (7 bits of repeat count)
private const int Repeat11To138 = 18; private const int Repeat11To138 = 18;
private const int EofSymbol = 256; private const int EofSymbol = 256;
@ -46,19 +46,24 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
private static readonly byte[] Bit4Reverse = { 0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15 }; private static readonly byte[] Bit4Reverse = { 0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15 };
private static short[] staticLCodes; private static readonly short[] StaticLCodes;
private static byte[] staticLLength; private static readonly byte[] StaticLLength;
private static short[] staticDCodes; private static readonly short[] StaticDCodes;
private static byte[] staticDLength; private static readonly byte[] StaticDLength;
private Tree literalTree; private Tree literalTree;
private Tree distTree; private Tree distTree;
private Tree blTree; private Tree blTree;
// Buffer for distances // Buffer for distances
private short[] distanceBuffer; private readonly IMemoryOwner<short> distanceManagedBuffer;
private readonly short* pinnedDistanceBuffer;
private MemoryHandle distanceBufferHandle;
private readonly IMemoryOwner<short> literalManagedBuffer;
private readonly short* pinnedLiteralBuffer;
private MemoryHandle literalBufferHandle;
private byte[] literalBuffer;
private int lastLiteral; private int lastLiteral;
private int extraBits; private int extraBits;
private bool isDisposed; private bool isDisposed;
@ -67,41 +72,41 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
{ {
// See RFC 1951 3.2.6 // See RFC 1951 3.2.6
// Literal codes // Literal codes
staticLCodes = new short[LiteralNumber]; StaticLCodes = new short[LiteralNumber];
staticLLength = new byte[LiteralNumber]; StaticLLength = new byte[LiteralNumber];
int i = 0; int i = 0;
while (i < 144) while (i < 144)
{ {
staticLCodes[i] = BitReverse((0x030 + i) << 8); StaticLCodes[i] = BitReverse((0x030 + i) << 8);
staticLLength[i++] = 8; StaticLLength[i++] = 8;
} }
while (i < 256) while (i < 256)
{ {
staticLCodes[i] = BitReverse((0x190 - 144 + i) << 7); StaticLCodes[i] = BitReverse((0x190 - 144 + i) << 7);
staticLLength[i++] = 9; StaticLLength[i++] = 9;
} }
while (i < 280) while (i < 280)
{ {
staticLCodes[i] = BitReverse((0x000 - 256 + i) << 9); StaticLCodes[i] = BitReverse((0x000 - 256 + i) << 9);
staticLLength[i++] = 7; StaticLLength[i++] = 7;
} }
while (i < LiteralNumber) while (i < LiteralNumber)
{ {
staticLCodes[i] = BitReverse((0x0c0 - 280 + i) << 8); StaticLCodes[i] = BitReverse((0x0c0 - 280 + i) << 8);
staticLLength[i++] = 8; StaticLLength[i++] = 8;
} }
// Distance codes // Distance codes
staticDCodes = new short[DistanceNumber]; StaticDCodes = new short[DistanceNumber];
staticDLength = new byte[DistanceNumber]; StaticDLength = new byte[DistanceNumber];
for (i = 0; i < DistanceNumber; i++) for (i = 0; i < DistanceNumber; i++)
{ {
staticDCodes[i] = BitReverse(i << 11); StaticDCodes[i] = BitReverse(i << 11);
staticDLength[i] = 5; StaticDLength[i] = 5;
} }
} }
@ -113,12 +118,17 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
{ {
this.Pending = new DeflaterPendingBuffer(memoryAllocator); this.Pending = new DeflaterPendingBuffer(memoryAllocator);
this.literalTree = new Tree(this, LiteralNumber, 257, 15); this.literalTree = new Tree(LiteralNumber, 257, 15);
this.distTree = new Tree(this, DistanceNumber, 1, 15); this.distTree = new Tree(DistanceNumber, 1, 15);
this.blTree = new Tree(this, BitLengthNumber, 4, 7); this.blTree = new Tree(BitLengthNumber, 4, 7);
this.distanceManagedBuffer = memoryAllocator.Allocate<short>(BufferSize);
this.distanceBufferHandle = this.distanceManagedBuffer.Memory.Pin();
this.pinnedDistanceBuffer = (short*)this.distanceBufferHandle.Pointer;
this.distanceBuffer = new short[BufferSize]; this.literalManagedBuffer = memoryAllocator.Allocate<short>(BufferSize);
this.literalBuffer = new byte[BufferSize]; this.literalBufferHandle = this.literalManagedBuffer.Memory.Pin();
this.pinnedLiteralBuffer = (short*)this.literalBufferHandle.Pointer;
} }
/// <summary> /// <summary>
@ -155,8 +165,8 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
this.Pending.WriteBits(this.blTree.Length[BitLengthOrder[rank]], 3); this.Pending.WriteBits(this.blTree.Length[BitLengthOrder[rank]], 3);
} }
this.literalTree.WriteTree(this.blTree); this.literalTree.WriteTree(this.Pending, this.blTree);
this.distTree.WriteTree(this.blTree); this.distTree.WriteTree(this.Pending, this.blTree);
} }
/// <summary> /// <summary>
@ -164,14 +174,18 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
/// </summary> /// </summary>
public void CompressBlock() public void CompressBlock()
{ {
DeflaterPendingBuffer pendingBuffer = this.Pending;
short* pinnedDistance = this.pinnedDistanceBuffer;
short* pinnedLiteral = this.pinnedLiteralBuffer;
for (int i = 0; i < this.lastLiteral; i++) for (int i = 0; i < this.lastLiteral; i++)
{ {
int litlen = this.literalBuffer[i] & 0xff; int litlen = pinnedLiteral[i] & 0xFF;
int dist = this.distanceBuffer[i]; int dist = pinnedDistance[i];
if (dist-- != 0) if (dist-- != 0)
{ {
int lc = Lcode(litlen); int lc = Lcode(litlen);
this.literalTree.WriteSymbol(lc); this.literalTree.WriteSymbol(pendingBuffer, lc);
int bits = (lc - 261) / 4; int bits = (lc - 261) / 4;
if (bits > 0 && bits <= 5) if (bits > 0 && bits <= 5)
@ -180,7 +194,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
} }
int dc = Dcode(dist); int dc = Dcode(dist);
this.distTree.WriteSymbol(dc); this.distTree.WriteSymbol(pendingBuffer, dc);
bits = (dc / 2) - 1; bits = (dc / 2) - 1;
if (bits > 0) if (bits > 0)
@ -190,11 +204,11 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
} }
else else
{ {
this.literalTree.WriteSymbol(litlen); this.literalTree.WriteSymbol(pendingBuffer, litlen);
} }
} }
this.literalTree.WriteSymbol(EofSymbol); this.literalTree.WriteSymbol(pendingBuffer, EofSymbol);
} }
/// <summary> /// <summary>
@ -245,19 +259,19 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
} }
} }
int opt_len = 14 + (blTreeCodes * 3) + this.blTree.GetEncodedLength() + int opt_len = 14 + (blTreeCodes * 3) + this.blTree.GetEncodedLength()
this.literalTree.GetEncodedLength() + this.distTree.GetEncodedLength() + + this.literalTree.GetEncodedLength() + this.distTree.GetEncodedLength()
this.extraBits; + this.extraBits;
int static_len = this.extraBits; int static_len = this.extraBits;
for (int i = 0; i < LiteralNumber; i++) for (int i = 0; i < LiteralNumber; i++)
{ {
static_len += this.literalTree.Freqs[i] * staticLLength[i]; static_len += this.literalTree.Freqs[i] * StaticLLength[i];
} }
for (int i = 0; i < DistanceNumber; i++) for (int i = 0; i < DistanceNumber; i++)
{ {
static_len += this.distTree.Freqs[i] * staticDLength[i]; static_len += this.distTree.Freqs[i] * StaticDLength[i];
} }
if (opt_len >= static_len) if (opt_len >= static_len)
@ -275,8 +289,8 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
{ {
// Encode with static tree // Encode with static tree
this.Pending.WriteBits((DeflaterConstants.STATIC_TREES << 1) + (lastBlock ? 1 : 0), 3); this.Pending.WriteBits((DeflaterConstants.STATIC_TREES << 1) + (lastBlock ? 1 : 0), 3);
this.literalTree.SetStaticCodes(staticLCodes, staticLLength); this.literalTree.SetStaticCodes(StaticLCodes, StaticLLength);
this.distTree.SetStaticCodes(staticDCodes, staticDLength); this.distTree.SetStaticCodes(StaticDCodes, StaticDLength);
this.CompressBlock(); this.CompressBlock();
this.Reset(); this.Reset();
} }
@ -294,20 +308,19 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
/// Get value indicating if internal buffer is full /// Get value indicating if internal buffer is full
/// </summary> /// </summary>
/// <returns>true if buffer is full</returns> /// <returns>true if buffer is full</returns>
public bool IsFull() [MethodImpl(InliningOptions.ShortMethod)]
{ public bool IsFull() => this.lastLiteral >= BufferSize;
return this.lastLiteral >= BufferSize;
}
/// <summary> /// <summary>
/// Add literal to buffer /// Add literal to buffer
/// </summary> /// </summary>
/// <param name="literal">Literal value to add to buffer.</param> /// <param name="literal">Literal value to add to buffer.</param>
/// <returns>Value indicating internal buffer is full</returns> /// <returns>Value indicating internal buffer is full</returns>
[MethodImpl(InliningOptions.ShortMethod)]
public bool TallyLit(int literal) public bool TallyLit(int literal)
{ {
this.distanceBuffer[this.lastLiteral] = 0; this.pinnedDistanceBuffer[this.lastLiteral] = 0;
this.literalBuffer[this.lastLiteral++] = (byte)literal; this.pinnedLiteralBuffer[this.lastLiteral++] = (byte)literal;
this.literalTree.Freqs[literal]++; this.literalTree.Freqs[literal]++;
return this.IsFull(); return this.IsFull();
} }
@ -318,10 +331,11 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
/// <param name="distance">Distance code</param> /// <param name="distance">Distance code</param>
/// <param name="length">Length</param> /// <param name="length">Length</param>
/// <returns>Value indicating if internal buffer is full</returns> /// <returns>Value indicating if internal buffer is full</returns>
[MethodImpl(InliningOptions.ShortMethod)]
public bool TallyDist(int distance, int length) public bool TallyDist(int distance, int length)
{ {
this.distanceBuffer[this.lastLiteral] = (short)distance; this.pinnedDistanceBuffer[this.lastLiteral] = (short)distance;
this.literalBuffer[this.lastLiteral++] = (byte)(length - 3); this.pinnedLiteralBuffer[this.lastLiteral++] = (byte)(length - 3);
int lc = Lcode(length - 3); int lc = Lcode(length - 3);
this.literalTree.Freqs[lc]++; this.literalTree.Freqs[lc]++;
@ -345,12 +359,13 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
/// </summary> /// </summary>
/// <param name="toReverse">Value to reverse bits</param> /// <param name="toReverse">Value to reverse bits</param>
/// <returns>Value with bits reversed</returns> /// <returns>Value with bits reversed</returns>
[MethodImpl(InliningOptions.ShortMethod)]
public static short BitReverse(int toReverse) public static short BitReverse(int toReverse)
{ {
return (short)(Bit4Reverse[toReverse & 0xF] << 12 | return (short)(Bit4Reverse[toReverse & 0xF] << 12
Bit4Reverse[(toReverse >> 4) & 0xF] << 8 | | Bit4Reverse[(toReverse >> 4) & 0xF] << 8
Bit4Reverse[(toReverse >> 8) & 0xF] << 4 | | Bit4Reverse[(toReverse >> 8) & 0xF] << 4
Bit4Reverse[toReverse >> 12]); | Bit4Reverse[toReverse >> 12]);
} }
/// <inheritdoc/> /// <inheritdoc/>
@ -360,6 +375,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
GC.SuppressFinalize(this); GC.SuppressFinalize(this);
} }
[MethodImpl(InliningOptions.ShortMethod)]
private static int Lcode(int length) private static int Lcode(int length)
{ {
if (length == 255) if (length == 255)
@ -377,6 +393,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
return code + length; return code + length;
} }
[MethodImpl(InliningOptions.ShortMethod)]
private static int Dcode(int distance) private static int Dcode(int distance)
{ {
int code = 0; int code = 0;
@ -396,6 +413,10 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
if (disposing) if (disposing)
{ {
this.Pending.Dispose(); this.Pending.Dispose();
this.distanceBufferHandle.Dispose();
this.distanceManagedBuffer.Dispose();
this.literalBufferHandle.Dispose();
this.literalManagedBuffer.Dispose();
} }
this.Pending = null; this.Pending = null;
@ -403,20 +424,18 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
} }
} }
private class Tree private sealed class Tree
{ {
private readonly int minNumCodes; private readonly int minNumCodes;
private short[] codes; private short[] codes;
private readonly int[] bitLengthCounts; private readonly int[] bitLengthCounts;
private readonly int maxLength; private readonly int maxLength;
private readonly DeflaterHuffman dh;
public Tree(DeflaterHuffman dh, int elems, int minCodes, int maxLength) public Tree(int elements, int minCodes, int maxLength)
{ {
this.dh = dh;
this.minNumCodes = minCodes; this.minNumCodes = minCodes;
this.maxLength = maxLength; this.maxLength = maxLength;
this.Freqs = new short[elems]; this.Freqs = new short[elements];
this.bitLengthCounts = new int[maxLength]; this.bitLengthCounts = new int[maxLength];
} }
@ -429,6 +448,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
/// <summary> /// <summary>
/// Resets the internal state of the tree /// Resets the internal state of the tree
/// </summary> /// </summary>
[MethodImpl(InliningOptions.ShortMethod)]
public void Reset() public void Reset()
{ {
for (int i = 0; i < this.Freqs.Length; i++) for (int i = 0; i < this.Freqs.Length; i++)
@ -440,17 +460,17 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
this.Length = null; this.Length = null;
} }
public void WriteSymbol(int code) [MethodImpl(InliningOptions.ShortMethod)]
{ public void WriteSymbol(DeflaterPendingBuffer pendingBuffer, int code)
this.dh.Pending.WriteBits(this.codes[code] & 0xffff, this.Length[code]); => pendingBuffer.WriteBits(this.codes[code] & 0xFFFF, this.Length[code]);
}
/// <summary> /// <summary>
/// Check that all frequencies are zero /// Check that all frequencies are zero
/// </summary> /// </summary>
/// <exception cref="ImageFormatException"> /// <exception cref="InvalidOperationException">
/// At least one frequency is non-zero /// At least one frequency is non-zero
/// </exception> /// </exception>
[MethodImpl(InliningOptions.ShortMethod)]
public void CheckEmpty() public void CheckEmpty()
{ {
bool empty = true; bool empty = true;
@ -461,7 +481,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
if (!empty) if (!empty)
{ {
throw new ImageFormatException("!Empty"); DeflateThrowHelper.ThrowFrequencyNotEmpty();
} }
} }
@ -481,7 +501,6 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
/// </summary> /// </summary>
public void BuildCodes() public void BuildCodes()
{ {
int numSymbols = this.Freqs.Length;
int[] nextCode = new int[this.maxLength]; int[] nextCode = new int[this.maxLength];
int code = 0; int code = 0;
@ -544,8 +563,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
// this case, both literals get a 1 bit code. // this case, both literals get a 1 bit code.
while (heapLen < 2) while (heapLen < 2)
{ {
int node = maxCode < 2 ? ++maxCode : 0; heap[heapLen++] = maxCode < 2 ? ++maxCode : 0;
heap[heapLen++] = node;
} }
this.NumCodes = Math.Max(maxCode + 1, this.minNumCodes); this.NumCodes = Math.Max(maxCode + 1, this.minNumCodes);
@ -602,7 +620,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
last = numNodes++; last = numNodes++;
childs[2 * last] = first; childs[2 * last] = first;
childs[(2 * last) + 1] = second; childs[(2 * last) + 1] = second;
int mindepth = Math.Min(values[first] & 0xff, values[second] & 0xff); int mindepth = Math.Min(values[first] & 0xFF, values[second] & 0xFF);
values[last] = lastVal = values[first] + values[second] - mindepth + 1; values[last] = lastVal = values[first] + values[second] - mindepth + 1;
// Again, propagate the hole to the leafs // Again, propagate the hole to the leafs
@ -633,7 +651,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
if (heap[0] != (childs.Length / 2) - 1) if (heap[0] != (childs.Length / 2) - 1)
{ {
throw new ImageFormatException("Heap invariant violated"); DeflateThrowHelper.ThrowHeapViolated();
} }
this.BuildLength(childs); this.BuildLength(childs);
@ -718,10 +736,11 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
} }
/// <summary> /// <summary>
/// Write tree values /// Write the tree values.
/// </summary> /// </summary>
/// <param name="blTree">Tree to write</param> /// <param name="pendingBuffer">The pending buffer.</param>
public void WriteTree(Tree blTree) /// <param name="bitLengthTree">The tree to write.</param>
public void WriteTree(DeflaterPendingBuffer pendingBuffer, Tree bitLengthTree)
{ {
int max_count; // max repeat count int max_count; // max repeat count
int min_count; // min repeat count int min_count; // min repeat count
@ -744,7 +763,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
min_count = 3; min_count = 3;
if (curlen != nextlen) if (curlen != nextlen)
{ {
blTree.WriteSymbol(nextlen); bitLengthTree.WriteSymbol(pendingBuffer, nextlen);
count = 0; count = 0;
} }
} }
@ -765,31 +784,31 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
{ {
while (count-- > 0) while (count-- > 0)
{ {
blTree.WriteSymbol(curlen); bitLengthTree.WriteSymbol(pendingBuffer, curlen);
} }
} }
else if (curlen != 0) else if (curlen != 0)
{ {
blTree.WriteSymbol(Repeat3To6); bitLengthTree.WriteSymbol(pendingBuffer, Repeat3To6);
this.dh.Pending.WriteBits(count - 3, 2); pendingBuffer.WriteBits(count - 3, 2);
} }
else if (count <= 10) else if (count <= 10)
{ {
blTree.WriteSymbol(Repeat3To10); bitLengthTree.WriteSymbol(pendingBuffer, Repeat3To10);
this.dh.Pending.WriteBits(count - 3, 3); pendingBuffer.WriteBits(count - 3, 3);
} }
else else
{ {
blTree.WriteSymbol(Repeat11To138); bitLengthTree.WriteSymbol(pendingBuffer, Repeat11To138);
this.dh.Pending.WriteBits(count - 11, 7); pendingBuffer.WriteBits(count - 11, 7);
} }
} }
} }
private void BuildLength(int[] childs) private void BuildLength(int[] children)
{ {
this.Length = new byte[this.Freqs.Length]; this.Length = new byte[this.Freqs.Length];
int numNodes = childs.Length / 2; int numNodes = children.Length / 2;
int numLeafs = (numNodes + 1) / 2; int numLeafs = (numNodes + 1) / 2;
int overflow = 0; int overflow = 0;
@ -804,7 +823,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
for (int i = numNodes - 1; i >= 0; i--) for (int i = numNodes - 1; i >= 0; i--)
{ {
if (childs[(2 * i) + 1] != -1) if (children[(2 * i) + 1] != -1)
{ {
int bitLength = lengths[i] + 1; int bitLength = lengths[i] + 1;
if (bitLength > this.maxLength) if (bitLength > this.maxLength)
@ -813,14 +832,14 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
overflow++; overflow++;
} }
lengths[childs[2 * i]] = lengths[childs[(2 * i) + 1]] = bitLength; lengths[children[2 * i]] = lengths[children[(2 * i) + 1]] = bitLength;
} }
else else
{ {
// A leaf node // A leaf node
int bitLength = lengths[i]; int bitLength = lengths[i];
this.bitLengthCounts[bitLength - 1]++; this.bitLengthCounts[bitLength - 1]++;
this.Length[childs[2 * i]] = (byte)lengths[i]; this.Length[children[2 * i]] = (byte)lengths[i];
} }
} }
@ -867,11 +886,11 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
int n = this.bitLengthCounts[bits - 1]; int n = this.bitLengthCounts[bits - 1];
while (n > 0) while (n > 0)
{ {
int childPtr = 2 * childs[nodePtr++]; int childPtr = 2 * children[nodePtr++];
if (childs[childPtr + 1] == -1) if (children[childPtr + 1] == -1)
{ {
// We found another leaf // We found another leaf
this.Length[childs[childPtr]] = (byte)bits; this.Length[children[childPtr]] = (byte)bits;
n--; n--;
} }
} }

1
src/ImageSharp/Formats/Png/Zlib/DeflaterPendingBuffer.cs

@ -29,7 +29,6 @@ namespace SixLabors.ImageSharp.Formats.Png.Zlib
/// <param name="memoryAllocator">The memory allocator to use for buffer allocations.</param> /// <param name="memoryAllocator">The memory allocator to use for buffer allocations.</param>
public DeflaterPendingBuffer(MemoryAllocator memoryAllocator) public DeflaterPendingBuffer(MemoryAllocator memoryAllocator)
{ {
this.buffer = new byte[DeflaterConstants.PENDING_BUF_SIZE];
this.managedBuffer = memoryAllocator.AllocateManagedByteBuffer(DeflaterConstants.PENDING_BUF_SIZE); this.managedBuffer = memoryAllocator.AllocateManagedByteBuffer(DeflaterConstants.PENDING_BUF_SIZE);
this.buffer = this.managedBuffer.Array; this.buffer = this.managedBuffer.Array;
this.handle = this.managedBuffer.Memory.Pin(); this.handle = this.managedBuffer.Memory.Pin();

Loading…
Cancel
Save