private JpegScanHeader ProcessScanHeader(ref JpegReader reader, bool metadataOnly) { if (!reader.TryReadLength(out ushort length)) { ThrowInvalidDataException(reader.ConsumedByteCount, "Unexpected end of input data when reading segment length."); } if (!reader.TryReadBytes(length, out ReadOnlySequence <byte> buffer)) { ThrowInvalidDataException(reader.ConsumedByteCount, "Unexpected end of input data when reading segment content."); } if (!JpegScanHeader.TryParse(buffer, metadataOnly, out JpegScanHeader scanHeader, out int bytesConsumed)) { ThrowInvalidDataException(reader.ConsumedByteCount - length + bytesConsumed, "Failed to parse scan header."); } return(scanHeader); }
public void Optimize(bool strip = true) { if (_encodingTables.IsEmpty) { throw new InvalidOperationException(); } IBufferWriter <byte> bufferWriter = _output ?? throw new InvalidOperationException(); JpegReader reader = new JpegReader(_inputBuffer); var writer = new JpegWriter(bufferWriter, _minimumBufferSegmentSize); bool eoiReached = false; bool huffmanTableWritten = false; bool quantizationTableWritten = false; while (!eoiReached && !reader.IsEmpty) { if (!reader.TryReadMarker(out JpegMarker marker)) { ThrowInvalidDataException(reader.ConsumedByteCount, "No marker found."); return; } switch (marker) { case JpegMarker.StartOfImage: writer.WriteMarker(marker); break; case JpegMarker.App0: case JpegMarker.StartOfFrame0: case JpegMarker.StartOfFrame1: writer.WriteMarker(marker); CopyMarkerData(ref reader, ref writer); break; case JpegMarker.StartOfFrame2: ProcessFrameHeader(ref reader, false, true); throw new InvalidDataException("Progressive JPEG is not supported currently."); case JpegMarker.StartOfFrame3: case JpegMarker.StartOfFrame5: case JpegMarker.StartOfFrame6: case JpegMarker.StartOfFrame7: case JpegMarker.StartOfFrame9: case JpegMarker.StartOfFrame10: case JpegMarker.StartOfFrame11: case JpegMarker.StartOfFrame13: case JpegMarker.StartOfFrame14: case JpegMarker.StartOfFrame15: ThrowInvalidDataException(reader.ConsumedByteCount, $"This type of JPEG stream is not supported ({marker})."); return; case JpegMarker.DefineHuffmanTable: if (!huffmanTableWritten) { WriteHuffmanTables(ref writer); huffmanTableWritten = true; } break; case JpegMarker.DefineQuantizationTable: if (!quantizationTableWritten) { WriteQuantizationTables(ref writer); quantizationTableWritten = true; } break; case JpegMarker.StartOfScan: writer.WriteMarker(marker); ReadOnlySequence <byte> buffer = CopyMarkerData(ref reader, ref writer); if (!JpegScanHeader.TryParse(buffer, false, out JpegScanHeader scanHeader, out _)) { ThrowInvalidDataException(reader.ConsumedByteCount - (int)buffer.Length, "Failed to parse scan header."); } CopyScanBaseline(ref reader, ref writer, scanHeader); break; case JpegMarker.DefineRestart0: case JpegMarker.DefineRestart1: case JpegMarker.DefineRestart2: case JpegMarker.DefineRestart3: case JpegMarker.DefineRestart4: case JpegMarker.DefineRestart5: case JpegMarker.DefineRestart6: case JpegMarker.DefineRestart7: writer.WriteMarker(marker); break; case JpegMarker.EndOfImage: writer.WriteMarker(JpegMarker.EndOfImage); eoiReached = true; break; default: if (strip) { SkipMarkerData(ref reader); } else { writer.WriteMarker(marker); CopyMarkerData(ref reader, ref writer); } break; } } writer.Flush(); }