Ejemplo n.º 1
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ScanDecoder"/> class.
 /// </summary>
 /// <param name="stream">The input stream.</param>
 /// <param name="frame">The image frame.</param>
 /// <param name="dcHuffmanTables">The DC Huffman tables.</param>
 /// <param name="acHuffmanTables">The AC Huffman tables.</param>
 /// <param name="fastACTables">The fast AC decoding tables.</param>
 /// <param name="componentIndex">The component index within the array.</param>
 /// <param name="componentsLength">The length of the components. Different to the array length.</param>
 /// <param name="restartInterval">The reset interval.</param>
 /// <param name="spectralStart">The spectral selection start.</param>
 /// <param name="spectralEnd">The spectral selection end.</param>
 /// <param name="successiveHigh">The successive approximation bit high end.</param>
 /// <param name="successiveLow">The successive approximation bit low end.</param>
 public ScanDecoder(
     DoubleBufferedStreamReader stream,
     PdfJsFrame frame,
     PdfJsHuffmanTables dcHuffmanTables,
     PdfJsHuffmanTables acHuffmanTables,
     FastACTables fastACTables,
     int componentIndex,
     int componentsLength,
     int restartInterval,
     int spectralStart,
     int spectralEnd,
     int successiveHigh,
     int successiveLow)
 {
     this.dctZigZag        = ZigZag.CreateUnzigTable();
     this.stream           = stream;
     this.frame            = frame;
     this.dcHuffmanTables  = dcHuffmanTables;
     this.acHuffmanTables  = acHuffmanTables;
     this.fastACTables     = fastACTables;
     this.components       = frame.Components;
     this.marker           = JpegConstants.Markers.XFF;
     this.markerPosition   = 0;
     this.componentIndex   = componentIndex;
     this.componentsLength = componentsLength;
     this.restartInterval  = restartInterval;
     this.spectralStart    = spectralStart;
     this.spectralEnd      = spectralEnd;
     this.successiveHigh   = successiveHigh;
     this.successiveLow    = successiveLow;
 }
Ejemplo n.º 2
0
 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 <Block8x8, short>(component.SpectralBlocks.Span));
         ref PdfJsHuffmanTable dcHuffmanTable = ref dcHuffmanTables[component.DCHuffmanTableId];
