Browse Source

Baseline decoding seems to work

pull/643/head
James Jackson-South 8 years ago
parent
commit
f064d955c2
  1. 6
      src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/FixedInt16Buffer18.cs
  2. 6
      src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/FixedInt64Buffer18.cs
  3. 22
      src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsHuffmanTable.cs
  4. 70
      src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/ScanDecoder.cs
  5. 6
      src/ImageSharp/Formats/Jpeg/PdfJsPort/PdfJsJpegDecoderCore.cs

6
src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/FixedInt16Buffer18.cs

@ -9,14 +9,14 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
[StructLayout(LayoutKind.Sequential)]
internal unsafe struct FixedInt16Buffer18
{
public fixed short Data[18];
public fixed int Data[18];
public short this[int idx]
public int this[int idx]
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
ref short self = ref Unsafe.As<FixedInt16Buffer18, short>(ref this);
ref int self = ref Unsafe.As<FixedInt16Buffer18, int>(ref this);
return Unsafe.Add(ref self, idx);
}
}

6
src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/FixedInt64Buffer18.cs

@ -9,14 +9,14 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
[StructLayout(LayoutKind.Sequential)]
internal unsafe struct FixedInt64Buffer18
{
public fixed long Data[18];
public fixed uint Data[18];
public long this[int idx]
public uint this[int idx]
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
ref long self = ref Unsafe.As<FixedInt64Buffer18, long>(ref this);
ref uint self = ref Unsafe.As<FixedInt64Buffer18, uint>(ref this);
return Unsafe.Add(ref self, idx);
}
}

22
src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsHuffmanTable.cs

