Browse Source

(╯°□°)╯︵ ┻━┻

af/merge-core
James Jackson-South 9 years ago
parent
commit
74ba49f162
  1. 30
      src/ImageSharp/Formats/Jpeg/Port/Components/HuffmanTables.cs
  2. 83
      src/ImageSharp/Formats/Jpeg/Port/JpegDecoderCore.cs

30
src/ImageSharp/Formats/Jpeg/Port/Components/HuffmanTables.cs

@ -1,5 +1,7 @@
namespace ImageSharp.Formats.Jpeg.Port.Components namespace ImageSharp.Formats.Jpeg.Port.Components
{ {
using System.Collections.Generic;
using ImageSharp.Memory; using ImageSharp.Memory;
/// <summary> /// <summary>
@ -10,6 +12,32 @@
/// <summary> /// <summary>
/// Gets or sets the quantization tables. /// Gets or sets the quantization tables.
/// </summary> /// </summary>
public Fast2DArray<short> Tables { get; set; } = new Fast2DArray<short>(256, 2); public Fast2DArray<HuffmanBranch> Tables { get; set; } = new Fast2DArray<HuffmanBranch>(256, 2);
}
internal struct HuffmanBranch
{
public HuffmanBranch(short value)
: this(value, new List<HuffmanBranch>())
{
}
public HuffmanBranch(List<HuffmanBranch> children)
: this(0, children)
{
}
private HuffmanBranch(short value, List<HuffmanBranch> children)
{
this.Index = 0;
this.Value = value;
this.Children = children;
}
public int Index;
public short Value;
public List<HuffmanBranch> Children;
} }
} }

83
src/ImageSharp/Formats/Jpeg/Port/JpegDecoderCore.cs

@ -6,8 +6,9 @@
namespace ImageSharp.Formats.Jpeg.Port namespace ImageSharp.Formats.Jpeg.Port
{ {
using System; using System;
using System.Buffers; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq;
using ImageSharp.Formats.Jpeg.Port.Components; using ImageSharp.Formats.Jpeg.Port.Components;
using ImageSharp.Memory; using ImageSharp.Memory;
@ -346,9 +347,9 @@ namespace ImageSharp.Formats.Jpeg.Port
using (var huffmanData = new Buffer<byte>(remaining)) using (var huffmanData = new Buffer<byte>(remaining))
{ {
this.InputStream.Read(huffmanData.Array, 1, remaining); this.InputStream.Skip(1);
this.InputStream.Read(huffmanData.Array, 0, remaining);
int o = 0;
for (int i = 0; i < remaining;) for (int i = 0; i < remaining;)
{ {
byte huffmanTableSpec = huffmanData[i]; byte huffmanTableSpec = huffmanData[i];
@ -357,41 +358,95 @@ namespace ImageSharp.Formats.Jpeg.Port
for (int j = 0; j < 16; j++) for (int j = 0; j < 16; j++)
{ {
codeLengthSum += codeLengths[j] = huffmanData[o++]; codeLengthSum += codeLengths[j] = huffmanData[j];
} }
// TODO: Pooling? // TODO: Pooling?
short[] huffmanValues = new short[codeLengthSum]; short[] huffmanValues = new short[codeLengthSum];
using (var values = new Buffer<byte>(256)) using (var values = new Buffer<byte>(codeLengthSum))
{ {
this.InputStream.Read(values.Array, 0, codeLengthSum); this.InputStream.Read(values.Array, 0, codeLengthSum);
for (int j = 0; j < codeLengthSum; j++) for (int j = 0; j < codeLengthSum; j++)
{ {
huffmanValues[j] = values[o++]; huffmanValues[j] = values[j];
} }
}
i += 17 + codeLengthSum; i += 17 + codeLengthSum;
this.BuildHuffmanTable( this.BuildHuffmanTable(
huffmanTableSpec >> 4 == 0 ? this.dcHuffmanTables : this.acHuffmanTables, huffmanTableSpec >> 4 == 0 ? this.dcHuffmanTables : this.acHuffmanTables,
huffmanTableSpec & 15, huffmanTableSpec & 15,
codeLengths, codeLengths,
huffmanValues); huffmanValues);
}
} }
} }
} }
private void BuildHuffmanTable(HuffmanTables tables, int index, byte[] codeLengths, short[] values) private void BuildHuffmanTable(HuffmanTables tables, int index, byte[] codeLengths, short[] values)
{ {
// (╯°□°)╯︵ ┻━┻ Everything up to here is going well. I can't match the JavaScript now though.
int length = 16; int length = 16;
while (length > 0 && codeLengths[length - 1] == 0) while (length > 0 && codeLengths[length - 1] == 0)
{ {
length--; length--;
} }
Span<short> tableSpan = tables.Tables.GetRowSpan(index); var code = new Queue<HuffmanBranch>();
code.Enqueue(new HuffmanBranch(new List<HuffmanBranch>()));
HuffmanBranch p = code.Peek();
p.Children = new List<HuffmanBranch>();
HuffmanBranch q;
int k = 0;
try
{
for (int i = 0; i < length; i++)
{
for (int j = 0; j < codeLengths[i]; j++)
{
p = code.Dequeue();
p.Children.Add(new HuffmanBranch(values[k]));
while (p.Index > 0)
{
p = code.Dequeue();
}
p.Index++;
code.Enqueue(p);
while (code.Count <= i)
{
q = new HuffmanBranch(new List<HuffmanBranch>());
code.Enqueue(q);
p.Children.Add(new HuffmanBranch(q.Children));
p = q;
}
k++;
}
if (i + 1 < length)
{
// p here points to last code
q = new HuffmanBranch(new List<HuffmanBranch>());
code.Enqueue(q);
p.Children.Add(new HuffmanBranch(q.Children));
p = q;
}
}
Span<HuffmanBranch> tableSpan = tables.Tables.GetRowSpan(index);
List<HuffmanBranch> result = code.Peek().Children;
for (int i = 0; i < result.Count; i++)
{
tableSpan[i] = result[i];
}
}
catch (Exception e)
{
throw;
}
} }
/// <summary> /// <summary>

Loading…
Cancel
Save