Browse Source

Faster scan decoder

pull/525/head
James Jackson-South 9 years ago
parent
commit
28facaf98d
  1. 24
      src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/FixedByteBuffer256.cs
  2. 24
      src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/FixedInt16Buffer18.cs
  3. 24
      src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/FixedInt16Buffer256.cs
  4. 24
      src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/FixedInt64Buffer18.cs
  5. 120
      src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsHuffmanTable.cs
  6. 14
      src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsHuffmanTables.cs
  7. 132
      src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsScanDecoder.cs
  8. 14
      src/ImageSharp/Formats/Jpeg/PdfJsPort/PdfJsJpegDecoderCore.cs

24
src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/FixedByteBuffer256.cs

@ -0,0 +1,24 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
{
[StructLayout(LayoutKind.Sequential)]
internal unsafe struct FixedByteBuffer256
{
public fixed byte Data[256];
public byte this[int idx]
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
ref byte self = ref Unsafe.As<FixedByteBuffer256, byte>(ref this);
return Unsafe.Add(ref self, idx);
}
}
}
}

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

@ -0,0 +1,24 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
{
[StructLayout(LayoutKind.Sequential)]
internal unsafe struct FixedInt16Buffer18
{
public fixed short Data[18];
public short this[int idx]
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
ref short self = ref Unsafe.As<FixedInt16Buffer18, short>(ref this);
return Unsafe.Add(ref self, idx);
}
}
}
}

24
src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/FixedInt16Buffer256.cs

@ -0,0 +1,24 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
{
[StructLayout(LayoutKind.Sequential)]
internal unsafe struct FixedInt16Buffer256
{
public fixed short Data[256];
public short this[int idx]
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
ref short self = ref Unsafe.As<FixedInt16Buffer256, short>(ref this);
return Unsafe.Add(ref self, idx);
}
}
}
}

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

@ -0,0 +1,24 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
{
[StructLayout(LayoutKind.Sequential)]
internal unsafe struct FixedInt64Buffer18
{
public fixed long Data[18];
public long this[int idx]
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
ref long self = ref Unsafe.As<FixedInt64Buffer18, long>(ref this);
return Unsafe.Add(ref self, idx);
}
}
}
}

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

