public JpegHuffmanProgressiveScanDecoder(JpegDecoder decoder, JpegFrameHeader frameHeader) : base(decoder) { _frameHeader = frameHeader; // Compute maximum sampling factor int maxHorizontalSampling = 1; int maxVerticalSampling = 1; foreach (JpegFrameComponentSpecificationParameters currentFrameComponent in frameHeader.Components !) { maxHorizontalSampling = Math.Max(maxHorizontalSampling, currentFrameComponent.HorizontalSamplingFactor); maxVerticalSampling = Math.Max(maxVerticalSampling, currentFrameComponent.VerticalSamplingFactor); } _mcusPerLine = (frameHeader.SamplesPerLine + 8 * maxHorizontalSampling - 1) / (8 * maxHorizontalSampling); _mcusPerColumn = (frameHeader.NumberOfLines + 8 * maxVerticalSampling - 1) / (8 * maxVerticalSampling); _levelShift = 1 << (frameHeader.SamplePrecision - 1); JpegBlockOutputWriter?outputWriter = decoder.GetOutputWriter(); if (outputWriter is null) { ThrowInvalidDataException("Output writer is not set."); } _outputWriter = outputWriter; _allocator = new JpegBlockAllocator(decoder.MemoryPool); _allocator.Allocate(frameHeader); // Pre-allocate the JpegDecodeComponent instances _components = new JpegHuffmanDecodingComponent[frameHeader.NumberOfComponents]; for (int i = 0; i < _components.Length; i++) { _components[i] = new JpegHuffmanDecodingComponent(); } }
private void DecodeProgressiveDataInterleaved(ref JpegReader reader, JpegScanHeader scanHeader, Span <JpegArithmeticDecodingComponent> components) { foreach (JpegArithmeticDecodingComponent component in components) { if (component.DcTable is null || component.DcStatistics is null) { ThrowInvalidDataException(); } } JpegBlockAllocator allocator = _allocator; JpegBitReader bitReader = new JpegBitReader(reader.RemainingBytes); int mcusPerColumn = _mcusPerColumn; int mcusPerLine = _mcusPerLine; for (int rowMcu = 0; rowMcu < mcusPerColumn; rowMcu++) { for (int colMcu = 0; colMcu < mcusPerLine; colMcu++) { foreach (JpegArithmeticDecodingComponent component in components) { int index = component.ComponentIndex; int h = component.HorizontalSamplingFactor; int v = component.VerticalSamplingFactor; int offsetX = colMcu * h; int offsetY = rowMcu * v; for (int y = 0; y < v; y++) { int blockOffsetY = offsetY + y; for (int x = 0; x < h; x++) { ref JpegBlock8x8 blockRef = ref allocator.GetBlockReference(index, offsetX + x, blockOffsetY); ReadBlockProgressiveDC(ref bitReader, component, scanHeader, ref blockRef); } } } if (!HandleRestart(ref bitReader, ref reader, ref scanHeader, ref MemoryMarshal.GetReference(components), components.Length)) { return; } } }
private void DecodeProgressiveDataInterleaved(ref JpegReader reader, JpegScanHeader scanHeader, Span <JpegHuffmanDecodingComponent> components) { JpegBlockAllocator allocator = _allocator; JpegBitReader bitReader = new JpegBitReader(reader.RemainingBytes); int mcusPerColumn = _mcusPerColumn; int mcusPerLine = _mcusPerLine; for (int rowMcu = 0; rowMcu < mcusPerColumn; rowMcu++) { for (int colMcu = 0; colMcu < mcusPerLine; colMcu++) { foreach (JpegHuffmanDecodingComponent component in components) { int index = component.ComponentIndex; int h = component.HorizontalSamplingFactor; int v = component.VerticalSamplingFactor; int offsetX = colMcu * h; int offsetY = rowMcu * v; for (int y = 0; y < v; y++) { int blockOffsetY = offsetY + y; for (int x = 0; x < h; x++) { ref JpegBlock8x8 blockRef = ref allocator.GetBlockReference(index, offsetX + x, blockOffsetY); ReadBlockProgressiveDC(ref bitReader, component, scanHeader, ref blockRef); } } } if (!HandleRestart(ref bitReader, ref reader)) { return; } } }