diff --git a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/InputProcessor.cs b/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/InputProcessor.cs
index a7a5fcd986..5aa0fa3097 100644
--- a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/InputProcessor.cs
+++ b/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/InputProcessor.cs
@@ -220,7 +220,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
if (this.LastErrorCode == OrigDecoderErrorCode.NoError)
{
int lutIndex = (this.Bits.Accumulator >> (this.Bits.UnreadBits - OrigHuffmanTree.LutSizeLog2)) & 0xFF;
- int v = huffmanTree.Lut[lutIndex];
+ int v = huffmanTree.ReadLut(lutIndex);
if (v != 0)
{
@@ -259,7 +259,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
this.Bits.UnreadBits--;
this.Bits.Mask >>= 1;
- if (code <= huffmanTree.MaxCodes[i])
+ if (code <= huffmanTree.GetMaxCode(i))
{
result = huffmanTree.GetValue(code, i);
return this.LastErrorCode = OrigDecoderErrorCode.NoError;
diff --git a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OrigHuffmanTree.cs b/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OrigHuffmanTree.cs
index e96421a2d6..f773a12dfa 100644
--- a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OrigHuffmanTree.cs
+++ b/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OrigHuffmanTree.cs
@@ -3,13 +3,14 @@
using System;
using System.Buffers;
+using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
{
///
/// Represents a Huffman tree
///
- internal struct OrigHuffmanTree
+ internal unsafe struct OrigHuffmanTree
{
///
/// The index of the AC table row
@@ -67,29 +68,29 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
/// are 1 plus the code length, or 0 if the value is too large to fit in
/// lutSize bits.
///
- public int[] Lut;
+ public fixed int Lut[MaxNCodes];
///
/// Gets the the decoded values, sorted by their encoding.
///
- public int[] Values;
+ public fixed int Values[MaxNCodes];
///
/// Gets the array of minimum codes.
/// MinCodes[i] is the minimum code of length i, or -1 if there are no codes of that length.
///
- public int[] MinCodes;
+ public fixed int MinCodes[MaxCodeLength];
///
/// Gets the array of maximum codes.
/// MaxCodes[i] is the maximum code of length i, or -1 if there are no codes of that length.
///
- public int[] MaxCodes;
+ public fixed int MaxCodes[MaxCodeLength];
///
/// Gets the array of indices. Indices[i] is the index into Values of MinCodes[i].
///
- public int[] Indices;
+ public fixed int Indices[MaxCodeLength];
///
/// Creates and initializes an array of instances of size
@@ -97,16 +98,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
/// An array of instances representing the Huffman tables
public static OrigHuffmanTree[] CreateHuffmanTrees()
{
- OrigHuffmanTree[] result = new OrigHuffmanTree[NumberOfTrees];
- for (int i = 0; i < MaxTc + 1; i++)
- {
- for (int j = 0; j < MaxTh + 1; j++)
- {
- result[(i * ThRowSize) + j].Init();
- }
- }
-
- return result;
+ return new OrigHuffmanTree[NumberOfTrees];
}
///
@@ -151,64 +143,73 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
byte[] values = new byte[MaxNCodes];
inputProcessor.ReadFull(values, 0, this.Length);
- for (int i = 0; i < values.Length; i++)
+ fixed (int* valuesPtr = this.Values)
+ fixed (int* lutPtr = this.Lut)
{
- this.Values[i] = values[i];
- }
-
- // Derive the look-up table.
- for (int i = 0; i < this.Lut.Length; i++)
- {
- this.Lut[i] = 0;
- }
+ for (int i = 0; i < values.Length; i++)
+ {
+ valuesPtr[i] = values[i];
+ }
- int x = 0, code = 0;
+ // Derive the look-up table.
+ for (int i = 0; i < MaxNCodes; i++)
+ {
+ lutPtr[i] = 0;
+ }
- for (int i = 0; i < LutSizeLog2; i++)
- {
- code <<= 1;
+ int x = 0, code = 0;
- for (int j = 0; j < ncodes[i]; j++)
+ for (int i = 0; i < LutSizeLog2; i++)
{
- // The codeLength is 1+i, so shift code by 8-(1+i) to
- // calculate the high bits for every 8-bit sequence
- // whose codeLength's high bits matches code.
- // The high 8 bits of lutValue are the encoded value.
- // The low 8 bits are 1 plus the codeLength.
- int base2 = code << (7 - i);
- int lutValue = (this.Values[x] << 8) | (2 + i);
-
- for (int k = 0; k < 1 << (7 - i); k++)
+ code <<= 1;
+
+ for (int j = 0; j < ncodes[i]; j++)
{
- this.Lut[base2 | k] = lutValue;
+ // The codeLength is 1+i, so shift code by 8-(1+i) to
+ // calculate the high bits for every 8-bit sequence
+ // whose codeLength's high bits matches code.
+ // The high 8 bits of lutValue are the encoded value.
+ // The low 8 bits are 1 plus the codeLength.
+ int base2 = code << (7 - i);
+ int lutValue = (valuesPtr[x] << 8) | (2 + i);
+
+ for (int k = 0; k < 1 << (7 - i); k++)
+ {
+ lutPtr[base2 | k] = lutValue;
+ }
+
+ code++;
+ x++;
}
-
- code++;
- x++;
}
}
- // Derive minCodes, maxCodes, and indices.
- int c = 0, index = 0;
- for (int i = 0; i < ncodes.Length; i++)
+ fixed (int* minCodesPtr = this.MinCodes)
+ fixed (int* maxCodesPtr = this.MaxCodes)
+ fixed (int* indicesPtr = this.Indices)
{
- int nc = ncodes[i];
- if (nc == 0)
- {
- this.MinCodes[i] = -1;
- this.MaxCodes[i] = -1;
- this.Indices[i] = -1;
- }
- else
+ // Derive minCodes, maxCodes, and indices.
+ int c = 0, index = 0;
+ for (int i = 0; i < ncodes.Length; i++)
{
- this.MinCodes[i] = c;
- this.MaxCodes[i] = c + nc - 1;
- this.Indices[i] = index;
- c += nc;
- index += nc;
- }
+ int nc = ncodes[i];
+ if (nc == 0)
+ {
+ minCodesPtr[i] = -1;
+ maxCodesPtr[i] = -1;
+ indicesPtr[i] = -1;
+ }
+ else
+ {
+ minCodesPtr[i] = c;
+ maxCodesPtr[i] = c + nc - 1;
+ indicesPtr[i] = index;
+ c += nc;
+ index += nc;
+ }
- c <<= 1;
+ c <<= 1;
+ }
}
}
@@ -220,19 +221,30 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
/// The value
public int GetValue(int code, int codeLength)
{
- return this.Values[this.Indices[codeLength] + code - this.MinCodes[codeLength]];
+ fixed (int* valuesPtr = this.Values)
+ fixed (int* minCodesPtr = this.MinCodes)
+ fixed (int* indicesPtr = this.Indices)
+ {
+ return valuesPtr[indicesPtr[codeLength] + code - minCodesPtr[codeLength]];
+ }
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public int ReadLut(int index)
+ {
+ fixed (int* lutPtr = this.Lut)
+ {
+ return lutPtr[index];
+ }
}
- ///
- /// Initializes the Huffman tree
- ///
- private void Init()
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public int GetMaxCode(int index)
{
- this.Lut = new int[MaxNCodes];
- this.Values = new int[MaxNCodes];
- this.MinCodes = new int[MaxCodeLength];
- this.MaxCodes = new int[MaxCodeLength];
- this.Indices = new int[MaxCodeLength];
+ fixed (int* maxCodesPtr = this.MaxCodes)
+ {
+ return maxCodesPtr[index];
+ }
}
}
}
\ No newline at end of file