@ -57,15 +57,15 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
int k = 0;
fixed (short* size = this.Sizes.Data)
fixed (short* delta = this.ValOffset.Data)
fixed (long* maxcode = this.MaxCode.Data)
fixed (int* delta = this.ValOffset.Data)
fixed (uint* maxcode = this.MaxCode.Data)
{
uint code = 0;
int j;
for (j = 1; j <= 16; j++)
{
// Compute delta to add to code to compute symbol id.
delta[j] = (short)(k - code);
delta[j] = (int)(k - code);
if (size[k] == j)
{
while (size[k] == j)
@ -89,8 +89,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
fixed (byte* lookaheadRef = this.Lookahead.Data)
{
const int FastBits = ScanDecoder.FastBits;
var fast = new Span<short>(lookaheadRef, 1 << FastBits);
fast.Fill(255); // Flag for non-accelerated
var fast = new Span<byte>(lookaheadRef, 1 << FastBits);
fast.Fill(0xFF); // Flag for non-accelerated
fixed (short* sizesRef = this.Sizes.Data)
{
@ -181,8 +181,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
/// <param name="huffcodeRef">The huffman code span ref</param>
private void GenerateDecoderTables(ReadOnlySpan<byte> lengths, ref short huffcodeRef)
{
fixed (short* valOffsetRef = this.ValOffset.Data)
fixed (long* maxcodeRef = this.MaxCode.Data)
fixed (int* valOffsetRef = this.ValOffset.Data)
fixed (uint* maxcodeRef = this.MaxCode.Data)
{
short bitcount = 0;
for (int i = 1; i <= 16; i++)
@ -190,18 +190,18 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
if (lengths[i] != 0)
{
// valOffsetRef[l] = huffcodeRef[] index of 1st symbol of code length i, minus the minimum code of length i
valOffsetRef[i] = (short)(bitcount - Unsafe.Add(ref huffcodeRef, bitcount));
valOffsetRef[i] = (int)(bitcount - Unsafe.Add(ref huffcodeRef, bitcount));
bitcount += lengths[i];
maxcodeRef[i] = Unsafe.Add(ref huffcodeRef, bitcount - 1) << (16 - i); // maximum code of length i preshifted for faster reading later
maxcodeRef[i] = (uint)Unsafe.Add(ref huffcodeRef, bitcount - 1) << (16 - i); // maximum code of length i preshifted for faster reading later
}
else
{
maxcodeRef[i] = -1; // -1 if no codes of this length
// maxcodeRef[i] = -1; // -1 if no codes of this length
}
}
valOffsetRef[17] = 0;
maxcodeRef[17] = 0xFFFFFFFFL;
maxcodeRef[17] = 0xFFFFFFFF;
}
}

70
src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/ScanDecoder.cs

@ -148,32 +148,39 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
{
for (int i = 0; i < mcusPerLine; i++)
{
// Scan an interleaved mcu... process components in order
for (int k = 0; k < this.componentsLength; k++)
try
{
PdfJsFrameComponent component = this.components[k];
ref short blockDataRef = ref MemoryMarshal.GetReference(MemoryMarshal.Cast<Block8x8, short>(component.SpectralBlocks.Span));
ref PdfJsHuffmanTable dcHuffmanTable = ref dcHuffmanTables[component.DCHuffmanTableId];
ref PdfJsHuffmanTable acHuffmanTable = ref acHuffmanTables[component.ACHuffmanTableId];
Span<short> fastAC = fastACTables.Tables.GetRowSpan(component.ACHuffmanTableId);
int h = component.HorizontalSamplingFactor;
int v = component.VerticalSamplingFactor;
// Scan out an mcu's worth of this component; that's just determined
// by the basic H and V specified for the component
for (int y = 0; y < v; y++)
// Scan an interleaved mcu... process components in order
for (int k = 0; k < this.componentsLength; k++)
{
for (int x = 0; x < h; x++)
PdfJsFrameComponent component = this.components[k];
ref short blockDataRef = ref MemoryMarshal.GetReference(MemoryMarshal.Cast<Block8x8, short>(component.SpectralBlocks.Span));
ref PdfJsHuffmanTable dcHuffmanTable = ref dcHuffmanTables[component.DCHuffmanTableId];
ref PdfJsHuffmanTable acHuffmanTable = ref acHuffmanTables[component.ACHuffmanTableId];
Span<short> fastAC = fastACTables.Tables.GetRowSpan(component.ACHuffmanTableId);
int h = component.HorizontalSamplingFactor;
int v = component.VerticalSamplingFactor;
// Scan out an mcu's worth of this component; that's just determined
// by the basic H and V specified for the component
for (int y = 0; y < v; y++)
{
int mcuRow = mcu / mcusPerLine;
int mcuCol = mcu % mcusPerLine;
int blockRow = (mcuRow * v) + y;
int blockCol = (mcuCol * h) + x;
int offset = component.GetBlockBufferOffset(blockRow, blockCol);
this.DecodeBlock(component, ref Unsafe.Add(ref blockDataRef, offset), ref dcHuffmanTable, ref acHuffmanTable, fastAC);
for (int x = 0; x < h; x++)
{
int mcuRow = mcu / mcusPerLine;
int mcuCol = mcu % mcusPerLine;
int blockRow = (mcuRow * v) + y;
int blockCol = (mcuCol * h) + x;
int offset = component.GetBlockBufferOffset(blockRow, blockCol);
this.DecodeBlock(component, ref Unsafe.Add(ref blockDataRef, offset), ref dcHuffmanTable, ref acHuffmanTable, fastAC);
}
}
}
}
catch
{
break;
}
// After all interleaved components, that's an interleaved MCU,
// so now count down the restart interval
@ -207,7 +214,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
ref short blockDataRef,
ref PdfJsHuffmanTable dcTable,
ref PdfJsHuffmanTable acTable,
Span<short> fac)
Span<short> fastAc)
{
this.CheckBits();
int t = this.DecodeHuffman(ref dcTable);
@ -217,7 +224,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
throw new ImageFormatException("Bad Huffman code");
}
int diff = t > 0 ? this.ExtendReceive(t) : 0;
int diff = t != 0 ? this.ExtendReceive(t) : 0;
int dc = component.DcPredictor + diff;
component.DcPredictor = dc;
blockDataRef = (short)dc;
@ -231,9 +238,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
this.CheckBits();
int c = this.PeekBits();
int r = fac[c];
int r = fastAc[c];
if (r > 0)
if (r != 0)
{
// Fast AC path
k += (r >> 4) & 15; // Run
@ -587,7 +594,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
// if the code is <= FastBits.
int c = this.PeekBits();
int k = table.Lookahead[c];
if (k < byte.MaxValue)
if (k < 0xFF)
{
int s = table.Sizes[k];
if (s > this.codeBits)
@ -628,7 +635,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
}
// Convert the huffman code to the symbol id
c = (int)((this.codeBuffer >> (32 - k)) & Bmask[k]) + table.ValOffset[k];
c = (int)(((this.codeBuffer >> (32 - k)) & Bmask[k]) + table.ValOffset[k]);
// Convert the id to a symbol
this.codeBits -= k;
@ -644,7 +651,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
this.GrowBufferUnsafe();
}
int sgn = (int)(this.codeBuffer >> 31);
int sgn = (int)((int)this.codeBuffer >> 31);
uint k = this.Lrot(this.codeBuffer, n);
this.codeBuffer = k & ~Bmask[n];
k &= Bmask[n];
@ -655,7 +662,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void CheckBits()
{
if (this.codeBuffer < 16)
if (this.codeBits < 16)
{
this.GrowBufferUnsafe();
}
@ -664,7 +671,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private int PeekBits()
{
return (int)(this.codeBuffer >> ((32 - FastBits) & ((1 << FastBits) - 1)));
return (int)((this.codeBuffer >> (32 - FastBits)) & ((1 << FastBits) - 1));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@ -693,11 +700,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
}
this.marker = PdfJsJpegConstants.Markers.Prefix;
this.todo = this.restartInterval > 0 ? this.restartInterval : 0x7FFFFFFF;
this.eobrun = 0;
// No more than 1<<31 MCUs if no restartInterval? that's plenty safe,
// since we don't even allow 1<<30 pixels
// No more than 1<<31 MCUs if no restartInterval? that's plenty safe since we don't even allow 1<<30 pixels
this.todo = this.restartInterval > 0 ? this.restartInterval : 0x7FFFFFFF;
}
}
}

6
src/ImageSharp/Formats/Jpeg/PdfJsPort/PdfJsJpegDecoderCore.cs

@ -808,9 +808,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
sd.ParseEntropyCodedData(this.Frame, this.dcHuffmanTables, this.acHuffmanTables, this.fastACTables);
//var scanDecoder = default(PdfJsScanDecoder);
//scanDecoder.DecodeScan(
// var scanDecoder = default(PdfJsScanDecoder);
//
// scanDecoder.DecodeScan(
// this.Frame,
// this.InputStream,
// this.dcHuffmanTables,

Loading…
Cancel
Save