/// <inheritdoc/> public void Dispose() { this.InputStream?.Dispose(); this.Frame?.Dispose(); this.fastACTables?.Dispose(); // Set large fields to null. this.InputStream = null; this.Frame = null; this.dcHuffmanTables = null; this.acHuffmanTables = null; this.fastACTables = null; }
/// <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.MemoryAllocator, stream); // Check for the Start Of Image marker. this.InputStream.Read(this.markerBuffer, 0, 2); var fileMarker = new JpegFileMarker(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 JpegFileMarker(marker, (int)this.InputStream.Position - 2); this.QuantizationTables = new Block8x8F[4]; // Only assign what we need if (!metadataOnly) { this.dcHuffmanTables = new HuffmanTables(); this.acHuffmanTables = new HuffmanTables(); this.fastACTables = new FastACTables(this.configuration.MemoryAllocator); } // Break only when we discover a valid EOI marker. // https://github.com/SixLabors/ImageSharp/issues/695 while (fileMarker.Marker != JpegConstants.Markers.EOI || (fileMarker.Marker == JpegConstants.Markers.EOI && fileMarker.Invalid)) { 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: 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); } }