/// <summary>
        /// Processes the Start of Frame marker.  Specified in section B.2.2.
        /// </summary>
        /// <param name="remaining">The remaining bytes in the segment block.</param>
        /// <param name="frameMarker">The current frame marker.</param>
        private void ProcessStartOfFrameMarker(int remaining, PdfJsFileMarker frameMarker)
        {
            if (this.Frame != null)
            {
                throw new ImageFormatException("Multiple SOF markers. Only single frame jpegs supported.");
            }

            this.InputStream.Read(this.temp, 0, remaining);

            this.Frame = new PdfJsFrame
            {
                Extended       = frameMarker.Marker == PdfJsJpegConstants.Markers.SOF1,
                Progressive    = frameMarker.Marker == PdfJsJpegConstants.Markers.SOF2,
                Precision      = this.temp[0],
                Scanlines      = (short)((this.temp[1] << 8) | this.temp[2]),
                SamplesPerLine = (short)((this.temp[3] << 8) | this.temp[4]),
                ComponentCount = this.temp[5]
            };

            int maxH  = 0;
            int maxV  = 0;
            int index = 6;

            // No need to pool this. They max out at 4
            this.Frame.ComponentIds = new byte[this.Frame.ComponentCount];
            this.Frame.Components   = new PdfJsFrameComponent[this.Frame.ComponentCount];

            for (int i = 0; i < this.Frame.Components.Length; i++)
            {
                int h = this.temp[index + 1] >> 4;
                int v = this.temp[index + 1] & 15;

                if (maxH < h)
                {
                    maxH = h;
                }

                if (maxV < v)
                {
                    maxV = v;
                }

                var component = new PdfJsFrameComponent(this.Frame, this.temp[index], h, v, this.temp[index + 2], i);

                this.Frame.Components[i]   = component;
                this.Frame.ComponentIds[i] = component.Id;

                index += 3;
            }

            this.Frame.MaxHorizontalFactor = maxH;
            this.Frame.MaxVerticalFactor   = maxV;
            this.Frame.InitComponents();
        }