@ -2,7 +2,6 @@
// Licensed under the Apache License, Version 2.0. // Licensed under the Apache License, Version 2.0.
using System; using System;
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.Memory;
namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
@ -10,12 +9,27 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
/// <summary> /// <summary>
/// Represents a Huffman Table /// Represents a Huffman Table
/// </summary> /// </summary>
internal struct PdfJsHuffmanTable : IDisposable internal unsafe struct PdfJsHuffmanTable
{ {
private BasicArrayBuffer<short> lookahead; /// <summary>
private BasicArrayBuffer<short> valOffset; /// Gets the max code array
private BasicArrayBuffer<long> maxcode; /// </summary>
private IManagedByteBuffer huffval; public FixedInt64Buffer18 MaxCode;
/// <summary>
/// Gets the value offset array
/// </summary>
public FixedInt16Buffer18 ValOffset;
/// <summary>
/// Gets the huffman value array
/// </summary>
public FixedByteBuffer256 HuffVal;
/// <summary>
/// Gets the lookahead array
/// </summary>
public FixedInt16Buffer256 Lookahead;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="PdfJsHuffmanTable"/> struct. /// Initializes a new instance of the <see cref="PdfJsHuffmanTable"/> struct.
@ -25,77 +39,22 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
/// <param name="values">The huffman values</param> /// <param name="values">The huffman values</param>
public PdfJsHuffmanTable(MemoryManager memoryManager, byte[] lengths, byte[] values) public PdfJsHuffmanTable(MemoryManager memoryManager, byte[] lengths, byte[] values)
{ {
// TODO: Replace FakeBuffer<T> usages with standard or array orfixed-sized arrays
this.lookahead = memoryManager.AllocateFake<short>(256);
this.valOffset = memoryManager.AllocateFake<short>(18);
this.maxcode = memoryManager.AllocateFake<long>(18);
using (IBuffer<short> huffsize = memoryManager.Allocate<short>(257)) using (IBuffer<short> huffsize = memoryManager.Allocate<short>(257))
using (IBuffer<short> huffcode = memoryManager.Allocate<short>(257)) using (IBuffer<short> huffcode = memoryManager.Allocate<short>(257))
{ {
GenerateSizeTable(lengths, huffsize.Span); GenerateSizeTable(lengths, huffsize.Span);
GenerateCodeTable(huffsize.Span, huffcode.Span); GenerateCodeTable(huffsize.Span, huffcode.Span);
GenerateDecoderTables(lengths, huffcode.Span, this.valOffset.Span, this.maxcode.Span); this.GenerateDecoderTables(lengths, huffcode.Span);
GenerateLookaheadTables(lengths, values, this.lookahead.Span); this.GenerateLookaheadTables(lengths, values);
} }
this.huffval = memoryManager.AllocateManagedByteBuffer(values.Length, true); fixed (byte* huffValRef = this.HuffVal.Data)
Buffer.BlockCopy(values, 0, this.huffval.Array, 0, values.Length);
this.MaxCode = this.maxcode.Array;
this.ValOffset = this.valOffset.Array;
this.HuffVal = this.huffval.Array;
this.Lookahead = this.lookahead.Array;
}
/// <summary>
/// Gets the max code array
/// </summary>
public long[] MaxCode
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining)] for (int i = 0; i < values.Length; i++)
get;
}
/// <summary>
/// Gets the value offset array
/// </summary>
public short[] ValOffset
{ {
[MethodImpl(MethodImplOptions.AggressiveInlining)] huffValRef[i] = values[i];
get;
} }
/// <summary>
/// Gets the huffman value array
/// </summary>
public byte[] HuffVal
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get;
}
/// <summary>
/// Gets the lookahead array
/// </summary>
public short[] Lookahead
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get;
} }
/// <inheritdoc/>
public void Dispose()
{
this.lookahead?.Dispose();
this.valOffset?.Dispose();
this.maxcode?.Dispose();
this.huffval?.Dispose();
this.lookahead = null;
this.valOffset = null;
this.maxcode = null;
this.huffval = null;
} }
/// <summary> /// <summary>
@ -148,29 +107,30 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
/// </summary> /// </summary>
/// <param name="lengths">The code lengths</param> /// <param name="lengths">The code lengths</param>
/// <param name="huffcode">The huffman code span</param> /// <param name="huffcode">The huffman code span</param>
/// <param name="valOffset">The value offset span</param> private void GenerateDecoderTables(byte[] lengths, Span<short> huffcode)
/// <param name="maxcode">The max code span</param> {
private static void GenerateDecoderTables(byte[] lengths, Span<short> huffcode, Span<short> valOffset, Span<long> maxcode) fixed (short* valOffsetRef = this.ValOffset.Data)
fixed (long* maxcodeRef = this.MaxCode.Data)
{ {
short bitcount = 0; short bitcount = 0;
for (int i = 1; i <= 16; i++) for (int i = 1; i <= 16; i++)
{ {
if (lengths[i] != 0) if (lengths[i] != 0)
{ {
// valoffset[l] = huffval[] index of 1st symbol of code length i, // valOffsetRef[l] = huffval[] index of 1st symbol of code length i, minus the minimum code of length i
// minus the minimum code of length i valOffsetRef[i] = (short)(bitcount - huffcode[bitcount]);
valOffset[i] = (short)(bitcount - huffcode[bitcount]);
bitcount += lengths[i]; bitcount += lengths[i];
maxcode[i] = huffcode[bitcount - 1]; // maximum code of length i maxcodeRef[i] = huffcode[bitcount - 1]; // maximum code of length i
} }
else else
{ {
maxcode[i] = -1; // -1 if no codes of this length maxcodeRef[i] = -1; // -1 if no codes of this length
} }
} }
valOffset[17] = 0; valOffsetRef[17] = 0;
maxcode[17] = 0xFFFFFL; maxcodeRef[17] = 0xFFFFFL;
}
} }
/// <summary> /// <summary>
@ -178,8 +138,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
/// </summary> /// </summary>
/// <param name="lengths">The code lengths</param> /// <param name="lengths">The code lengths</param>
/// <param name="huffval">The huffman value array</param> /// <param name="huffval">The huffman value array</param>
/// <param name="lookahead">The lookahead span</param> private void GenerateLookaheadTables(byte[] lengths, byte[] huffval)
private static void GenerateLookaheadTables(byte[] lengths, byte[] huffval, Span<short> lookahead) {
fixed (short* lookaheadRef = this.Lookahead.Data)
{ {
int x = 0, code = 0; int x = 0, code = 0;
@ -199,7 +160,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
for (int k = 0; k < 1 << (7 - i); k++) for (int k = 0; k < 1 << (7 - i); k++)
{ {
lookahead[base2 | k] = lutValue; lookaheadRef[base2 | k] = lutValue;
} }
code++; code++;
@ -208,4 +169,5 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
} }
} }
} }
}
} }

14
src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsHuffmanTables.cs

@ -1,16 +1,15 @@
// Copyright (c) Six Labors and contributors. // Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0. // Licensed under the Apache License, Version 2.0.
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
{ {
/// <summary> /// <summary>
/// Defines a pair of huffman tables /// Defines a 2 pairs of huffman tables
/// </summary> /// </summary>
internal sealed class PdfJsHuffmanTables : IDisposable internal sealed class PdfJsHuffmanTables
{ {
private readonly PdfJsHuffmanTable[] tables = new PdfJsHuffmanTable[4]; private readonly PdfJsHuffmanTable[] tables = new PdfJsHuffmanTable[4];
@ -27,14 +26,5 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
return ref this.tables[index]; return ref this.tables[index];
} }
} }
/// <inheritdoc/>
public void Dispose()
{
for (int i = 0; i < this.tables.Length; i++)
{
this.tables[i].Dispose();
}
}
} }
} }

132
src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsScanDecoder.cs

