Browse Source

Baseline decoding seems to work

af/merge-core
James Jackson-South 8 years ago
parent
commit
e1a8ebb644
  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)] [StructLayout(LayoutKind.Sequential)]
internal unsafe struct FixedInt16Buffer18 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)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
get 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); 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)] [StructLayout(LayoutKind.Sequential)]
internal unsafe struct FixedInt64Buffer18 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)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
get 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); 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; int k = 0;
fixed (short* size = this.Sizes.Data) fixed (short* size = this.Sizes.Data)
fixed (short* delta = this.ValOffset.Data) fixed (int* delta = this.ValOffset.Data)
fixed (long* maxcode = this.MaxCode.Data) fixed (uint* maxcode = this.MaxCode.Data)
{ {
uint code = 0; uint code = 0;
int j; int j;
for (j = 1; j <= 16; j++) for (j = 1; j <= 16; j++)
{ {
// Compute delta to add to code to compute symbol id. // Compute delta to add to code to compute symbol id.
delta[j] = (short)(k - code); delta[j] = (int)(k - code);
if (size[k] == j) if (size[k] == j)
{ {
while (size[k] == j) while (size[k] == j)
@ -89,8 +89,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
fixed (byte* lookaheadRef = this.Lookahead.Data) fixed (byte* lookaheadRef = this.Lookahead.Data)
{ {
const int FastBits = ScanDecoder.FastBits; const int FastBits = ScanDecoder.FastBits;
var fast = new Span<short>(lookaheadRef, 1 << FastBits); var fast = new Span<byte>(lookaheadRef, 1 << FastBits);
fast.Fill(255); // Flag for non-accelerated fast.Fill(0xFF); // Flag for non-accelerated
fixed (short* sizesRef = this.Sizes.Data) 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> /// <param name="huffcodeRef">The huffman code span ref</param>
private void GenerateDecoderTables(ReadOnlySpan<byte> lengths, ref short huffcodeRef) private void GenerateDecoderTables(ReadOnlySpan<byte> lengths, ref short huffcodeRef)
{ {
fixed (short* valOffsetRef = this.ValOffset.Data) fixed (int* valOffsetRef = this.ValOffset.Data)
fixed (long* maxcodeRef = this.MaxCode.Data) fixed (uint* maxcodeRef = this.MaxCode.Data)
{ {
short bitcount = 0; short bitcount = 0;
for (int i = 1; i <= 16; i++) for (int i = 1; i <= 16; i++)
@ -190,18 +190,18 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
if (lengths[i] != 0) if (lengths[i] != 0)
{ {
// valOffsetRef[l] = huffcodeRef[] index of 1st symbol of code length i, minus the minimum code of length i // 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]; 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 else
{ {
maxcodeRef[i] = -1; // -1 if no codes of this length // maxcodeRef[i] = -1; // -1 if no codes of this length
} }
} }
valOffsetRef[17] = 0; 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++) for (int i = 0; i < mcusPerLine; i++)
{ {
// Scan an interleaved mcu... process components in order try
for (int k = 0; k < this.componentsLength; k++)
{ {
PdfJsFrameComponent component = this.components[k]; // Scan an interleaved mcu... process components in order
ref short blockDataRef = ref MemoryMarshal.GetReference(MemoryMarshal.Cast<Block8x8, short>(component.SpectralBlocks.Span)); for (int k = 0; k < this.componentsLength; k++)
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++)
{ {
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; for (int x = 0; x < h; x++)
int mcuCol = mcu % mcusPerLine; {
int blockRow = (mcuRow * v) + y; int mcuRow = mcu / mcusPerLine;
int blockCol = (mcuCol * h) + x; int mcuCol = mcu % mcusPerLine;
int offset = component.GetBlockBufferOffset(blockRow, blockCol); int blockRow = (mcuRow * v) + y;
this.DecodeBlock(component, ref Unsafe.Add(ref blockDataRef, offset), ref dcHuffmanTable, ref acHuffmanTable, fastAC); 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, // After all interleaved components, that's an interleaved MCU,
// so now count down the restart interval // so now count down the restart interval
@ -207,7 +214,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
ref short blockDataRef, ref short blockDataRef,
ref PdfJsHuffmanTable dcTable, ref PdfJsHuffmanTable dcTable,
ref PdfJsHuffmanTable acTable, ref PdfJsHuffmanTable acTable,
Span<short> fac) Span<short> fastAc)
{ {
this.CheckBits(); this.CheckBits();
int t = this.DecodeHuffman(ref dcTable); int t = this.DecodeHuffman(ref dcTable);
@ -217,7 +224,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
throw new ImageFormatException("Bad Huffman code"); 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; int dc = component.DcPredictor + diff;
component.DcPredictor = dc; component.DcPredictor = dc;
blockDataRef = (short)dc; blockDataRef = (short)dc;
@ -231,9 +238,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
this.CheckBits(); this.CheckBits();
int c = this.PeekBits(); int c = this.PeekBits();
int r = fac[c]; int r = fastAc[c];
if (r > 0) if (r != 0)
{ {
// Fast AC path // Fast AC path
k += (r >> 4) & 15; // Run k += (r >> 4) & 15; // Run
@ -587,7 +594,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
// if the code is <= FastBits. // if the code is <= FastBits.
int c = this.PeekBits(); int c = this.PeekBits();
int k = table.Lookahead[c]; int k = table.Lookahead[c];
if (k < byte.MaxValue) if (k < 0xFF)
{ {
int s = table.Sizes[k]; int s = table.Sizes[k];
if (s > this.codeBits) if (s > this.codeBits)
@ -628,7 +635,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
} }
// Convert the huffman code to the symbol id // 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 // Convert the id to a symbol
this.codeBits -= k; this.codeBits -= k;
@ -644,7 +651,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
this.GrowBufferUnsafe(); this.GrowBufferUnsafe();
} }
int sgn = (int)(this.codeBuffer >> 31); int sgn = (int)((int)this.codeBuffer >> 31);
uint k = this.Lrot(this.codeBuffer, n); uint k = this.Lrot(this.codeBuffer, n);
this.codeBuffer = k & ~Bmask[n]; this.codeBuffer = k & ~Bmask[n];
k &= Bmask[n]; k &= Bmask[n];
@ -655,7 +662,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private void CheckBits() private void CheckBits()
{ {
if (this.codeBuffer < 16) if (this.codeBits < 16)
{ {
this.GrowBufferUnsafe(); this.GrowBufferUnsafe();
} }
@ -664,7 +671,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private int PeekBits() private int PeekBits()
{ {
return (int)(this.codeBuffer >> ((32 - FastBits) & ((1 << FastBits) - 1))); return (int)((this.codeBuffer >> (32 - FastBits)) & ((1 << FastBits) - 1));
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
@ -693,11 +700,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
} }
this.marker = PdfJsJpegConstants.Markers.Prefix; this.marker = PdfJsJpegConstants.Markers.Prefix;
this.todo = this.restartInterval > 0 ? this.restartInterval : 0x7FFFFFFF;
this.eobrun = 0; this.eobrun = 0;
// No more than 1<<31 MCUs if no restartInterval? that's plenty safe, // No more than 1<<31 MCUs if no restartInterval? that's plenty safe since we don't even allow 1<<30 pixels
// 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); sd.ParseEntropyCodedData(this.Frame, this.dcHuffmanTables, this.acHuffmanTables, this.fastACTables);
//var scanDecoder = default(PdfJsScanDecoder); // var scanDecoder = default(PdfJsScanDecoder);
//
//scanDecoder.DecodeScan( // scanDecoder.DecodeScan(
// this.Frame, // this.Frame,
// this.InputStream, // this.InputStream,
// this.dcHuffmanTables, // this.dcHuffmanTables,

Loading…
Cancel
Save