mirror of https://github.com/SixLabors/ImageSharp
4 changed files with 170 additions and 70 deletions
@ -0,0 +1,136 @@ |
|||
namespace ImageSharp.Formats.Jpeg.Port.Components |
|||
{ |
|||
using System; |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
/// <summary>
|
|||
/// Represents a HUffman Table
|
|||
/// </summary>
|
|||
internal sealed class HuffmanTable |
|||
{ |
|||
private short[] huffcode = new short[257]; |
|||
private short[] huffsize = new short[257]; |
|||
private short[] valOffset = new short[18]; |
|||
private long[] maxcode = new long[18]; |
|||
|
|||
private byte[] huffval; |
|||
private byte[] bits; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="HuffmanTable"/> class.
|
|||
/// </summary>
|
|||
/// <param name="lengths">The code lengths</param>
|
|||
/// <param name="values">The huffman values</param>
|
|||
public HuffmanTable(byte[] lengths, byte[] values) |
|||
{ |
|||
this.huffval = new byte[values.Length]; |
|||
Buffer.BlockCopy(values, 0, this.huffval, 0, values.Length); |
|||
this.bits = new byte[lengths.Length]; |
|||
Buffer.BlockCopy(lengths, 0, this.bits, 0, lengths.Length); |
|||
|
|||
this.GenerateSizeTable(); |
|||
this.GenerateCodeTable(); |
|||
this.GenerateDecoderTables(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the Huffman value code at the given index
|
|||
/// </summary>
|
|||
/// <param name="i">The index</param>
|
|||
/// <returns>The <see cref="int"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public short GetHuffVal(int i) |
|||
{ |
|||
return this.huffval[i]; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the max code at the given index
|
|||
/// </summary>
|
|||
/// <param name="i">The index</param>
|
|||
/// <returns>The <see cref="int"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public long GetMaxCode(int i) |
|||
{ |
|||
return this.maxcode[i]; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the index to the locatation of the huffman value
|
|||
/// </summary>
|
|||
/// <param name="i">The index</param>
|
|||
/// <returns>The <see cref="int"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public int GetValPtr(int i) |
|||
{ |
|||
return this.valOffset[i]; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Figure C.1: make table of Huffman code length for each symbol
|
|||
/// </summary>
|
|||
private void GenerateSizeTable() |
|||
{ |
|||
short index = 0; |
|||
for (short l = 1; l <= 16; l++) |
|||
{ |
|||
byte i = this.bits[l]; |
|||
for (short j = 0; j < i; j++) |
|||
{ |
|||
this.huffsize[index] = l; |
|||
index++; |
|||
} |
|||
} |
|||
|
|||
this.huffsize[index] = 0; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Figure C.2: generate the codes themselves
|
|||
/// </summary>
|
|||
private void GenerateCodeTable() |
|||
{ |
|||
short k = 0; |
|||
short si = this.huffsize[0]; |
|||
short code = 0; |
|||
for (short i = 0; i < this.huffsize.Length; i++) |
|||
{ |
|||
while (this.huffsize[k] == si) |
|||
{ |
|||
this.huffcode[k] = code; |
|||
code++; |
|||
k++; |
|||
} |
|||
|
|||
code <<= 1; |
|||
si++; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Figure F.15: generate decoding tables for bit-sequential decoding
|
|||
/// </summary>
|
|||
private void GenerateDecoderTables() |
|||
{ |
|||
short bitcount = 0; |
|||
for (int i = 1; i <= 16; i++) |
|||
{ |
|||
if (this.bits[i] != 0) |
|||
{ |
|||
// valoffset[l] = huffval[] index of 1st symbol of code length i,
|
|||
// minus the minimum code of length i
|
|||
this.valOffset[i] = (short)(bitcount - this.huffcode[bitcount]); |
|||
bitcount += this.bits[i]; |
|||
this.maxcode[i] = this.huffcode[bitcount - 1]; // maximum code of length i
|
|||
} |
|||
else |
|||
{ |
|||
this.maxcode[i] = -1; // -1 if no codes of this length
|
|||
} |
|||
} |
|||
|
|||
this.valOffset[17] = 0; |
|||
this.maxcode[17] = 0xFFFFFL; |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue