Browse Source

Clean up Huffman table code.

af/merge-core
James Jackson-South 8 years ago
parent
commit
bc5010bfbb
  1. 8
      src/ImageSharp/Formats/Jpeg/Components/Decoder/FastACTables.cs
  2. 104
      src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanTable.cs

8
src/ImageSharp/Formats/Jpeg/Components/Decoder/FastACTables.cs

@ -46,19 +46,19 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
{ {
const int FastBits = ScanDecoder.FastBits; const int FastBits = ScanDecoder.FastBits;
Span<short> fastAC = this.tables.GetRowSpan(index); Span<short> fastAC = this.tables.GetRowSpan(index);
ref HuffmanTable huffman = ref acHuffmanTables[index]; ref HuffmanTable huffmanTable = ref acHuffmanTables[index];
int i; int i;
for (i = 0; i < (1 << FastBits); i++) for (i = 0; i < (1 << FastBits); i++)
{ {
byte fast = huffman.Lookahead[i]; byte fast = huffmanTable.Lookahead[i];
fastAC[i] = 0; fastAC[i] = 0;
if (fast < byte.MaxValue) if (fast < byte.MaxValue)
{ {
int rs = huffman.Values[fast]; int rs = huffmanTable.Values[fast];
int run = (rs >> 4) & 15; int run = (rs >> 4) & 15;
int magbits = rs & 15; int magbits = rs & 15;
int len = huffman.Sizes[fast]; int len = huffmanTable.Sizes[fast];
if (magbits != 0 && len + magbits <= FastBits) if (magbits != 0 && len + magbits <= FastBits)
{ {

104
src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanTable.cs

@ -46,87 +46,79 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
/// Initializes a new instance of the <see cref="HuffmanTable"/> struct. /// Initializes a new instance of the <see cref="HuffmanTable"/> struct.
/// </summary> /// </summary>
/// <param name="memoryAllocator">The <see cref="MemoryAllocator"/> to use for buffer allocations.</param> /// <param name="memoryAllocator">The <see cref="MemoryAllocator"/> to use for buffer allocations.</param>
/// <param name="count">The code lengths</param> /// <param name="codeLengths">The code lengths</param>
/// <param name="values">The huffman values</param> /// <param name="values">The huffman values</param>
public HuffmanTable(MemoryAllocator memoryAllocator, ReadOnlySpan<byte> count, ReadOnlySpan<byte> values) public HuffmanTable(MemoryAllocator memoryAllocator, ReadOnlySpan<byte> codeLengths, ReadOnlySpan<byte> values)
{ {
const int Length = 257; const int Length = 257;
using (IMemoryOwner<short> huffcode = memoryAllocator.Allocate<short>(Length)) using (IMemoryOwner<short> huffcode = memoryAllocator.Allocate<short>(Length))
{ {
ref short huffcodeRef = ref MemoryMarshal.GetReference(huffcode.GetSpan()); ref short huffcodeRef = ref MemoryMarshal.GetReference(huffcode.GetSpan());
ref byte codeLengthsRef = ref MemoryMarshal.GetReference(codeLengths);
// Figure C.1: make table of Huffman code length for each symbol // Figure C.1: make table of Huffman code length for each symbol
fixed (short* sizesRef = this.Sizes.Data) ref short sizesRef = ref this.Sizes.Data[0];
short x = 0;
for (short i = 1; i < 17; i++)
{ {
short x = 0; byte length = Unsafe.Add(ref codeLengthsRef, i);
for (short i = 1; i < 17; i++) for (short j = 0; j < length; j++)
{ {
byte l = count[i]; Unsafe.Add(ref sizesRef, x++) = i;
for (short j = 0; j < l; j++)
{
sizesRef[x++] = i;
}
} }
}
sizesRef[x] = 0; Unsafe.Add(ref sizesRef, x) = 0;
// Figure C.2: generate the codes themselves // Figure C.2: generate the codes themselves
int k = 0; int si = 0;
fixed (int* valOffsetRef = this.ValOffset.Data) ref int valOffsetRef = ref this.ValOffset.Data[0];
fixed (uint* maxcodeRef = this.MaxCode.Data) ref uint maxcodeRef = ref this.MaxCode.Data[0];
uint code = 0;
int k;
for (k = 1; k < 17; k++)
{
// Compute delta to add to code to compute symbol id.
Unsafe.Add(ref valOffsetRef, k) = (int)(si - code);
if (Unsafe.Add(ref sizesRef, si) == k)
{ {
uint code = 0; while (Unsafe.Add(ref sizesRef, si) == k)
int j;
for (j = 1; j < 17; j++)
{ {
// Compute delta to add to code to compute symbol id. Unsafe.Add(ref huffcodeRef, si++) = (short)code++;
valOffsetRef[j] = (int)(k - code);
if (sizesRef[k] == j)
{
while (sizesRef[k] == j)
{
Unsafe.Add(ref huffcodeRef, k++) = (short)code++;
}
}
// Figure F.15: generate decoding tables for bit-sequential decoding.
// Compute largest code + 1 for this size. preshifted as need later.
maxcodeRef[j] = code << (16 - j);
code <<= 1;
} }
maxcodeRef[j] = 0xFFFFFFFF;
} }
// Generate non-spec lookup tables to speed up decoding. // Figure F.15: generate decoding tables for bit-sequential decoding.
fixed (byte* lookaheadRef = this.Lookahead.Data) // Compute largest code + 1 for this size. preshifted as we need later.
{ Unsafe.Add(ref maxcodeRef, k) = code << (16 - k);
const int FastBits = ScanDecoder.FastBits; code <<= 1;
var fast = new Span<byte>(lookaheadRef, 1 << FastBits); }
fast.Fill(0xFF); // Flag for non-accelerated
Unsafe.Add(ref maxcodeRef, k) = 0xFFFFFFFF;
for (int i = 0; i < k; i++) // Generate non-spec lookup tables to speed up decoding.
const int FastBits = ScanDecoder.FastBits;
ref byte fastRef = ref this.Lookahead.Data[0];
new Span<byte>(Unsafe.AsPointer(ref fastRef), 1 << FastBits).Fill(0xFF); // Flag for non-accelerated
for (int i = 0; i < si; i++)
{
int size = Unsafe.Add(ref sizesRef, i);
if (size <= FastBits)
{
int c = Unsafe.Add(ref huffcodeRef, i) << (FastBits - size);
int m = 1 << (FastBits - size);
for (int l = 0; l < m; l++)
{ {
int s = sizesRef[i]; Unsafe.Add(ref fastRef, c + l) = (byte)i;
if (s <= ScanDecoder.FastBits)
{
int c = Unsafe.Add(ref huffcodeRef, i) << (FastBits - s);
int m = 1 << (FastBits - s);
for (int j = 0; j < m; j++)
{
fast[c + j] = (byte)i;
}
}
} }
} }
} }
} }
fixed (byte* huffValRef = this.Values.Data) values.CopyTo(new Span<byte>(Unsafe.AsPointer(ref this.Values.Data[0]), 256));
{
var huffValSpan = new Span<byte>(huffValRef, 256);
values.CopyTo(huffValSpan);
}
} }
} }
} }
Loading…
Cancel
Save