Ejemplo n.º 3
0
 private void DecodeScanBaseline(
     PdfJsHuffmanTables dcHuffmanTables,
     PdfJsHuffmanTables acHuffmanTables,
     PdfJsFrameComponent[] components,
     int componentsLength,
     int mcusPerLine,
     int mcuToRead,
     ref int mcu,
     Stream stream)
 {
     if (componentsLength == 1)
     {
         PdfJsFrameComponent   component      = components[this.compIndex];
         ref PdfJsHuffmanTable dcHuffmanTable = ref dcHuffmanTables[component.DCHuffmanTableId];
         ref PdfJsHuffmanTable acHuffmanTable = ref acHuffmanTables[component.ACHuffmanTableId];
Ejemplo n.º 4
0
        /// <summary>
        /// Decodes the spectral scan
        /// </summary>
        /// <param name="frame">The image frame</param>
        /// <param name="stream">The input stream</param>
        /// <param name="dcHuffmanTables">The DC Huffman tables</param>
        /// <param name="acHuffmanTables">The AC Huffman tables</param>
        /// <param name="components">The scan components</param>
        /// <param name="componentIndex">The component index within the array</param>
        /// <param name="componentsLength">The length of the components. Different to the array length</param>
        /// <param name="resetInterval">The reset interval</param>
        /// <param name="spectralStart">The spectral selection start</param>
        /// <param name="spectralEnd">The spectral selection end</param>
        /// <param name="successivePrev">The successive approximation bit high end</param>
        /// <param name="successive">The successive approximation bit low end</param>
        public void DecodeScan(
            PdfJsFrame frame,
            Stream stream,
            PdfJsHuffmanTables dcHuffmanTables,
            PdfJsHuffmanTables acHuffmanTables,
            PdfJsFrameComponent[] components,
            int componentIndex,
            int componentsLength,
            ushort resetInterval,
            int spectralStart,
            int spectralEnd,
            int successivePrev,
            int successive)
        {
            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;
            int  mcusPerLine = frame.McusPerLine;

            int mcu = 0;
            int mcuExpected;

            if (componentsLength == 1)
            {
                mcuExpected = components[this.compIndex].WidthInBlocks * components[this.compIndex].HeightInBlocks;
            }
            else
            {
                mcuExpected = mcusPerLine * frame.McusPerColumn;
            }

            PdfJsFileMarker fileMarker;

            while (mcu < mcuExpected)
            {
                // Reset interval stuff
                int mcuToRead = resetInterval != 0 ? Math.Min(mcuExpected - mcu, resetInterval) : mcuExpected;
                for (int i = 0; i < components.Length; i++)
                {
                    PdfJsFrameComponent c = components[i];
                    c.Pred = 0;
                }

                this.eobrun = 0;

                if (!progressive)
                {
                    this.DecodeScanBaseline(dcHuffmanTables, acHuffmanTables, components, componentsLength, mcusPerLine, mcuToRead, ref mcu, stream);
                }
                else
                {
                    if (this.specStart == 0)
                    {
                        if (successivePrev == 0)
                        {
                            this.DecodeScanDCFirst(dcHuffmanTables, components, componentsLength, mcusPerLine, mcuToRead, ref mcu, stream);
                        }
                        else
                        {
                            this.DecodeScanDCSuccessive(components, componentsLength, mcusPerLine, mcuToRead, ref mcu, stream);
                        }
                    }
                    else
                    {
                        if (successivePrev == 0)
                        {
                            this.DecodeScanACFirst(acHuffmanTables, components, componentsLength, mcusPerLine, mcuToRead, ref mcu, stream);
                        }
                        else
                        {
                            this.DecodeScanACSuccessive(acHuffmanTables, components, componentsLength, mcusPerLine, mcuToRead, ref mcu, stream);
                        }
                    }
                }

                // Find marker
                this.bitsCount   = 0;
                this.accumulator = 0;
                this.bitsUnRead  = 0;
                fileMarker       = PdfJsJpegDecoderCore.FindNextFileMarker(this.markerBuffer, stream);

                // Some bad images seem to pad Scan blocks with e.g. zero bytes, skip past
                // those to attempt to find a valid marker (fixes issue4090.pdf) in original code.
                if (fileMarker.Invalid)
                {
#if DEBUG
                    Debug.WriteLine($"DecodeScan - Unexpected MCU data at {stream.Position}, next marker is: {fileMarker.Marker:X}");
#endif
                }

                ushort marker = fileMarker.Marker;

                // RSTn - We've already read the bytes and altered the position so no need to skip
                if (marker >= PdfJsJpegConstants.Markers.RST0 && marker <= PdfJsJpegConstants.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;
                }
            }

            fileMarker = PdfJsJpegDecoderCore.FindNextFileMarker(this.markerBuffer, stream);

            // 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.
            if (fileMarker.Invalid)
            {
#if DEBUG
                Debug.WriteLine($"DecodeScan - Unexpected MCU data at {stream.Position}, next marker is: {fileMarker.Marker:X}");
#endif
            }
            else
            {
                // We've found a valid marker.
                // Rewind the stream to the position of the marker
                stream.Position = fileMarker.Position;
            }
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Decodes the spectral scan
        /// </summary>
        /// <param name="frame">The image frame</param>
        /// <param name="stream">The input stream</param>
        /// <param name="dcHuffmanTables">The DC Huffman tables</param>
        /// <param name="acHuffmanTables">The AC Huffman tables</param>
        /// <param name="components">The scan components</param>
        /// <param name="componentIndex">The component index within the array</param>
        /// <param name="componentsLength">The length of the components. Different to the array length</param>
        /// <param name="resetInterval">The reset interval</param>
        /// <param name="spectralStart">The spectral selection start</param>
        /// <param name="spectralEnd">The spectral selection end</param>
        /// <param name="successivePrev">The successive approximation bit high end</param>
        /// <param name="successive">The successive approximation bit low end</param>
        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.Pred = 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 >= PdfJsJpegConstants.Markers.RST0 && marker <= PdfJsJpegConstants.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
            }
        }
Ejemplo n.º 6
0
 /// <summary>
 /// Builds a lookup table for fast AC entropy scan decoding.
 /// </summary>
 /// <param name="index">The table index.</param>
 /// <param name="acHuffmanTables">The collection of AC Huffman tables.</param>
 public void BuildACTableLut(int index, PdfJsHuffmanTables acHuffmanTables)
 {
     const int             FastBits = ScanDecoder.FastBits;
     Span <short>          fastAC   = this.tables.GetRowSpan(index);
     ref PdfJsHuffmanTable huffman  = ref acHuffmanTables[index];