@ -5,6 +5,7 @@ using System;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
{ {
@ -172,7 +173,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
fileMarker = PdfJsJpegDecoderCore.FindNextFileMarker(this.markerBuffer, stream); fileMarker = PdfJsJpegDecoderCore.FindNextFileMarker(this.markerBuffer, stream);
// Some images include more Scan blocks than expected, skip past those and // Some images include more Scan blocks than expected, skip past those and
// attempt to find the next valid marker (fixes issue8182.pdf) in original code. // attempt to find the next valid marker (fixes issue8182.pdf) ref original code.
if (fileMarker.Invalid) if (fileMarker.Invalid)
{ {
#if DEBUG #if DEBUG
@ -201,6 +202,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
if (componentsLength == 1) if (componentsLength == 1)
{ {
PdfJsFrameComponent component = components[this.compIndex]; PdfJsFrameComponent component = components[this.compIndex];
ref short blockDataRef = ref MemoryMarshal.GetReference(component.BlockData.Span);
ref PdfJsHuffmanTable dcHuffmanTable = ref dcHuffmanTables[component.DCHuffmanTableId]; ref PdfJsHuffmanTable dcHuffmanTable = ref dcHuffmanTables[component.DCHuffmanTableId];
ref PdfJsHuffmanTable acHuffmanTable = ref acHuffmanTables[component.ACHuffmanTableId]; ref PdfJsHuffmanTable acHuffmanTable = ref acHuffmanTables[component.ACHuffmanTableId];
@ -211,7 +213,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
continue; continue;
} }
this.DecodeBlockBaseline(ref dcHuffmanTable, ref acHuffmanTable, component, mcu, stream); this.DecodeBlockBaseline(ref dcHuffmanTable, ref acHuffmanTable, component, ref blockDataRef, mcu, stream);
mcu++; mcu++;
} }
} }
@ -222,6 +224,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
for (int i = 0; i < componentsLength; i++) for (int i = 0; i < componentsLength; i++)
{ {
PdfJsFrameComponent component = components[i]; PdfJsFrameComponent component = components[i];
ref short blockDataRef = ref MemoryMarshal.GetReference(component.BlockData.Span);
ref PdfJsHuffmanTable dcHuffmanTable = ref dcHuffmanTables[component.DCHuffmanTableId]; ref PdfJsHuffmanTable dcHuffmanTable = ref dcHuffmanTables[component.DCHuffmanTableId];
ref PdfJsHuffmanTable acHuffmanTable = ref acHuffmanTables[component.ACHuffmanTableId]; ref PdfJsHuffmanTable acHuffmanTable = ref acHuffmanTables[component.ACHuffmanTableId];
int h = component.HorizontalSamplingFactor; int h = component.HorizontalSamplingFactor;
@ -236,7 +239,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
continue; continue;
} }
this.DecodeMcuBaseline(ref dcHuffmanTable, ref acHuffmanTable, component, mcusPerLine, mcu, j, k, stream); this.DecodeMcuBaseline(ref dcHuffmanTable, ref acHuffmanTable, component, ref blockDataRef, mcusPerLine, mcu, j, k, stream);
} }
} }
} }
@ -259,6 +262,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
if (componentsLength == 1) if (componentsLength == 1)
{ {
PdfJsFrameComponent component = components[this.compIndex]; PdfJsFrameComponent component = components[this.compIndex];
ref short blockDataRef = ref MemoryMarshal.GetReference(component.BlockData.Span);
ref PdfJsHuffmanTable dcHuffmanTable = ref dcHuffmanTables[component.DCHuffmanTableId]; ref PdfJsHuffmanTable dcHuffmanTable = ref dcHuffmanTables[component.DCHuffmanTableId];
for (int n = 0; n < mcuToRead; n++) for (int n = 0; n < mcuToRead; n++)
@ -268,7 +272,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
continue; continue;
} }
this.DecodeBlockDCFirst(ref dcHuffmanTable, component, mcu, stream); this.DecodeBlockDCFirst(ref dcHuffmanTable, component, ref blockDataRef, mcu, stream);
mcu++; mcu++;
} }
} }
@ -279,6 +283,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
for (int i = 0; i < componentsLength; i++) for (int i = 0; i < componentsLength; i++)
{ {
PdfJsFrameComponent component = components[i]; PdfJsFrameComponent component = components[i];
ref short blockDataRef = ref MemoryMarshal.GetReference(component.BlockData.Span);
ref PdfJsHuffmanTable dcHuffmanTable = ref dcHuffmanTables[component.DCHuffmanTableId]; ref PdfJsHuffmanTable dcHuffmanTable = ref dcHuffmanTables[component.DCHuffmanTableId];
int h = component.HorizontalSamplingFactor; int h = component.HorizontalSamplingFactor;
int v = component.VerticalSamplingFactor; int v = component.VerticalSamplingFactor;
@ -292,7 +297,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
continue; continue;
} }
this.DecodeMcuDCFirst(ref dcHuffmanTable, component, mcusPerLine, mcu, j, k, stream); this.DecodeMcuDCFirst(ref dcHuffmanTable, component, ref blockDataRef, mcusPerLine, mcu, j, k, stream);
} }
} }
} }
@ -314,6 +319,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
if (componentsLength == 1) if (componentsLength == 1)
{ {
PdfJsFrameComponent component = components[this.compIndex]; PdfJsFrameComponent component = components[this.compIndex];
ref short blockDataRef = ref MemoryMarshal.GetReference(component.BlockData.Span);
for (int n = 0; n < mcuToRead; n++) for (int n = 0; n < mcuToRead; n++)
{ {
if (this.endOfStreamReached || this.unexpectedMarkerReached) if (this.endOfStreamReached || this.unexpectedMarkerReached)
@ -321,7 +328,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
continue; continue;
} }
this.DecodeBlockDCSuccessive(component, mcu, stream); this.DecodeBlockDCSuccessive(component, ref blockDataRef, mcu, stream);
mcu++; mcu++;
} }
} }
@ -334,6 +341,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
PdfJsFrameComponent component = components[i]; PdfJsFrameComponent component = components[i];
int h = component.HorizontalSamplingFactor; int h = component.HorizontalSamplingFactor;
int v = component.VerticalSamplingFactor; int v = component.VerticalSamplingFactor;
ref short blockDataRef = ref MemoryMarshal.GetReference(component.BlockData.Span);
for (int j = 0; j < v; j++) for (int j = 0; j < v; j++)
{ {
for (int k = 0; k < h; k++) for (int k = 0; k < h; k++)
@ -343,7 +352,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
continue; continue;
} }
this.DecodeMcuDCSuccessive(component, mcusPerLine, mcu, j, k, stream); this.DecodeMcuDCSuccessive(component, ref blockDataRef, mcusPerLine, mcu, j, k, stream);
} }
} }
} }
@ -366,6 +375,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
if (componentsLength == 1) if (componentsLength == 1)
{ {
PdfJsFrameComponent component = components[this.compIndex]; PdfJsFrameComponent component = components[this.compIndex];
ref short blockDataRef = ref MemoryMarshal.GetReference(component.BlockData.Span);
ref PdfJsHuffmanTable acHuffmanTable = ref acHuffmanTables[component.ACHuffmanTableId]; ref PdfJsHuffmanTable acHuffmanTable = ref acHuffmanTables[component.ACHuffmanTableId];
for (int n = 0; n < mcuToRead; n++) for (int n = 0; n < mcuToRead; n++)
@ -375,7 +385,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
continue; continue;
} }
this.DecodeBlockACFirst(ref acHuffmanTable, component, mcu, stream); this.DecodeBlockACFirst(ref acHuffmanTable, component, ref blockDataRef, mcu, stream);
mcu++; mcu++;
} }
} }
@ -386,6 +396,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
for (int i = 0; i < componentsLength; i++) for (int i = 0; i < componentsLength; i++)
{ {
PdfJsFrameComponent component = components[i]; PdfJsFrameComponent component = components[i];
ref short blockDataRef = ref MemoryMarshal.GetReference(component.BlockData.Span);
ref PdfJsHuffmanTable acHuffmanTable = ref acHuffmanTables[component.ACHuffmanTableId]; ref PdfJsHuffmanTable acHuffmanTable = ref acHuffmanTables[component.ACHuffmanTableId];
int h = component.HorizontalSamplingFactor; int h = component.HorizontalSamplingFactor;
int v = component.VerticalSamplingFactor; int v = component.VerticalSamplingFactor;
@ -399,7 +410,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
continue; continue;
} }
this.DecodeMcuACFirst(ref acHuffmanTable, component, mcusPerLine, mcu, j, k, stream); this.DecodeMcuACFirst(ref acHuffmanTable, component, ref blockDataRef, mcusPerLine, mcu, j, k, stream);
} }
} }
} }
@ -422,6 +433,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
if (componentsLength == 1) if (componentsLength == 1)
{ {
PdfJsFrameComponent component = components[this.compIndex]; PdfJsFrameComponent component = components[this.compIndex];
ref short blockDataRef = ref MemoryMarshal.GetReference(component.BlockData.Span);
ref PdfJsHuffmanTable acHuffmanTable = ref acHuffmanTables[component.ACHuffmanTableId]; ref PdfJsHuffmanTable acHuffmanTable = ref acHuffmanTables[component.ACHuffmanTableId];
for (int n = 0; n < mcuToRead; n++) for (int n = 0; n < mcuToRead; n++)
@ -431,7 +443,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
continue; continue;
} }
this.DecodeBlockACSuccessive(ref acHuffmanTable, component, mcu, stream); this.DecodeBlockACSuccessive(ref acHuffmanTable, component, ref blockDataRef, mcu, stream);
mcu++; mcu++;
} }
} }
@ -442,6 +454,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
for (int i = 0; i < componentsLength; i++) for (int i = 0; i < componentsLength; i++)
{ {
PdfJsFrameComponent component = components[i]; PdfJsFrameComponent component = components[i];
ref short blockDataRef = ref MemoryMarshal.GetReference(component.BlockData.Span);
ref PdfJsHuffmanTable acHuffmanTable = ref acHuffmanTables[component.ACHuffmanTableId]; ref PdfJsHuffmanTable acHuffmanTable = ref acHuffmanTables[component.ACHuffmanTableId];
int h = component.HorizontalSamplingFactor; int h = component.HorizontalSamplingFactor;
int v = component.VerticalSamplingFactor; int v = component.VerticalSamplingFactor;
@ -455,7 +468,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
continue; continue;
} }
this.DecodeMcuACSuccessive(ref acHuffmanTable, component, mcusPerLine, mcu, j, k, stream); this.DecodeMcuACSuccessive(ref acHuffmanTable, component, ref blockDataRef, mcusPerLine, mcu, j, k, stream);
} }
} }
} }
@ -466,103 +479,103 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private void DecodeBlockBaseline(ref PdfJsHuffmanTable dcHuffmanTable, ref PdfJsHuffmanTable acHuffmanTable, PdfJsFrameComponent component, int mcu, Stream stream) private void DecodeBlockBaseline(ref PdfJsHuffmanTable dcHuffmanTable, ref PdfJsHuffmanTable acHuffmanTable, PdfJsFrameComponent component, ref short blockDataRef, int mcu, Stream stream)
{ {
int blockRow = mcu / component.WidthInBlocks; int blockRow = mcu / component.WidthInBlocks;
int blockCol = mcu % component.WidthInBlocks; int blockCol = mcu % component.WidthInBlocks;
int offset = component.GetBlockBufferOffset(blockRow, blockCol); int offset = component.GetBlockBufferOffset(blockRow, blockCol);
this.DecodeBaseline(component, offset, ref dcHuffmanTable, ref acHuffmanTable, stream); this.DecodeBaseline(component, ref blockDataRef, offset, ref dcHuffmanTable, ref acHuffmanTable, stream);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private void DecodeMcuBaseline(ref PdfJsHuffmanTable dcHuffmanTable, ref PdfJsHuffmanTable acHuffmanTable, PdfJsFrameComponent component, int mcusPerLine, int mcu, int row, int col, Stream stream) private void DecodeMcuBaseline(ref PdfJsHuffmanTable dcHuffmanTable, ref PdfJsHuffmanTable acHuffmanTable, PdfJsFrameComponent component, ref short blockDataRef, int mcusPerLine, int mcu, int row, int col, Stream stream)
{ {
int mcuRow = mcu / mcusPerLine; int mcuRow = mcu / mcusPerLine;
int mcuCol = mcu % mcusPerLine; int mcuCol = mcu % mcusPerLine;
int blockRow = (mcuRow * component.VerticalSamplingFactor) + row; int blockRow = (mcuRow * component.VerticalSamplingFactor) + row;
int blockCol = (mcuCol * component.HorizontalSamplingFactor) + col; int blockCol = (mcuCol * component.HorizontalSamplingFactor) + col;
int offset = component.GetBlockBufferOffset(blockRow, blockCol); int offset = component.GetBlockBufferOffset(blockRow, blockCol);
this.DecodeBaseline(component, offset, ref dcHuffmanTable, ref acHuffmanTable, stream); this.DecodeBaseline(component, ref blockDataRef, offset, ref dcHuffmanTable, ref acHuffmanTable, stream);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private void DecodeBlockDCFirst(ref PdfJsHuffmanTable dcHuffmanTable, PdfJsFrameComponent component, int mcu, Stream stream) private void DecodeBlockDCFirst(ref PdfJsHuffmanTable dcHuffmanTable, PdfJsFrameComponent component, ref short blockDataRef, int mcu, Stream stream)
{ {
int blockRow = mcu / component.WidthInBlocks; int blockRow = mcu / component.WidthInBlocks;
int blockCol = mcu % component.WidthInBlocks; int blockCol = mcu % component.WidthInBlocks;
int offset = component.GetBlockBufferOffset(blockRow, blockCol); int offset = component.GetBlockBufferOffset(blockRow, blockCol);
this.DecodeDCFirst(component, offset, ref dcHuffmanTable, stream); this.DecodeDCFirst(component, ref blockDataRef, offset, ref dcHuffmanTable, stream);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private void DecodeMcuDCFirst(ref PdfJsHuffmanTable dcHuffmanTable, PdfJsFrameComponent component, int mcusPerLine, int mcu, int row, int col, Stream stream) private void DecodeMcuDCFirst(ref PdfJsHuffmanTable dcHuffmanTable, PdfJsFrameComponent component, ref short blockDataRef, int mcusPerLine, int mcu, int row, int col, Stream stream)
{ {
int mcuRow = mcu / mcusPerLine; int mcuRow = mcu / mcusPerLine;
int mcuCol = mcu % mcusPerLine; int mcuCol = mcu % mcusPerLine;
int blockRow = (mcuRow * component.VerticalSamplingFactor) + row; int blockRow = (mcuRow * component.VerticalSamplingFactor) + row;
int blockCol = (mcuCol * component.HorizontalSamplingFactor) + col; int blockCol = (mcuCol * component.HorizontalSamplingFactor) + col;
int offset = component.GetBlockBufferOffset(blockRow, blockCol); int offset = component.GetBlockBufferOffset(blockRow, blockCol);
this.DecodeDCFirst(component, offset, ref dcHuffmanTable, stream); this.DecodeDCFirst(component, ref blockDataRef, offset, ref dcHuffmanTable, stream);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private void DecodeBlockDCSuccessive(PdfJsFrameComponent component, int mcu, Stream stream) private void DecodeBlockDCSuccessive(PdfJsFrameComponent component, ref short blockDataRef, int mcu, Stream stream)
{ {
int blockRow = mcu / component.WidthInBlocks; int blockRow = mcu / component.WidthInBlocks;
int blockCol = mcu % component.WidthInBlocks; int blockCol = mcu % component.WidthInBlocks;
int offset = component.GetBlockBufferOffset(blockRow, blockCol); int offset = component.GetBlockBufferOffset(blockRow, blockCol);
this.DecodeDCSuccessive(component, offset, stream); this.DecodeDCSuccessive(component, ref blockDataRef, offset, stream);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private void DecodeMcuDCSuccessive(PdfJsFrameComponent component, int mcusPerLine, int mcu, int row, int col, Stream stream) private void DecodeMcuDCSuccessive(PdfJsFrameComponent component, ref short blockDataRef, int mcusPerLine, int mcu, int row, int col, Stream stream)
{ {
int mcuRow = mcu / mcusPerLine; int mcuRow = mcu / mcusPerLine;
int mcuCol = mcu % mcusPerLine; int mcuCol = mcu % mcusPerLine;
int blockRow = (mcuRow * component.VerticalSamplingFactor) + row; int blockRow = (mcuRow * component.VerticalSamplingFactor) + row;
int blockCol = (mcuCol * component.HorizontalSamplingFactor) + col; int blockCol = (mcuCol * component.HorizontalSamplingFactor) + col;
int offset = component.GetBlockBufferOffset(blockRow, blockCol); int offset = component.GetBlockBufferOffset(blockRow, blockCol);
this.DecodeDCSuccessive(component, offset, stream); this.DecodeDCSuccessive(component, ref blockDataRef, offset, stream);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private void DecodeBlockACFirst(ref PdfJsHuffmanTable acHuffmanTable, PdfJsFrameComponent component, int mcu, Stream stream) private void DecodeBlockACFirst(ref PdfJsHuffmanTable acHuffmanTable, PdfJsFrameComponent component, ref short blockDataRef, int mcu, Stream stream)
{ {
int blockRow = mcu / component.WidthInBlocks; int blockRow = mcu / component.WidthInBlocks;
int blockCol = mcu % component.WidthInBlocks; int blockCol = mcu % component.WidthInBlocks;
int offset = component.GetBlockBufferOffset(blockRow, blockCol); int offset = component.GetBlockBufferOffset(blockRow, blockCol);
this.DecodeACFirst(component, offset, ref acHuffmanTable, stream); this.DecodeACFirst(component, ref blockDataRef, offset, ref acHuffmanTable, stream);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private void DecodeMcuACFirst(ref PdfJsHuffmanTable acHuffmanTable, PdfJsFrameComponent component, int mcusPerLine, int mcu, int row, int col, Stream stream) private void DecodeMcuACFirst(ref PdfJsHuffmanTable acHuffmanTable, PdfJsFrameComponent component, ref short blockDataRef, int mcusPerLine, int mcu, int row, int col, Stream stream)
{ {
int mcuRow = mcu / mcusPerLine; int mcuRow = mcu / mcusPerLine;
int mcuCol = mcu % mcusPerLine; int mcuCol = mcu % mcusPerLine;
int blockRow = (mcuRow * component.VerticalSamplingFactor) + row; int blockRow = (mcuRow * component.VerticalSamplingFactor) + row;
int blockCol = (mcuCol * component.HorizontalSamplingFactor) + col; int blockCol = (mcuCol * component.HorizontalSamplingFactor) + col;
int offset = component.GetBlockBufferOffset(blockRow, blockCol); int offset = component.GetBlockBufferOffset(blockRow, blockCol);
this.DecodeACFirst(component, offset, ref acHuffmanTable, stream); this.DecodeACFirst(component, ref blockDataRef, offset, ref acHuffmanTable, stream);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private void DecodeBlockACSuccessive(ref PdfJsHuffmanTable acHuffmanTable, PdfJsFrameComponent component, int mcu, Stream stream) private void DecodeBlockACSuccessive(ref PdfJsHuffmanTable acHuffmanTable, PdfJsFrameComponent component, ref short blockDataRef, int mcu, Stream stream)
{ {
int blockRow = mcu / component.WidthInBlocks; int blockRow = mcu / component.WidthInBlocks;
int blockCol = mcu % component.WidthInBlocks; int blockCol = mcu % component.WidthInBlocks;
int offset = component.GetBlockBufferOffset(blockRow, blockCol); int offset = component.GetBlockBufferOffset(blockRow, blockCol);
this.DecodeACSuccessive(component, offset, ref acHuffmanTable, stream); this.DecodeACSuccessive(component, ref blockDataRef, offset, ref acHuffmanTable, stream);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private void DecodeMcuACSuccessive(ref PdfJsHuffmanTable acHuffmanTable, PdfJsFrameComponent component, int mcusPerLine, int mcu, int row, int col, Stream stream) private void DecodeMcuACSuccessive(ref PdfJsHuffmanTable acHuffmanTable, PdfJsFrameComponent component, ref short blockDataRef, int mcusPerLine, int mcu, int row, int col, Stream stream)
{ {
int mcuRow = mcu / mcusPerLine; int mcuRow = mcu / mcusPerLine;
int mcuCol = mcu % mcusPerLine; int mcuCol = mcu % mcusPerLine;
int blockRow = (mcuRow * component.VerticalSamplingFactor) + row; int blockRow = (mcuRow * component.VerticalSamplingFactor) + row;
int blockCol = (mcuCol * component.HorizontalSamplingFactor) + col; int blockCol = (mcuCol * component.HorizontalSamplingFactor) + col;
int offset = component.GetBlockBufferOffset(blockRow, blockCol); int offset = component.GetBlockBufferOffset(blockRow, blockCol);
this.DecodeACSuccessive(component, offset, ref acHuffmanTable, stream); this.DecodeACSuccessive(component, ref blockDataRef, offset, ref acHuffmanTable, stream);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
@ -579,7 +592,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
if (this.bitsData == -0x1) if (this.bitsData == -0x1)
{ {
// We've encountered the end of the file stream which means there's no EOI marker in the image // We've encountered the end of the file stream which means there's no EOI marker ref the image
this.endOfStreamReached = true; this.endOfStreamReached = true;
} }
@ -705,23 +718,21 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private void DecodeBaseline(PdfJsFrameComponent component, int offset, ref PdfJsHuffmanTable dcHuffmanTable, ref PdfJsHuffmanTable acHuffmanTable, Stream stream) private void DecodeBaseline(PdfJsFrameComponent component, ref short blockDataRef, int offset, ref PdfJsHuffmanTable dcHuffmanTable, ref PdfJsHuffmanTable acHuffmanTable, Stream stream)
{ {
Span<short> blockDataSpan = component.BlockData.Span; short t = this.DecodeHuffman(ref dcHuffmanTable, stream);
int t = this.DecodeHuffman(ref dcHuffmanTable, stream);
if (this.endOfStreamReached || this.unexpectedMarkerReached) if (this.endOfStreamReached || this.unexpectedMarkerReached)
{ {
return; return;
} }
int diff = t == 0 ? 0 : this.ReceiveAndExtend(t, stream); int diff = t == 0 ? 0 : this.ReceiveAndExtend(t, stream);
blockDataSpan[offset] = (short)(component.Pred += diff); Unsafe.Add(ref blockDataRef, offset) = (short)(component.Pred += diff);
int k = 1; int k = 1;
while (k < 64) while (k < 64)
{ {
int rs = this.DecodeHuffman(ref acHuffmanTable, stream); short rs = this.DecodeHuffman(ref acHuffmanTable, stream);
if (this.endOfStreamReached || this.unexpectedMarkerReached) if (this.endOfStreamReached || this.unexpectedMarkerReached)
{ {
return; return;
@ -750,42 +761,38 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
byte z = PdfJsQuantizationTables.DctZigZag[k]; byte z = PdfJsQuantizationTables.DctZigZag[k];
short re = (short)this.ReceiveAndExtend(s, stream); short re = (short)this.ReceiveAndExtend(s, stream);
blockDataSpan[offset + z] = re; Unsafe.Add(ref blockDataRef, offset + z) = re;
k++; k++;
} }
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private void DecodeDCFirst(PdfJsFrameComponent component, int offset, ref PdfJsHuffmanTable dcHuffmanTable, Stream stream) private void DecodeDCFirst(PdfJsFrameComponent component, ref short blockDataRef, int offset, ref PdfJsHuffmanTable dcHuffmanTable, Stream stream)
{ {
Span<short> blockDataSpan = component.BlockData.Span; short t = this.DecodeHuffman(ref dcHuffmanTable, stream);
int t = this.DecodeHuffman(ref dcHuffmanTable, stream);
if (this.endOfStreamReached || this.unexpectedMarkerReached) if (this.endOfStreamReached || this.unexpectedMarkerReached)
{ {
return; return;
} }
int diff = t == 0 ? 0 : this.ReceiveAndExtend(t, stream) << this.successiveState; int diff = t == 0 ? 0 : this.ReceiveAndExtend(t, stream) << this.successiveState;
blockDataSpan[offset] = (short)(component.Pred += diff); Unsafe.Add(ref blockDataRef, offset) = (short)(component.Pred += diff);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private void DecodeDCSuccessive(PdfJsFrameComponent component, int offset, Stream stream) private void DecodeDCSuccessive(PdfJsFrameComponent component, ref short blockDataRef, int offset, Stream stream)
{ {
Span<short> blockDataSpan = component.BlockData.Span;
int bit = this.ReadBit(stream); int bit = this.ReadBit(stream);
if (this.endOfStreamReached || this.unexpectedMarkerReached) if (this.endOfStreamReached || this.unexpectedMarkerReached)
{ {
return; return;
} }
blockDataSpan[offset] |= (short)(bit << this.successiveState); Unsafe.Add(ref blockDataRef, offset) |= (short)(bit << this.successiveState);
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private void DecodeACFirst(PdfJsFrameComponent component, int offset, ref PdfJsHuffmanTable acHuffmanTable, Stream stream) private void DecodeACFirst(PdfJsFrameComponent component, ref short blockDataRef, int offset, ref PdfJsHuffmanTable acHuffmanTable, Stream stream)
{ {
if (this.eobrun > 0) if (this.eobrun > 0)
{ {
@ -793,7 +800,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
return; return;
} }
Span<short> componentBlockDataSpan = component.BlockData.Span;
int k = this.specStart; int k = this.specStart;
int e = this.specEnd; int e = this.specEnd;
while (k <= e) while (k <= e)
@ -820,19 +826,20 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
} }
k += r; k += r;
byte z = PdfJsQuantizationTables.DctZigZag[k];
componentBlockDataSpan[offset + z] = (short)(this.ReceiveAndExtend(s, stream) * (1 << this.successiveState)); ref byte z = ref PdfJsQuantizationTables.DctZigZag[k];
Unsafe.Add(ref blockDataRef, offset + z) = (short)(this.ReceiveAndExtend(s, stream) * (1 << this.successiveState));
k++; k++;
} }
} }
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private void DecodeACSuccessive(PdfJsFrameComponent component, int offset, ref PdfJsHuffmanTable acHuffmanTable, Stream stream) private void DecodeACSuccessive(PdfJsFrameComponent component, ref short blockDataRef, int offset, ref PdfJsHuffmanTable acHuffmanTable, Stream stream)
{ {
int k = this.specStart; int k = this.specStart;
int e = this.specEnd; int e = this.specEnd;
int r = 0; int r = 0;
Span<short> componentBlockDataSpan = component.BlockData.Span;
while (k <= e) while (k <= e)
{ {
byte z = PdfJsQuantizationTables.DctZigZag[k]; byte z = PdfJsQuantizationTables.DctZigZag[k];
@ -874,7 +881,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
continue; continue;
case 1: // Skipping r zero items case 1: // Skipping r zero items
case 2: case 2:
if (componentBlockDataSpan[offset + z] != 0) ref short blockRef = ref Unsafe.Add(ref blockDataRef, offset + z);
if (blockRef != 0)
{ {
int bit = this.ReadBit(stream); int bit = this.ReadBit(stream);
if (this.endOfStreamReached || this.unexpectedMarkerReached) if (this.endOfStreamReached || this.unexpectedMarkerReached)
@ -882,7 +890,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
return; return;
} }
componentBlockDataSpan[offset + z] += (short)(bit << this.successiveState); blockRef += (short)(bit << this.successiveState);
} }
else else
{ {
@ -895,7 +903,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
break; break;
case 3: // Set value for a zero item case 3: // Set value for a zero item
if (componentBlockDataSpan[offset + z] != 0) ref short blockRef2 = ref Unsafe.Add(ref blockDataRef, offset + z);
if (blockRef2 != 0)
{ {
int bit = this.ReadBit(stream); int bit = this.ReadBit(stream);
if (this.endOfStreamReached || this.unexpectedMarkerReached) if (this.endOfStreamReached || this.unexpectedMarkerReached)
@ -903,17 +912,18 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
return; return;
} }
componentBlockDataSpan[offset + z] += (short)(bit << this.successiveState); blockRef2 += (short)(bit << this.successiveState);
} }
else else
{ {
componentBlockDataSpan[offset + z] = (short)(this.successiveACNextValue << this.successiveState); blockRef2 = (short)(this.successiveACNextValue << this.successiveState);
this.successiveACState = 0; this.successiveACState = 0;
} }
break; break;
case 4: // Eob case 4: // Eob
if (componentBlockDataSpan[offset + z] != 0) ref short blockRef3 = ref Unsafe.Add(ref blockDataRef, offset + z);
if (blockRef3 != 0)
{ {
int bit = this.ReadBit(stream); int bit = this.ReadBit(stream);
if (this.endOfStreamReached || this.unexpectedMarkerReached) if (this.endOfStreamReached || this.unexpectedMarkerReached)
@ -921,7 +931,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
return; return;
} }
componentBlockDataSpan[offset + z] += (short)(bit << this.successiveState); blockRef3 += (short)(bit << this.successiveState);
} }
break; break;

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

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. // Licensed under the Apache License, Version 2.0.
using System; using System;
using System.Buffers.Binary;
using System.IO; using System.IO;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Advanced; using SixLabors.ImageSharp.Advanced;
@ -123,7 +124,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
if (value == 0) if (value == 0)
{ {
return new PdfJsFileMarker(PdfJsJpegConstants.Markers.EOI, (int)stream.Length - 2); return new PdfJsFileMarker(PdfJsJpegConstants.Markers.EOI, stream.Length - 2);
} }
if (marker[0] == PdfJsJpegConstants.Markers.Prefix) if (marker[0] == PdfJsJpegConstants.Markers.Prefix)
@ -135,16 +136,16 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
int suffix = stream.ReadByte(); int suffix = stream.ReadByte();
if (suffix == -1) if (suffix == -1)
{ {
return new PdfJsFileMarker(PdfJsJpegConstants.Markers.EOI, (int)stream.Length - 2); return new PdfJsFileMarker(PdfJsJpegConstants.Markers.EOI, stream.Length - 2);
} }
marker[1] = (byte)suffix; marker[1] = (byte)suffix;
} }
return new PdfJsFileMarker((ushort)((marker[0] << 8) | marker[1]), (int)(stream.Position - 2)); return new PdfJsFileMarker(BinaryPrimitives.ReadUInt16BigEndian(marker), stream.Position - 2);
} }
return new PdfJsFileMarker((ushort)((marker[0] << 8) | marker[1]), (int)(stream.Position - 2), true); return new PdfJsFileMarker(BinaryPrimitives.ReadUInt16BigEndian(marker), stream.Position - 2, true);
} }
/// <summary> /// <summary>
@ -172,8 +173,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
this.Frame?.Dispose(); this.Frame?.Dispose();
this.components?.Dispose(); this.components?.Dispose();
this.quantizationTables?.Dispose(); this.quantizationTables?.Dispose();
this.dcHuffmanTables?.Dispose();
this.acHuffmanTables?.Dispose();
this.pixelArea.Dispose(); this.pixelArea.Dispose();
// Set large fields to null. // Set large fields to null.
@ -827,6 +826,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
/// <param name="index">The table index</param> /// <param name="index">The table index</param>
/// <param name="codeLengths">The codelengths</param> /// <param name="codeLengths">The codelengths</param>
/// <param name="values">The values</param> /// <param name="values">The values</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void BuildHuffmanTable(PdfJsHuffmanTables tables, int index, byte[] codeLengths, byte[] values) private void BuildHuffmanTable(PdfJsHuffmanTables tables, int index, byte[] codeLengths, byte[] values)
{ {
tables[index] = new PdfJsHuffmanTable(this.configuration.MemoryManager, codeLengths, values); tables[index] = new PdfJsHuffmanTable(this.configuration.MemoryManager, codeLengths, values);
@ -938,7 +938,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort
private ushort ReadUint16() private ushort ReadUint16()
{ {
this.InputStream.Read(this.markerBuffer, 0, 2); this.InputStream.Read(this.markerBuffer, 0, 2);
return (ushort)((this.markerBuffer[0] << 8) | this.markerBuffer[1]); return BinaryPrimitives.ReadUInt16BigEndian(this.markerBuffer);
} }
} }
} }
Loading…
Cancel
Save