Browse Source

- Use fixed buffers in Huffman table

af/merge-core
Lauri Kotilainen 8 years ago
parent
commit
15521be1c3
  1. 4
      src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/InputProcessor.cs
  2. 154
      src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OrigHuffmanTree.cs

4
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) if (this.LastErrorCode == OrigDecoderErrorCode.NoError)
{ {
int lutIndex = (this.Bits.Accumulator >> (this.Bits.UnreadBits - OrigHuffmanTree.LutSizeLog2)) & 0xFF; int lutIndex = (this.Bits.Accumulator >> (this.Bits.UnreadBits - OrigHuffmanTree.LutSizeLog2)) & 0xFF;
int v = huffmanTree.Lut[lutIndex]; int v = huffmanTree.ReadLut(lutIndex);
if (v != 0) if (v != 0)
{ {
@ -259,7 +259,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
this.Bits.UnreadBits--; this.Bits.UnreadBits--;
this.Bits.Mask >>= 1; this.Bits.Mask >>= 1;
if (code <= huffmanTree.MaxCodes[i]) if (code <= huffmanTree.GetMaxCode(i))
{ {
result = huffmanTree.GetValue(code, i); result = huffmanTree.GetValue(code, i);
return this.LastErrorCode = OrigDecoderErrorCode.NoError; return this.LastErrorCode = OrigDecoderErrorCode.NoError;

154
src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/OrigHuffmanTree.cs

@ -3,13 +3,14 @@
using System; using System;
using System.Buffers; using System.Buffers;
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
{ {
/// <summary> /// <summary>
/// Represents a Huffman tree /// Represents a Huffman tree
/// </summary> /// </summary>
internal struct OrigHuffmanTree internal unsafe struct OrigHuffmanTree
{ {
/// <summary> /// <summary>
/// The index of the AC table row /// 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 /// are 1 plus the code length, or 0 if the value is too large to fit in
/// lutSize bits. /// lutSize bits.
/// </summary> /// </summary>
public int[] Lut; public fixed int Lut[MaxNCodes];
/// <summary> /// <summary>
/// Gets the the decoded values, sorted by their encoding. /// Gets the the decoded values, sorted by their encoding.
/// </summary> /// </summary>
public int[] Values; public fixed int Values[MaxNCodes];
/// <summary> /// <summary>
/// Gets the array of minimum codes. /// 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. /// MinCodes[i] is the minimum code of length i, or -1 if there are no codes of that length.
/// </summary> /// </summary>
public int[] MinCodes; public fixed int MinCodes[MaxCodeLength];
/// <summary> /// <summary>
/// Gets the array of maximum codes. /// 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. /// MaxCodes[i] is the maximum code of length i, or -1 if there are no codes of that length.
/// </summary> /// </summary>
public int[] MaxCodes; public fixed int MaxCodes[MaxCodeLength];
/// <summary> /// <summary>
/// Gets the array of indices. Indices[i] is the index into Values of MinCodes[i]. /// Gets the array of indices. Indices[i] is the index into Values of MinCodes[i].
/// </summary> /// </summary>
public int[] Indices; public fixed int Indices[MaxCodeLength];
/// <summary> /// <summary>
/// Creates and initializes an array of <see cref="OrigHuffmanTree" /> instances of size <see cref="NumberOfTrees" /> /// Creates and initializes an array of <see cref="OrigHuffmanTree" /> instances of size <see cref="NumberOfTrees" />
@ -97,16 +98,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
/// <returns>An array of <see cref="OrigHuffmanTree" /> instances representing the Huffman tables</returns> /// <returns>An array of <see cref="OrigHuffmanTree" /> instances representing the Huffman tables</returns>
public static OrigHuffmanTree[] CreateHuffmanTrees() public static OrigHuffmanTree[] CreateHuffmanTrees()
{ {
OrigHuffmanTree[] result = new OrigHuffmanTree[NumberOfTrees]; return 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;
} }
/// <summary> /// <summary>
@ -151,64 +143,73 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
byte[] values = new byte[MaxNCodes]; byte[] values = new byte[MaxNCodes];
inputProcessor.ReadFull(values, 0, this.Length); 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]; for (int i = 0; i < values.Length; i++)
} {
valuesPtr[i] = values[i];
// Derive the look-up table. }
for (int i = 0; i < this.Lut.Length; i++)
{
this.Lut[i] = 0;
}
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++) int x = 0, code = 0;
{
code <<= 1;
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 code <<= 1;
// calculate the high bits for every 8-bit sequence
// whose codeLength's high bits matches code. for (int j = 0; j < ncodes[i]; j++)
// 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++)
{ {
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. fixed (int* minCodesPtr = this.MinCodes)
int c = 0, index = 0; fixed (int* maxCodesPtr = this.MaxCodes)
for (int i = 0; i < ncodes.Length; i++) fixed (int* indicesPtr = this.Indices)
{ {
int nc = ncodes[i]; // Derive minCodes, maxCodes, and indices.
if (nc == 0) int c = 0, index = 0;
{ for (int i = 0; i < ncodes.Length; i++)
this.MinCodes[i] = -1;
this.MaxCodes[i] = -1;
this.Indices[i] = -1;
}
else
{ {
this.MinCodes[i] = c; int nc = ncodes[i];
this.MaxCodes[i] = c + nc - 1; if (nc == 0)
this.Indices[i] = index; {
c += nc; minCodesPtr[i] = -1;
index += nc; 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
/// <returns>The value</returns> /// <returns>The value</returns>
public int GetValue(int code, int codeLength) 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];
}
} }
/// <summary> [MethodImpl(MethodImplOptions.AggressiveInlining)]
/// Initializes the Huffman tree public int GetMaxCode(int index)
/// </summary>
private void Init()
{ {
this.Lut = new int[MaxNCodes]; fixed (int* maxCodesPtr = this.MaxCodes)
this.Values = new int[MaxNCodes]; {
this.MinCodes = new int[MaxCodeLength]; return maxCodesPtr[index];
this.MaxCodes = new int[MaxCodeLength]; }
this.Indices = new int[MaxCodeLength];
} }
} }
} }
Loading…
Cancel
Save