Browse Source

Use properties

af/merge-core
James Jackson-South 9 years ago
parent
commit
8e4cdc732a
  1. 125
      src/ImageSharp/Formats/Jpeg/Port/Components/HuffmanTable.cs
  2. 8
      src/ImageSharp/Formats/Jpeg/Port/Components/ScanDecoder.cs

125
src/ImageSharp/Formats/Jpeg/Port/Components/HuffmanTable.cs

@ -16,13 +16,9 @@ namespace ImageSharp.Formats.Jpeg.Port.Components
internal struct HuffmanTable : IDisposable
{
private Buffer<short> lookahead;
private Buffer<short> huffcode;
private Buffer<short> huffsize;
private Buffer<short> valOffset;
private Buffer<long> maxcode;
private Buffer<byte> huffval;
private Buffer<byte> bits;
/// <summary>
/// Initializes a new instance of the <see cref="HuffmanTable"/> struct.
@ -32,119 +28,113 @@ namespace ImageSharp.Formats.Jpeg.Port.Components
public HuffmanTable(byte[] lengths, byte[] values)
{
this.lookahead = Buffer<short>.CreateClean(256);
this.huffcode = Buffer<short>.CreateClean(257);
this.huffsize = Buffer<short>.CreateClean(257);
this.valOffset = Buffer<short>.CreateClean(18);
this.maxcode = Buffer<long>.CreateClean(18);
using (var huffsize = Buffer<short>.CreateClean(257))
using (var huffcode = Buffer<short>.CreateClean(257))
{
GenerateSizeTable(lengths, huffsize);
GenerateCodeTable(huffsize, huffcode);
GenerateDecoderTables(lengths, huffcode, this.valOffset, this.maxcode);
GenerateLookaheadTables(lengths, values, this.lookahead);
}
this.huffval = Buffer<byte>.CreateClean(values.Length);
Buffer.BlockCopy(values, 0, this.huffval.Array, 0, values.Length);
this.bits = Buffer<byte>.CreateClean(lengths.Length);
Buffer.BlockCopy(lengths, 0, this.bits.Array, 0, lengths.Length);
this.GenerateSizeTable();
this.GenerateCodeTable();
this.GenerateDecoderTables();
this.GenerateLookaheadTables();
this.MaxCode = this.maxcode.Array;
this.ValOffset = this.valOffset.Array;
this.HuffVal = this.huffval.Array;
this.Lookahead = this.lookahead.Array;
}
/// <summary>
/// Gets the Huffman value code at the given index
/// Gets the max code array
/// </summary>
/// <param name="i">The index</param>
/// <returns>The <see cref="int"/></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public short GetHuffVal(int i)
public long[] MaxCode
{
return this.huffval[i];
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get;
}
/// <summary>
/// Gets the max code at the given index
/// Gets the value offset array
/// </summary>
/// <param name="i">The index</param>
/// <returns>The <see cref="int"/></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public long GetMaxCode(int i)
public short[] ValOffset
{
return this.maxcode[i];
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get;
}
/// <summary>
/// Gets the index to the locatation of the huffman value
/// Gets the huffman value array
/// </summary>
/// <param name="i">The index</param>
/// <returns>The <see cref="int"/></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int GetValOffset(int i)
public byte[] HuffVal
{
return this.valOffset[i];
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get;
}
/// <summary>
/// Gets the look ahead table balue
/// Gets the lookahead array
/// </summary>
/// <param name="i">The index</param>
/// <returns>The <see cref="int"/></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int GetLookAhead(int i)
public short[] Lookahead
{
return this.lookahead[i];
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get;
}
/// <inheritdoc/>
public void Dispose()
{
this.lookahead?.Dispose();
this.huffcode?.Dispose();
this.huffsize?.Dispose();
this.valOffset?.Dispose();
this.maxcode?.Dispose();
this.huffval?.Dispose();
this.bits?.Dispose();
this.lookahead = null;
this.huffcode = null;
this.huffsize = null;
this.valOffset = null;
this.maxcode = null;
this.huffval = null;
this.bits = null;
}
/// <summary>
/// Figure C.1: make table of Huffman code length for each symbol
/// </summary>
private void GenerateSizeTable()
/// <param name="lengths">The code lengths</param>
/// <param name="huffsize">The huffman size span</param>
private static void GenerateSizeTable(byte[] lengths, Span<short> huffsize)
{
short index = 0;
for (short l = 1; l <= 16; l++)
{
byte i = this.bits[l];
byte i = lengths[l];
for (short j = 0; j < i; j++)
{
this.huffsize[index] = l;
huffsize[index] = l;
index++;
}
}
this.huffsize[index] = 0;
huffsize[index] = 0;
}
/// <summary>
/// Figure C.2: generate the codes themselves
/// </summary>
private void GenerateCodeTable()
/// <param name="huffsize">The huffman size span</param>
/// <param name="huffcode">The huffman code span</param>
private static void GenerateCodeTable(Span<short> huffsize, Span<short> huffcode)
{
short k = 0;
short si = this.huffsize[0];
short si = huffsize[0];
short code = 0;
for (short i = 0; i < this.huffsize.Length; i++)
for (short i = 0; i < huffsize.Length; i++)
{
while (this.huffsize[k] == si)
while (huffsize[k] == si)
{
this.huffcode[k] = code;
huffcode[k] = code;
code++;
k++;
}
@ -157,33 +147,40 @@ namespace ImageSharp.Formats.Jpeg.Port.Components
/// <summary>
/// Figure F.15: generate decoding tables for bit-sequential decoding
/// </summary>
private void GenerateDecoderTables()
/// <param name="lengths">The code lengths</param>
/// <param name="huffcode">The huffman code span</param>
/// <param name="valOffset">The value offset span</param>
/// <param name="maxcode">The max code span</param>
private static void GenerateDecoderTables(byte[] lengths, Span<short> huffcode, Span<short> valOffset, Span<long> maxcode)
{
short bitcount = 0;
for (int i = 1; i <= 16; i++)
{
if (this.bits[i] != 0)
if (lengths[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
valOffset[i] = (short)(bitcount - huffcode[bitcount]);
bitcount += lengths[i];
maxcode[i] = huffcode[bitcount - 1]; // maximum code of length i
}
else
{
this.maxcode[i] = -1; // -1 if no codes of this length
maxcode[i] = -1; // -1 if no codes of this length
}
}
this.valOffset[17] = 0;
this.maxcode[17] = 0xFFFFFL;
valOffset[17] = 0;
maxcode[17] = 0xFFFFFL;
}
/// <summary>
/// Generates lookup tables to speed up decoding
/// </summary>
private void GenerateLookaheadTables()
/// <param name="lengths">The code lengths</param>
/// <param name="huffval">The huffman value array</param>
/// <param name="lookahead">The lookahead span</param>
private static void GenerateLookaheadTables(byte[] lengths, byte[] huffval, Span<short> lookahead)
{
int x = 0, code = 0;
@ -191,7 +188,7 @@ namespace ImageSharp.Formats.Jpeg.Port.Components
{
code <<= 1;
for (int j = 0; j < this.bits[i + 1]; j++)
for (int j = 0; j < lengths[i + 1]; j++)
{
// The codeLength is 1+i, so shift code by 8-(1+i) to
// calculate the high bits for every 8-bit sequence
@ -199,11 +196,11 @@ namespace ImageSharp.Formats.Jpeg.Port.Components
// The high 8 bits of lutValue are the encoded value.
// The low 8 bits are 1 plus the codeLength.
byte base2 = (byte)(code << (7 - i));
short lutValue = (short)((short)(this.huffval[x] << 8) | (short)(2 + i));
short lutValue = (short)((short)(huffval[x] << 8) | (short)(2 + i));
for (int k = 0; k < 1 << (7 - i); k++)
{
this.lookahead[base2 | k] = lutValue;
lookahead[base2 | k] = lutValue;
}
code++;

8
src/ImageSharp/Formats/Jpeg/Port/Components/ScanDecoder.cs

@ -635,7 +635,7 @@ namespace ImageSharp.Formats.Jpeg.Port.Components
// }
// this.accumulator = (this.accumulator << 8) | this.bitsData;
// int lutIndex = (this.accumulator >> (this.bitsUnRead - 8)) & 0xFF;
// int v = tree.GetLookAhead(lutIndex);
// int v = tree.Lookahead[lutIndex];
// if (v != 0)
// {
// int nb = (v & 0xFF) - 1;
@ -657,7 +657,7 @@ namespace ImageSharp.Formats.Jpeg.Port.Components
// "DECODE", section F.2.2.3, figure F.16, page 109 of T.81
int i = 1;
while (code > tree.GetMaxCode(i))
while (code > tree.MaxCode[i])
{
code <<= 1;
code |= (short)this.ReadBit(stream);
@ -670,8 +670,8 @@ namespace ImageSharp.Formats.Jpeg.Port.Components
i++;
}
int j = tree.GetValOffset(i);
return tree.GetHuffVal((j + code) & 0xFF);
int j = tree.ValOffset[i];
return tree.HuffVal[(j + code) & 0xFF];
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]

Loading…
Cancel
Save