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
{
using System.Collections.Generic;
using ImageSharp.Memory;
/// <summary>
@ -10,6 +12,32 @@
/// <summary>
/// Gets or sets the quantization tables.
/// </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
{
using System;
using System.Buffers;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using ImageSharp.Formats.Jpeg.Port.Components;
using ImageSharp.Memory;
@ -346,9 +347,9 @@ namespace ImageSharp.Formats.Jpeg.Port
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;)
{
byte huffmanTableSpec = huffmanData[i];
@ -357,41 +358,95 @@ namespace ImageSharp.Formats.Jpeg.Port
for (int j = 0; j < 16; j++)
{
codeLengthSum += codeLengths[j] = huffmanData[o++];
codeLengthSum += codeLengths[j] = huffmanData[j];
}
// TODO: Pooling?
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);
for (int j = 0; j < codeLengthSum; j++)
{
huffmanValues[j] = values[o++];
huffmanValues[j] = values[j];
}
}
i += 17 + codeLengthSum;
i += 17 + codeLengthSum;
this.BuildHuffmanTable(
huffmanTableSpec >> 4 == 0 ? this.dcHuffmanTables : this.acHuffmanTables,
huffmanTableSpec & 15,
codeLengths,
huffmanValues);
this.BuildHuffmanTable(
huffmanTableSpec >> 4 == 0 ? this.dcHuffmanTables : this.acHuffmanTables,
huffmanTableSpec & 15,
codeLengths,
huffmanValues);
}
}
}
}
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;
while (length > 0 && codeLengths[length - 1] == 0)
{
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>

Loading…
Cancel
Save