diff --git a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/FastACTables.cs b/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/FastACTables.cs index 1e608cf7a..f936f7342 100644 --- a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/FastACTables.cs +++ b/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/FastACTables.cs @@ -7,7 +7,7 @@ using SixLabors.Memory; namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components { /// - /// The collection of tables used for fast AC entropy scan decoding. + /// The collection of lookup tables used for fast AC entropy scan decoding. /// internal sealed class FastACTables : IDisposable { diff --git a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/FixedByteBuffer257.cs b/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/FixedByteBuffer257.cs deleted file mode 100644 index 301524316..000000000 --- a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/FixedByteBuffer257.cs +++ /dev/null @@ -1,24 +0,0 @@ -// 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 FixedByteBuffer257 - { - public fixed byte Data[257]; - - public byte this[int idx] - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - ref byte self = ref Unsafe.As(ref this); - return Unsafe.Add(ref self, idx); - } - } - } -} \ No newline at end of file diff --git a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/FixedInt16Buffer256.cs b/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/FixedInt16Buffer256.cs deleted file mode 100644 index 2c16a918f..000000000 --- a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/FixedInt16Buffer256.cs +++ /dev/null @@ -1,24 +0,0 @@ -// 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(ref this); - return Unsafe.Add(ref self, idx); - } - } - } -} \ No newline at end of file diff --git a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsFrameComponent.cs b/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsFrameComponent.cs index eefe8b97e..1a10adf88 100644 --- a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsFrameComponent.cs +++ b/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsFrameComponent.cs @@ -129,7 +129,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components this.SubSamplingDivisors = c0.SamplingFactors.DivideBy(this.SamplingFactors); } - this.SpectralBlocks = this.memoryAllocator.Allocate2D(blocksPerColumnForMcu, blocksPerLineForMcu + 1, true); + this.SpectralBlocks = this.memoryAllocator.AllocateClean2D(blocksPerColumnForMcu, blocksPerLineForMcu + 1); } [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsHuffmanTable.cs b/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsHuffmanTable.cs index e843ebbac..3babb449a 100644 --- a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsHuffmanTable.cs +++ b/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsHuffmanTable.cs @@ -88,7 +88,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components } // Figure F.15: generate decoding tables for bit-sequential decoding. - // Compute largest code + 1 for this size. preshifted as neeed later. + // Compute largest code + 1 for this size. preshifted as need later. maxcodeRef[j] = code << (16 - j); code <<= 1; } diff --git a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsScanDecoder.cs b/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsScanDecoder.cs deleted file mode 100644 index d524fa5d8..000000000 --- a/src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsScanDecoder.cs +++ /dev/null @@ -1,866 +0,0 @@ -// Copyright (c) Six Labors and contributors. -// Licensed under the Apache License, Version 2.0. - -using System; - -#if DEBUG -using System.Diagnostics; -#endif -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using SixLabors.ImageSharp.Formats.Jpeg.Components; -using SixLabors.Memory; - -namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components -{ - /// - /// Provides the means to decode a spectral scan - /// - internal struct PdfJsScanDecoder - { - private ZigZag dctZigZag; - - private byte[] markerBuffer; - - private int mcuToRead; - - private int mcusPerLine; - - private int mcu; - - private int bitsData; - - private int bitsCount; - - private int specStart; - - private int specEnd; - - private int eobrun; - - private int compIndex; - - private int successiveState; - - private int successiveACState; - - private int successiveACNextValue; - - private bool endOfStreamReached; - - private bool unexpectedMarkerReached; - - /// - /// Decodes the spectral scan - /// - /// The image frame - /// The input stream - /// The DC Huffman tables - /// The AC Huffman tables - /// The scan components - /// The component index within the array - /// The length of the components. Different to the array length - /// The reset interval - /// The spectral selection start - /// The spectral selection end - /// The successive approximation bit high end - /// The successive approximation bit low end - public void DecodeScan( - PdfJsFrame frame, - DoubleBufferedStreamReader stream, - PdfJsHuffmanTables dcHuffmanTables, - PdfJsHuffmanTables acHuffmanTables, - PdfJsFrameComponent[] components, - int componentIndex, - int componentsLength, - ushort resetInterval, - int spectralStart, - int spectralEnd, - int successivePrev, - int successive) - { - this.dctZigZag = ZigZag.CreateUnzigTable(); - this.markerBuffer = new byte[2]; - this.compIndex = componentIndex; - this.specStart = spectralStart; - this.specEnd = spectralEnd; - this.successiveState = successive; - this.endOfStreamReached = false; - this.unexpectedMarkerReached = false; - - bool progressive = frame.Progressive; - this.mcusPerLine = frame.McusPerLine; - - this.mcu = 0; - int mcuExpected; - if (componentsLength == 1) - { - mcuExpected = components[this.compIndex].WidthInBlocks * components[this.compIndex].HeightInBlocks; - } - else - { - mcuExpected = this.mcusPerLine * frame.McusPerColumn; - } - - while (this.mcu < mcuExpected) - { - // Reset interval stuff - this.mcuToRead = resetInterval != 0 ? Math.Min(mcuExpected - this.mcu, resetInterval) : mcuExpected; - for (int i = 0; i < components.Length; i++) - { - PdfJsFrameComponent c = components[i]; - c.DcPredictor = 0; - } - - this.eobrun = 0; - - if (!progressive) - { - this.DecodeScanBaseline(dcHuffmanTables, acHuffmanTables, components, componentsLength, stream); - } - else - { - bool isAc = this.specStart != 0; - bool isFirst = successivePrev == 0; - PdfJsHuffmanTables huffmanTables = isAc ? acHuffmanTables : dcHuffmanTables; - this.DecodeScanProgressive(huffmanTables, isAc, isFirst, components, componentsLength, stream); - } - - // Reset - // TODO: I do not understand why these values are reset? We should surely be tracking the bits across mcu's? - this.bitsCount = 0; - this.bitsData = 0; - this.unexpectedMarkerReached = false; - - // Some images include more scan blocks than expected, skip past those and - // attempt to find the next valid marker - PdfJsFileMarker fileMarker = PdfJsJpegDecoderCore.FindNextFileMarker(this.markerBuffer, stream); - byte marker = fileMarker.Marker; - - // RSTn - We've already read the bytes and altered the position so no need to skip - if (marker >= JpegConstants.Markers.RST0 && marker <= JpegConstants.Markers.RST7) - { - continue; - } - - if (!fileMarker.Invalid) - { - // We've found a valid marker. - // Rewind the stream to the position of the marker and break - stream.Position = fileMarker.Position; - break; - } - -#if DEBUG - Debug.WriteLine($"DecodeScan - Unexpected MCU data at {stream.Position}, next marker is: {fileMarker.Marker:X}"); -#endif - } - } - - private void DecodeScanBaseline( - PdfJsHuffmanTables dcHuffmanTables, - PdfJsHuffmanTables acHuffmanTables, - PdfJsFrameComponent[] components, - int componentsLength, - DoubleBufferedStreamReader stream) - { - if (componentsLength == 1) - { - PdfJsFrameComponent component = components[this.compIndex]; - ref short blockDataRef = ref MemoryMarshal.GetReference(MemoryMarshal.Cast(component.SpectralBlocks.GetSpan())); - ref PdfJsHuffmanTable dcHuffmanTable = ref dcHuffmanTables[component.DCHuffmanTableId]; - ref PdfJsHuffmanTable acHuffmanTable = ref acHuffmanTables[component.ACHuffmanTableId]; - - for (int n = 0; n < this.mcuToRead; n++) - { - if (this.endOfStreamReached || this.unexpectedMarkerReached) - { - continue; - } - - this.DecodeBlockBaseline(ref dcHuffmanTable, ref acHuffmanTable, component, ref blockDataRef, stream); - this.mcu++; - } - } - else - { - for (int n = 0; n < this.mcuToRead; n++) - { - for (int i = 0; i < componentsLength; i++) - { - PdfJsFrameComponent component = components[i]; - ref short blockDataRef = ref MemoryMarshal.GetReference(MemoryMarshal.Cast(component.SpectralBlocks.GetSpan())); - ref PdfJsHuffmanTable dcHuffmanTable = ref dcHuffmanTables[component.DCHuffmanTableId]; - ref PdfJsHuffmanTable acHuffmanTable = ref acHuffmanTables[component.ACHuffmanTableId]; - int h = component.HorizontalSamplingFactor; - int v = component.VerticalSamplingFactor; - - for (int j = 0; j < v; j++) - { - for (int k = 0; k < h; k++) - { - if (this.endOfStreamReached || this.unexpectedMarkerReached) - { - continue; - } - - this.DecodeMcuBaseline(ref dcHuffmanTable, ref acHuffmanTable, component, ref blockDataRef, j, k, stream); - } - } - } - - this.mcu++; - } - } - } - - private void DecodeScanProgressive( - PdfJsHuffmanTables huffmanTables, - bool isAC, - bool isFirst, - PdfJsFrameComponent[] components, - int componentsLength, - DoubleBufferedStreamReader stream) - { - if (componentsLength == 1) - { - PdfJsFrameComponent component = components[this.compIndex]; - ref short blockDataRef = ref MemoryMarshal.GetReference(MemoryMarshal.Cast(component.SpectralBlocks.GetSpan())); - ref PdfJsHuffmanTable huffmanTable = ref huffmanTables[isAC ? component.ACHuffmanTableId : component.DCHuffmanTableId]; - - for (int n = 0; n < this.mcuToRead; n++) - { - if (this.endOfStreamReached || this.unexpectedMarkerReached) - { - continue; - } - - if (isAC) - { - if (isFirst) - { - this.DecodeBlockACFirst(ref huffmanTable, component, ref blockDataRef, stream); - } - else - { - this.DecodeBlockACSuccessive(ref huffmanTable, component, ref blockDataRef, stream); - } - } - else - { - if (isFirst) - { - this.DecodeBlockDCFirst(ref huffmanTable, component, ref blockDataRef, stream); - } - else - { - this.DecodeBlockDCSuccessive(component, ref blockDataRef, stream); - } - } - - this.mcu++; - } - } - else - { - for (int n = 0; n < this.mcuToRead; n++) - { - for (int i = 0; i < componentsLength; i++) - { - PdfJsFrameComponent component = components[i]; - ref short blockDataRef = ref MemoryMarshal.GetReference(MemoryMarshal.Cast(component.SpectralBlocks.GetSpan())); - ref PdfJsHuffmanTable huffmanTable = ref huffmanTables[isAC ? component.ACHuffmanTableId : component.DCHuffmanTableId]; - int h = component.HorizontalSamplingFactor; - int v = component.VerticalSamplingFactor; - - for (int j = 0; j < v; j++) - { - for (int k = 0; k < h; k++) - { - // No need to continue here. - if (this.endOfStreamReached || this.unexpectedMarkerReached) - { - break; - } - - if (isAC) - { - if (isFirst) - { - this.DecodeMcuACFirst(ref huffmanTable, component, ref blockDataRef, j, k, stream); - } - else - { - this.DecodeMcuACSuccessive(ref huffmanTable, component, ref blockDataRef, j, k, stream); - } - } - else - { - if (isFirst) - { - this.DecodeMcuDCFirst(ref huffmanTable, component, ref blockDataRef, j, k, stream); - } - else - { - this.DecodeMcuDCSuccessive(component, ref blockDataRef, j, k, stream); - } - } - } - } - } - - this.mcu++; - } - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void DecodeBlockBaseline(ref PdfJsHuffmanTable dcHuffmanTable, ref PdfJsHuffmanTable acHuffmanTable, PdfJsFrameComponent component, ref short blockDataRef, DoubleBufferedStreamReader stream) - { - int blockRow = this.mcu / component.WidthInBlocks; - int blockCol = this.mcu % component.WidthInBlocks; - int offset = component.GetBlockBufferOffset(blockRow, blockCol); - this.DecodeBaseline(component, ref blockDataRef, offset, ref dcHuffmanTable, ref acHuffmanTable, stream); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void DecodeMcuBaseline(ref PdfJsHuffmanTable dcHuffmanTable, ref PdfJsHuffmanTable acHuffmanTable, PdfJsFrameComponent component, ref short blockDataRef, int row, int col, DoubleBufferedStreamReader stream) - { - int mcuRow = this.mcu / this.mcusPerLine; - int mcuCol = this.mcu % this.mcusPerLine; - int blockRow = (mcuRow * component.VerticalSamplingFactor) + row; - int blockCol = (mcuCol * component.HorizontalSamplingFactor) + col; - int offset = component.GetBlockBufferOffset(blockRow, blockCol); - this.DecodeBaseline(component, ref blockDataRef, offset, ref dcHuffmanTable, ref acHuffmanTable, stream); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void DecodeBlockDCFirst(ref PdfJsHuffmanTable dcHuffmanTable, PdfJsFrameComponent component, ref short blockDataRef, DoubleBufferedStreamReader stream) - { - int blockRow = this.mcu / component.WidthInBlocks; - int blockCol = this.mcu % component.WidthInBlocks; - int offset = component.GetBlockBufferOffset(blockRow, blockCol); - this.DecodeDCFirst(component, ref blockDataRef, offset, ref dcHuffmanTable, stream); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void DecodeMcuDCFirst(ref PdfJsHuffmanTable dcHuffmanTable, PdfJsFrameComponent component, ref short blockDataRef, int row, int col, DoubleBufferedStreamReader stream) - { - int mcuRow = this.mcu / this.mcusPerLine; - int mcuCol = this.mcu % this.mcusPerLine; - int blockRow = (mcuRow * component.VerticalSamplingFactor) + row; - int blockCol = (mcuCol * component.HorizontalSamplingFactor) + col; - int offset = component.GetBlockBufferOffset(blockRow, blockCol); - this.DecodeDCFirst(component, ref blockDataRef, offset, ref dcHuffmanTable, stream); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void DecodeBlockDCSuccessive(PdfJsFrameComponent component, ref short blockDataRef, DoubleBufferedStreamReader stream) - { - int blockRow = this.mcu / component.WidthInBlocks; - int blockCol = this.mcu % component.WidthInBlocks; - int offset = component.GetBlockBufferOffset(blockRow, blockCol); - this.DecodeDCSuccessive(component, ref blockDataRef, offset, stream); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void DecodeMcuDCSuccessive(PdfJsFrameComponent component, ref short blockDataRef, int row, int col, DoubleBufferedStreamReader stream) - { - int mcuRow = this.mcu / this.mcusPerLine; - int mcuCol = this.mcu % this.mcusPerLine; - int blockRow = (mcuRow * component.VerticalSamplingFactor) + row; - int blockCol = (mcuCol * component.HorizontalSamplingFactor) + col; - int offset = component.GetBlockBufferOffset(blockRow, blockCol); - this.DecodeDCSuccessive(component, ref blockDataRef, offset, stream); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void DecodeBlockACFirst(ref PdfJsHuffmanTable acHuffmanTable, PdfJsFrameComponent component, ref short blockDataRef, DoubleBufferedStreamReader stream) - { - int blockRow = this.mcu / component.WidthInBlocks; - int blockCol = this.mcu % component.WidthInBlocks; - int offset = component.GetBlockBufferOffset(blockRow, blockCol); - this.DecodeACFirst(ref blockDataRef, offset, ref acHuffmanTable, stream); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void DecodeMcuACFirst(ref PdfJsHuffmanTable acHuffmanTable, PdfJsFrameComponent component, ref short blockDataRef, int row, int col, DoubleBufferedStreamReader stream) - { - int mcuRow = this.mcu / this.mcusPerLine; - int mcuCol = this.mcu % this.mcusPerLine; - int blockRow = (mcuRow * component.VerticalSamplingFactor) + row; - int blockCol = (mcuCol * component.HorizontalSamplingFactor) + col; - int offset = component.GetBlockBufferOffset(blockRow, blockCol); - this.DecodeACFirst(ref blockDataRef, offset, ref acHuffmanTable, stream); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void DecodeBlockACSuccessive(ref PdfJsHuffmanTable acHuffmanTable, PdfJsFrameComponent component, ref short blockDataRef, DoubleBufferedStreamReader stream) - { - int blockRow = this.mcu / component.WidthInBlocks; - int blockCol = this.mcu % component.WidthInBlocks; - int offset = component.GetBlockBufferOffset(blockRow, blockCol); - this.DecodeACSuccessive(ref blockDataRef, offset, ref acHuffmanTable, stream); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void DecodeMcuACSuccessive(ref PdfJsHuffmanTable acHuffmanTable, PdfJsFrameComponent component, ref short blockDataRef, int row, int col, DoubleBufferedStreamReader stream) - { - int mcuRow = this.mcu / this.mcusPerLine; - int mcuCol = this.mcu % this.mcusPerLine; - int blockRow = (mcuRow * component.VerticalSamplingFactor) + row; - int blockCol = (mcuCol * component.HorizontalSamplingFactor) + col; - int offset = component.GetBlockBufferOffset(blockRow, blockCol); - this.DecodeACSuccessive(ref blockDataRef, offset, ref acHuffmanTable, stream); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private bool TryReadBit(DoubleBufferedStreamReader stream, out int bit) - { - if (this.bitsCount == 0) - { - if (!this.TryFillBits(stream)) - { - bit = 0; - return false; - } - } - - this.bitsCount--; - bit = (this.bitsData >> this.bitsCount) & 1; - return true; - } - - [MethodImpl(MethodImplOptions.NoInlining)] - private bool TryFillBits(DoubleBufferedStreamReader stream) - { - // TODO: Read more then 1 byte at a time. - // In LibJpegTurbo this is be 25 bits (32-7) but I cannot get this to work - // for some images, I'm assuming because I am crossing MCU boundaries and not maintining the correct buffer state. - const int MinGetBits = 7; - - if (!this.unexpectedMarkerReached) - { - // Attempt to load to the minimum bit count. - while (this.bitsCount < MinGetBits) - { - int c = stream.ReadByte(); - - switch (c) - { - case -0x1: - - // We've encountered the end of the file stream which means there's no EOI marker in the image. - this.endOfStreamReached = true; - return false; - - case JpegConstants.Markers.XFF: - int nextByte = stream.ReadByte(); - - if (nextByte == -0x1) - { - this.endOfStreamReached = true; - return false; - } - - if (nextByte != 0) - { -#if DEBUG - Debug.WriteLine($"DecodeScan - Unexpected marker {(c << 8) | nextByte:X} at {stream.Position}"); -#endif - - // We've encountered an unexpected marker. Reverse the stream and exit. - this.unexpectedMarkerReached = true; - stream.Position -= 2; - - // TODO: double check we need this. - // Fill buffer with zero bits. - if (this.bitsCount == 0) - { - this.bitsData <<= MinGetBits; - this.bitsCount = MinGetBits; - } - - return true; - } - - break; - } - - // OK, load the next byte into bitsData - this.bitsData = (this.bitsData << 8) | c; - this.bitsCount += 8; - } - } - - return true; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private int PeekBits(int count) - { - return this.bitsData >> (this.bitsCount - count) & ((1 << count) - 1); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void DropBits(int count) - { - this.bitsCount -= count; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private bool TryDecodeHuffman(ref PdfJsHuffmanTable tree, DoubleBufferedStreamReader stream, out short value) - { - value = -1; - - // TODO: Implement fast Huffman decoding. - // In LibJpegTurbo a minimum of 25 bits (32-7) is collected from the stream - // Then a LUT is used to avoid the loop when decoding the Huffman value. - // using 3 methods: FillBits, PeekBits, and DropBits. - // The LUT has been ported from LibJpegTurbo as has this code but it doesn't work. - // this.TryFillBits(stream); - // - // const int LookAhead = 8; - // int look = this.PeekBits(LookAhead); - // look = tree.Lookahead[look]; - // int bits = look >> LookAhead; - // - // if (bits <= LookAhead) - // { - // this.DropBits(bits); - // value = (short)(look & ((1 << LookAhead) - 1)); - // return true; - // } - if (!this.TryReadBit(stream, out int bit)) - { - return false; - } - - short code = (short)bit; - - // "DECODE", section F.2.2.3, figure F.16, page 109 of T.81 - int i = 1; - - while (code > tree.MaxCode[i]) - { - if (!this.TryReadBit(stream, out bit)) - { - return false; - } - - code <<= 1; - code |= (short)bit; - i++; - } - - int j = tree.ValOffset[i]; - value = tree.Values[(j + code) & 0xFF]; - return true; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private bool TryReceive(int length, DoubleBufferedStreamReader stream, out int value) - { - value = 0; - while (length > 0) - { - if (!this.TryReadBit(stream, out int bit)) - { - return false; - } - - value = (value << 1) | bit; - length--; - } - - return true; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private bool TryReceiveAndExtend(int length, DoubleBufferedStreamReader stream, out int value) - { - if (length == 1) - { - if (!this.TryReadBit(stream, out value)) - { - return false; - } - - value = value == 1 ? 1 : -1; - } - else - { - if (!this.TryReceive(length, stream, out value)) - { - return false; - } - - if (value < 1 << (length - 1)) - { - value += (-1 << length) + 1; - } - } - - return true; - } - - private void DecodeBaseline(PdfJsFrameComponent component, ref short blockDataRef, int offset, ref PdfJsHuffmanTable dcHuffmanTable, ref PdfJsHuffmanTable acHuffmanTable, DoubleBufferedStreamReader stream) - { - if (!this.TryDecodeHuffman(ref dcHuffmanTable, stream, out short t)) - { - return; - } - - int diff = 0; - if (t != 0) - { - if (!this.TryReceiveAndExtend(t, stream, out diff)) - { - return; - } - } - - Unsafe.Add(ref blockDataRef, offset) = (short)(component.DcPredictor += diff); - - int k = 1; - while (k < 64) - { - if (!this.TryDecodeHuffman(ref acHuffmanTable, stream, out short rs)) - { - return; - } - - int s = rs & 15; - int r = rs >> 4; - - if (s == 0) - { - if (r < 15) - { - break; - } - - k += 16; - continue; - } - - k += r; - - byte z = this.dctZigZag[k]; - - if (!this.TryReceiveAndExtend(s, stream, out int re)) - { - return; - } - - Unsafe.Add(ref blockDataRef, offset + z) = (short)re; - k++; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void DecodeDCFirst(PdfJsFrameComponent component, ref short blockDataRef, int offset, ref PdfJsHuffmanTable dcHuffmanTable, DoubleBufferedStreamReader stream) - { - if (!this.TryDecodeHuffman(ref dcHuffmanTable, stream, out short t)) - { - return; - } - - int diff = 0; - if (t != 0) - { - if (!this.TryReceiveAndExtend(t, stream, out diff)) - { - return; - } - } - - Unsafe.Add(ref blockDataRef, offset) = (short)(component.DcPredictor += diff << this.successiveState); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void DecodeDCSuccessive(PdfJsFrameComponent component, ref short blockDataRef, int offset, DoubleBufferedStreamReader stream) - { - if (!this.TryReadBit(stream, out int bit)) - { - return; - } - - Unsafe.Add(ref blockDataRef, offset) |= (short)(bit << this.successiveState); - } - - private void DecodeACFirst(ref short blockDataRef, int offset, ref PdfJsHuffmanTable acHuffmanTable, DoubleBufferedStreamReader stream) - { - if (this.eobrun > 0) - { - this.eobrun--; - return; - } - - int k = this.specStart; - int e = this.specEnd; - while (k <= e) - { - if (!this.TryDecodeHuffman(ref acHuffmanTable, stream, out short rs)) - { - return; - } - - int s = rs & 15; - int r = rs >> 4; - - if (s == 0) - { - if (r < 15) - { - if (!this.TryReceive(r, stream, out int eob)) - { - return; - } - - this.eobrun = eob + (1 << r) - 1; - break; - } - - k += 16; - continue; - } - - k += r; - - byte z = this.dctZigZag[k]; - - if (!this.TryReceiveAndExtend(s, stream, out int v)) - { - return; - } - - Unsafe.Add(ref blockDataRef, offset + z) = (short)(v * (1 << this.successiveState)); - k++; - } - } - - private void DecodeACSuccessive(ref short blockDataRef, int offset, ref PdfJsHuffmanTable acHuffmanTable, DoubleBufferedStreamReader stream) - { - int k = this.specStart; - int e = this.specEnd; - int r = 0; - - while (k <= e) - { - int offsetZ = offset + this.dctZigZag[k]; - ref short blockOffsetZRef = ref Unsafe.Add(ref blockDataRef, offsetZ); - int sign = blockOffsetZRef < 0 ? -1 : 1; - - switch (this.successiveACState) - { - case 0: // Initial state - - if (!this.TryDecodeHuffman(ref acHuffmanTable, stream, out short rs)) - { - return; - } - - int s = rs & 15; - r = rs >> 4; - if (s == 0) - { - if (r < 15) - { - if (!this.TryReceive(r, stream, out int eob)) - { - return; - } - - this.eobrun = eob + (1 << r); - this.successiveACState = 4; - } - else - { - r = 16; - this.successiveACState = 1; - } - } - else - { - if (s != 1) - { - throw new ImageFormatException("Invalid ACn encoding"); - } - - if (!this.TryReceiveAndExtend(s, stream, out int v)) - { - return; - } - - this.successiveACNextValue = v; - this.successiveACState = r > 0 ? 2 : 3; - } - - continue; - case 1: // Skipping r zero items - case 2: - if (blockOffsetZRef != 0) - { - if (!this.TryReadBit(stream, out int bit)) - { - return; - } - - blockOffsetZRef += (short)(sign * (bit << this.successiveState)); - } - else - { - r--; - if (r == 0) - { - this.successiveACState = this.successiveACState == 2 ? 3 : 0; - } - } - - break; - case 3: // Set value for a zero item - if (blockOffsetZRef != 0) - { - if (!this.TryReadBit(stream, out int bit)) - { - return; - } - - blockOffsetZRef += (short)(sign * (bit << this.successiveState)); - } - else - { - blockOffsetZRef = (short)(this.successiveACNextValue << this.successiveState); - this.successiveACState = 0; - } - - break; - case 4: // Eob - if (blockOffsetZRef != 0) - { - if (!this.TryReadBit(stream, out int bit)) - { - return; - } - - blockOffsetZRef += (short)(sign * (bit << this.successiveState)); - } - - break; - } - - k++; - } - - if (this.successiveACState == 4) - { - this.eobrun--; - if (this.eobrun == 0) - { - this.successiveACState = 0; - } - } - } - } -} \ No newline at end of file diff --git a/src/ImageSharp/Formats/Jpeg/PdfJsPort/PdfJsJpegDecoderCore.cs b/src/ImageSharp/Formats/Jpeg/PdfJsPort/PdfJsJpegDecoderCore.cs index b71667300..86ac6b195 100644 --- a/src/ImageSharp/Formats/Jpeg/PdfJsPort/PdfJsJpegDecoderCore.cs +++ b/src/ImageSharp/Formats/Jpeg/PdfJsPort/PdfJsJpegDecoderCore.cs @@ -816,22 +816,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort successiveApproximation & 15); sd.ParseEntropyCodedData(this.Frame, this.dcHuffmanTables, this.acHuffmanTables, this.fastACTables); - - // PdfJsScanDecoder scanDecoder = default; - // - // scanDecoder.DecodeScan( - // this.Frame, - // this.InputStream, - // this.dcHuffmanTables, - // this.acHuffmanTables, - // this.Frame.Components, - // componentIndex, - // selectorsCount, - // this.resetInterval, - // spectralStart, - // spectralEnd, - // successiveApproximation >> 4, - // successiveApproximation & 15); } ///