Skip to content

Commit 3728b82

Browse files
(╯°□°)╯︵ ┻━┻
1 parent b025ed6 commit 3728b82

File tree

2 files changed

+98
-15
lines changed

2 files changed

+98
-15
lines changed

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

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
namespace ImageSharp.Formats.Jpeg.Port.Components
22
{
3+
using System.Collections.Generic;
4+
35
using ImageSharp.Memory;
46

57
/// <summary>
@@ -10,6 +12,32 @@ internal class HuffmanTables
1012
/// <summary>
1113
/// Gets or sets the quantization tables.
1214
/// </summary>
13-
public Fast2DArray<short> Tables { get; set; } = new Fast2DArray<short>(256, 2);
15+
public Fast2DArray<HuffmanBranch> Tables { get; set; } = new Fast2DArray<HuffmanBranch>(256, 2);
16+
}
17+
18+
internal struct HuffmanBranch
19+
{
20+
public HuffmanBranch(short value)
21+
: this(value, new List<HuffmanBranch>())
22+
{
23+
}
24+
25+
public HuffmanBranch(List<HuffmanBranch> children)
26+
: this(0, children)
27+
{
28+
}
29+
30+
private HuffmanBranch(short value, List<HuffmanBranch> children)
31+
{
32+
this.Index = 0;
33+
this.Value = value;
34+
this.Children = children;
35+
}
36+
37+
public int Index;
38+
39+
public short Value;
40+
41+
public List<HuffmanBranch> Children;
1442
}
1543
}

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

Lines changed: 69 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@
66
namespace ImageSharp.Formats.Jpeg.Port
77
{
88
using System;
9-
using System.Buffers;
9+
using System.Collections.Generic;
1010
using System.IO;
11+
using System.Linq;
1112

1213
using ImageSharp.Formats.Jpeg.Port.Components;
1314
using ImageSharp.Memory;
@@ -346,9 +347,9 @@ private void ProcessDefineHuffmanTablesMarker(int remaining)
346347

347348
using (var huffmanData = new Buffer<byte>(remaining))
348349
{
349-
this.InputStream.Read(huffmanData.Array, 1, remaining);
350+
this.InputStream.Skip(1);
351+
this.InputStream.Read(huffmanData.Array, 0, remaining);
350352

351-
int o = 0;
352353
for (int i = 0; i < remaining;)
353354
{
354355
byte huffmanTableSpec = huffmanData[i];
@@ -357,41 +358,95 @@ private void ProcessDefineHuffmanTablesMarker(int remaining)
357358

358359
for (int j = 0; j < 16; j++)
359360
{
360-
codeLengthSum += codeLengths[j] = huffmanData[o++];
361+
codeLengthSum += codeLengths[j] = huffmanData[j];
361362
}
362363

363364
// TODO: Pooling?
364365
short[] huffmanValues = new short[codeLengthSum];
365-
using (var values = new Buffer<byte>(256))
366+
using (var values = new Buffer<byte>(codeLengthSum))
366367
{
367368
this.InputStream.Read(values.Array, 0, codeLengthSum);
368369

369370
for (int j = 0; j < codeLengthSum; j++)
370371
{
371-
huffmanValues[j] = values[o++];
372+
huffmanValues[j] = values[j];
372373
}
373-
}
374374

375-
i += 17 + codeLengthSum;
375+
i += 17 + codeLengthSum;
376376

377-
this.BuildHuffmanTable(
378-
huffmanTableSpec >> 4 == 0 ? this.dcHuffmanTables : this.acHuffmanTables,
379-
huffmanTableSpec & 15,
380-
codeLengths,
381-
huffmanValues);
377+
this.BuildHuffmanTable(
378+
huffmanTableSpec >> 4 == 0 ? this.dcHuffmanTables : this.acHuffmanTables,
379+
huffmanTableSpec & 15,
380+
codeLengths,
381+
huffmanValues);
382+
}
382383
}
383384
}
384385
}
385386

386387
private void BuildHuffmanTable(HuffmanTables tables, int index, byte[] codeLengths, short[] values)
387388
{
389+
// (╯°□°)╯︵ ┻━┻ Everything up to here is going well. I can't match the JavaScript now though.
388390
int length = 16;
389391
while (length > 0 && codeLengths[length - 1] == 0)
390392
{
391393
length--;
392394
}
393395

394-
Span<short> tableSpan = tables.Tables.GetRowSpan(index);
396+
var code = new Queue<HuffmanBranch>();
397+
code.Enqueue(new HuffmanBranch(new List<HuffmanBranch>()));
398+
HuffmanBranch p = code.Peek();
399+
p.Children = new List<HuffmanBranch>();
400+
HuffmanBranch q;
401+
int k = 0;
402+
try
403+
{
404+
for (int i = 0; i < length; i++)
405+
{
406+
for (int j = 0; j < codeLengths[i]; j++)
407+
{
408+
p = code.Dequeue();
409+
p.Children.Add(new HuffmanBranch(values[k]));
410+
while (p.Index > 0)
411+
{
412+
p = code.Dequeue();
413+
}
414+
415+
p.Index++;
416+
code.Enqueue(p);
417+
while (code.Count <= i)
418+
{
419+
q = new HuffmanBranch(new List<HuffmanBranch>());
420+
code.Enqueue(q);
421+
p.Children.Add(new HuffmanBranch(q.Children));
422+
p = q;
423+
}
424+
425+
k++;
426+
}
427+
428+
if (i + 1 < length)
429+
{
430+
// p here points to last code
431+
q = new HuffmanBranch(new List<HuffmanBranch>());
432+
code.Enqueue(q);
433+
p.Children.Add(new HuffmanBranch(q.Children));
434+
p = q;
435+
}
436+
}
437+
438+
Span<HuffmanBranch> tableSpan = tables.Tables.GetRowSpan(index);
439+
440+
List<HuffmanBranch> result = code.Peek().Children;
441+
for (int i = 0; i < result.Count; i++)
442+
{
443+
tableSpan[i] = result[i];
444+
}
445+
}
446+
catch (Exception e)
447+
{
448+
throw;
449+
}
395450
}
396451

397452
/// <summary>

0 commit comments

Comments
 (0)