/// <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(); }
/// <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; }