Beispiel #2
0
        /// <summary>
        /// Parses the input stream for file markers
        /// </summary>
        /// <param name="stream">The input stream</param>
        /// <param name="metadataOnly">Whether to decode metadata only.</param>
        public void ParseStream(Stream stream, bool metadataOnly = false)
        {
            this.MetaData    = new ImageMetaData();
            this.InputStream = new DoubleBufferedStreamReader(this.configuration.MemoryManager, stream);

            // Check for the Start Of Image marker.
            this.InputStream.Read(this.markerBuffer, 0, 2);
            var fileMarker = new PdfJsFileMarker(this.markerBuffer[1], 0);

            if (fileMarker.Marker != JpegConstants.Markers.SOI)
            {
                throw new ImageFormatException("Missing SOI marker.");
            }

            this.InputStream.Read(this.markerBuffer, 0, 2);
            byte marker = this.markerBuffer[1];

            fileMarker = new PdfJsFileMarker(marker, (int)this.InputStream.Position - 2);

            // Only assign what we need
            if (!metadataOnly)
            {
                this.QuantizationTables = new Block8x8F[4];
                this.dcHuffmanTables    = new PdfJsHuffmanTables();
                this.acHuffmanTables    = new PdfJsHuffmanTables();
            }

            while (fileMarker.Marker != JpegConstants.Markers.EOI)
            {
                if (!fileMarker.Invalid)
                {
                    // Get the marker length
                    int remaining = this.ReadUint16() - 2;

                    switch (fileMarker.Marker)
                    {
                    case JpegConstants.Markers.SOF0:
                    case JpegConstants.Markers.SOF1:
                    case JpegConstants.Markers.SOF2:
                        this.ProcessStartOfFrameMarker(remaining, fileMarker, metadataOnly);
                        break;

                    case JpegConstants.Markers.SOS:
                        if (!metadataOnly)
                        {
                            this.ProcessStartOfScanMarker();
                            break;
                        }
                        else
                        {
                            // It's highly unlikely that APPn related data will be found after the SOS marker
                            // We should have gathered everything we need by now.
                            return;
                        }

                    case JpegConstants.Markers.DHT:
                        if (metadataOnly)
                        {
                            this.InputStream.Skip(remaining);
                        }
                        else
                        {
                            this.ProcessDefineHuffmanTablesMarker(remaining);
                        }

                        break;

                    case JpegConstants.Markers.DQT:
                        if (metadataOnly)
                        {
                            this.InputStream.Skip(remaining);
                        }
                        else
                        {
                            this.ProcessDefineQuantizationTablesMarker(remaining);
                        }

                        break;

                    case JpegConstants.Markers.DRI:
                        if (metadataOnly)
                        {
                            this.InputStream.Skip(remaining);
                        }
                        else
                        {
                            this.ProcessDefineRestartIntervalMarker(remaining);
                        }

                        break;

                    case JpegConstants.Markers.APP0:
                        this.ProcessApplicationHeaderMarker(remaining);
                        break;

                    case JpegConstants.Markers.APP1:
                        this.ProcessApp1Marker(remaining);
                        break;

                    case JpegConstants.Markers.APP2:
                        this.ProcessApp2Marker(remaining);
                        break;

                    case JpegConstants.Markers.APP3:
                    case JpegConstants.Markers.APP4:
                    case JpegConstants.Markers.APP5:
                    case JpegConstants.Markers.APP6:
                    case JpegConstants.Markers.APP7:
                    case JpegConstants.Markers.APP8:
                    case JpegConstants.Markers.APP9:
                    case JpegConstants.Markers.APP10:
                    case JpegConstants.Markers.APP11:
                    case JpegConstants.Markers.APP12:
                    case JpegConstants.Markers.APP13:
                        this.InputStream.Skip(remaining);
                        break;

                    case JpegConstants.Markers.APP14:
                        this.ProcessApp14Marker(remaining);
                        break;

                    case JpegConstants.Markers.APP15:
                    case JpegConstants.Markers.COM:
                        this.InputStream.Skip(remaining);
                        break;
                    }
                }

                // Read on.
                fileMarker = FindNextFileMarker(this.markerBuffer, this.InputStream);
            }
        }
        /// <summary>
        /// Parses the input stream for file markers
        /// </summary>
        /// <param name="stream">The input stream</param>
        /// <param name="metadataOnly">Whether to decode metadata only.</param>
        public void ParseStream(Stream stream, bool metadataOnly = false)
        {
            this.MetaData    = new ImageMetaData();
            this.InputStream = stream;

            // Check for the Start Of Image marker.
            var fileMarker = new PdfJsFileMarker(this.ReadUint16(), 0);

            if (fileMarker.Marker != PdfJsJpegConstants.Markers.SOI)
            {
                throw new ImageFormatException("Missing SOI marker.");
            }

            ushort marker = this.ReadUint16();

            fileMarker = new PdfJsFileMarker(marker, (int)this.InputStream.Position - 2);

            this.QuantizationTables = new Block8x8F[4];

            // this.quantizationTables = new PdfJsQuantizationTables(this.configuration.MemoryManager);
            this.dcHuffmanTables = new PdfJsHuffmanTables();
            this.acHuffmanTables = new PdfJsHuffmanTables();

            while (fileMarker.Marker != PdfJsJpegConstants.Markers.EOI)
            {
                // Get the marker length
                int remaining = this.ReadUint16() - 2;

                switch (fileMarker.Marker)
                {
                case PdfJsJpegConstants.Markers.APP0:
                    this.ProcessApplicationHeaderMarker(remaining);
                    break;

                case PdfJsJpegConstants.Markers.APP1:
                    this.ProcessApp1Marker(remaining);
                    break;

                case PdfJsJpegConstants.Markers.APP2:
                    this.ProcessApp2Marker(remaining);
                    break;

                case PdfJsJpegConstants.Markers.APP3:
                case PdfJsJpegConstants.Markers.APP4:
                case PdfJsJpegConstants.Markers.APP5:
                case PdfJsJpegConstants.Markers.APP6:
                case PdfJsJpegConstants.Markers.APP7:
                case PdfJsJpegConstants.Markers.APP8:
                case PdfJsJpegConstants.Markers.APP9:
                case PdfJsJpegConstants.Markers.APP10:
                case PdfJsJpegConstants.Markers.APP11:
                case PdfJsJpegConstants.Markers.APP12:
                case PdfJsJpegConstants.Markers.APP13:
                    this.InputStream.Skip(remaining);
                    break;

                case PdfJsJpegConstants.Markers.APP14:
                    this.ProcessApp14Marker(remaining);
                    break;

                case PdfJsJpegConstants.Markers.APP15:
                case PdfJsJpegConstants.Markers.COM:
                    this.InputStream.Skip(remaining);
                    break;

                case PdfJsJpegConstants.Markers.DQT:
                    if (metadataOnly)
                    {
                        this.InputStream.Skip(remaining);
                    }
                    else
                    {
                        this.ProcessDefineQuantizationTablesMarker(remaining);
                    }

                    break;

                case PdfJsJpegConstants.Markers.SOF0:
                case PdfJsJpegConstants.Markers.SOF1:
                case PdfJsJpegConstants.Markers.SOF2:
                    this.ProcessStartOfFrameMarker(remaining, fileMarker);
                    if (metadataOnly && !this.jFif.Equals(default))
                    {
                        this.InputStream.Skip(remaining);
                    }

                    break;

                case PdfJsJpegConstants.Markers.DHT:
                    if (metadataOnly)
                    {
                        this.InputStream.Skip(remaining);
                    }
                    else
                    {
                        this.ProcessDefineHuffmanTablesMarker(remaining);
                    }

                    break;

                case PdfJsJpegConstants.Markers.DRI:
                    if (metadataOnly)
                    {
                        this.InputStream.Skip(remaining);
                    }
                    else
                    {
                        this.ProcessDefineRestartIntervalMarker(remaining);
                    }

                    break;

                case PdfJsJpegConstants.Markers.SOS:
                    if (!metadataOnly)
                    {
                        this.ProcessStartOfScanMarker();
                    }

                    break;
                }

                // Read on.
                fileMarker = FindNextFileMarker(this.markerBuffer, this.InputStream);
            }

            this.ImageWidth     = this.Frame.SamplesPerLine;
            this.ImageHeight    = this.Frame.Scanlines;
            this.ComponentCount = this.Frame.ComponentCount;
        }
        /// <summary>
        /// Parses the input stream for file markers
        /// </summary>
        /// <param name="metaData">Contains the metadata for an image</param>
        /// <param name="metadataOnly">Whether to decode metadata only.</param>
        private void ParseStream(ImageMetaData metaData, bool metadataOnly)
        {
            // TODO: metadata only logic
            // Check for the Start Of Image marker.
            var fileMarker = new PdfJsFileMarker(this.ReadUint16(), 0);

            if (fileMarker.Marker != PdfJsJpegConstants.Markers.SOI)
            {
                throw new ImageFormatException("Missing SOI marker.");
            }

            ushort marker = this.ReadUint16();

            fileMarker = new PdfJsFileMarker(marker, (int)this.InputStream.Position - 2);

            this.quantizationTables = new PdfJsQuantizationTables();
            this.dcHuffmanTables    = new PdfJsHuffmanTables();
            this.acHuffmanTables    = new PdfJsHuffmanTables();

            while (fileMarker.Marker != PdfJsJpegConstants.Markers.EOI)
            {
                // Get the marker length
                int remaining = this.ReadUint16() - 2;

                switch (fileMarker.Marker)
                {
                case PdfJsJpegConstants.Markers.APP0:
                    this.ProcessApplicationHeaderMarker(remaining);
                    break;

                case PdfJsJpegConstants.Markers.APP1:
                    this.ProcessApp1Marker(remaining, metaData);
                    break;

                case PdfJsJpegConstants.Markers.APP2:
                    this.ProcessApp2Marker(remaining, metaData);
                    break;

                case PdfJsJpegConstants.Markers.APP3:
                case PdfJsJpegConstants.Markers.APP4:
                case PdfJsJpegConstants.Markers.APP5:
                case PdfJsJpegConstants.Markers.APP6:
                case PdfJsJpegConstants.Markers.APP7:
                case PdfJsJpegConstants.Markers.APP8:
                case PdfJsJpegConstants.Markers.APP9:
                case PdfJsJpegConstants.Markers.APP10:
                case PdfJsJpegConstants.Markers.APP11:
                case PdfJsJpegConstants.Markers.APP12:
                case PdfJsJpegConstants.Markers.APP13:
                    this.InputStream.Skip(remaining);
                    break;

                case PdfJsJpegConstants.Markers.APP14:
                    this.ProcessApp14Marker(remaining);
                    break;

                case PdfJsJpegConstants.Markers.APP15:
                case PdfJsJpegConstants.Markers.COM:
                    this.InputStream.Skip(remaining);
                    break;

                case PdfJsJpegConstants.Markers.DQT:
                    this.ProcessDefineQuantizationTablesMarker(remaining);
                    break;

                case PdfJsJpegConstants.Markers.SOF0:
                case PdfJsJpegConstants.Markers.SOF1:
                case PdfJsJpegConstants.Markers.SOF2:
                    this.ProcessStartOfFrameMarker(remaining, fileMarker);
                    break;

                case PdfJsJpegConstants.Markers.DHT:
                    this.ProcessDefineHuffmanTablesMarker(remaining);
                    break;

                case PdfJsJpegConstants.Markers.DRI:
                    this.ProcessDefineRestartIntervalMarker(remaining);
                    break;

                case PdfJsJpegConstants.Markers.SOS:
                    this.ProcessStartOfScanMarker();
                    break;
                }

                // Read on.
                fileMarker = FindNextFileMarker(this.markerBuffer, this.InputStream);
            }

            this.ImageWidth  = this.Frame.SamplesPerLine;
            this.ImageHeight = this.Frame.Scanlines;
            this.components  = new PdfJsComponentBlocks {
                Components = new PdfJsComponent[this.Frame.ComponentCount]
            };

            for (int i = 0; i < this.components.Components.Length; i++)
            {
                PdfJsFrameComponent frameComponent = this.Frame.Components[i];
                var component = new PdfJsComponent
                {
                    Scale = new System.Numerics.Vector2(
                        frameComponent.HorizontalSamplingFactor / (float)this.Frame.MaxHorizontalFactor,
                        frameComponent.VerticalSamplingFactor / (float)this.Frame.MaxVerticalFactor),
                    BlocksPerLine   = frameComponent.WidthInBlocks,
                    BlocksPerColumn = frameComponent.HeightInBlocks
                };

                // this.QuantizeAndInverseComponentData(ref component, frameComponent);
                this.components.Components[i] = component;
            }

            this.NumberOfComponents = this.components.Components.Length;
        }