Пример #1
0
        public JpegArithmeticSequentialScanDecoder(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);
            }
            _maxHorizontalSampling = maxHorizontalSampling;
            _maxVerticalSampling   = maxVerticalSampling;

            _restartInterval = decoder.GetRestartInterval();
            _mcusPerLine     = (frameHeader.SamplesPerLine + 8 * maxHorizontalSampling - 1) / (8 * maxHorizontalSampling);
            _mcusPerColumn   = (frameHeader.NumberOfLines + 8 * maxVerticalSampling - 1) / (8 * maxVerticalSampling);
            _levelShift      = 1 << (frameHeader.SamplePrecision - 1);

            // Pre-allocate the JpegDecodeComponent instances
            _components = new JpegArithmeticDecodingComponent[frameHeader.NumberOfComponents];
            for (int i = 0; i < _components.Length; i++)
            {
                _components[i] = new JpegArithmeticDecodingComponent();
            }
        }
        public JpegArithmeticProgressiveScanDecoder(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 JpegArithmeticDecodingComponent[frameHeader.NumberOfComponents];
            for (int i = 0; i < _components.Length; i++)
            {
                _components[i] = new JpegArithmeticDecodingComponent();
            }
        }
        public JpegHuffmanLosslessScanDecoder(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);
            }

            _restartInterval = decoder.GetRestartInterval();
            _mcusPerLine     = (frameHeader.SamplesPerLine + maxHorizontalSampling - 1) / maxHorizontalSampling;
            _mcusPerColumn   = (frameHeader.NumberOfLines + maxVerticalSampling - 1) / maxVerticalSampling;

            JpegBlockOutputWriter?outputWriter = decoder.GetOutputWriter();

            if (outputWriter is null)
            {
                ThrowInvalidDataException("Output writer is not set.");
            }
            _allocator = new JpegPartialScanlineAllocator(outputWriter, 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();
            }
        }
            public void Encode(bool writeHuffmanTables, bool writeQuantizationTables, bool optimizeCoding)
            {
                JpegWriter writer = CreateJpegWriter();

                WriteStartOfImage(ref writer);
                if (writeQuantizationTables)
                {
                    WriteQuantizationTables(ref writer);
                }
                JpegFrameHeader    frameHeader = WriteStartOfFrame(ref writer);
                JpegBlockAllocator?allocator   = optimizeCoding ? new JpegBlockAllocator(MemoryPool) : null;

                try
                {
                    if (!(allocator is null))
                    {
                        allocator.Allocate(frameHeader);
                        TransformBlocks(allocator);
                        BuildHuffmanTables(frameHeader, allocator, false);
                        WriteHuffmanTables(ref writer);
                        WriteStartOfScan(ref writer);
                        WritePreparedScanData(frameHeader, allocator, ref writer);
                    }
                    else
                    {
                        if (writeHuffmanTables)
                        {
                            WriteHuffmanTables(ref writer);
                        }
                        WriteStartOfScan(ref writer);
                        WriteScanData(ref writer);
                    }
                }
        public void Decompress(TiffDecompressionContext context, ReadOnlyMemory <byte> input, Memory <byte> output)
        {
            // Copy frame header
            JpegFrameHeader frameHeader = _frameHeader;

            frameHeader = new JpegFrameHeader(frameHeader.SamplePrecision, (ushort)context.ImageSize.Height, (ushort)context.ImageSize.Width, frameHeader.NumberOfComponents, frameHeader.Components);

            var decoder = new JpegDecoder();

            decoder.StartOfFrame = JpegMarker.StartOfFrame0;
            decoder.MemoryPool   = context.MemoryPool;
            decoder.SetFrameHeader(frameHeader);
            decoder.SetRestartInterval(_restartInterval);

            foreach (ComponentInfo componentInfo in _components)
            {
                decoder.SetQuantizationTable(componentInfo.QuantizationTable);
                decoder.SetHuffmanTable(componentInfo.DcTable);
                decoder.SetHuffmanTable(componentInfo.AcTable);
            }

            var outputWriter = new JpegBuffer8BitOutputWriter(context.ImageSize.Width, context.SkippedScanlines, context.SkippedScanlines + context.RequestedScanlines, decoder.NumberOfComponents, output);

            decoder.SetOutputWriter(outputWriter);

            var reader = new JpegReader(input);

            decoder.ProcessScan(ref reader, _scanHeader);
        }
        public void Initialize(ushort restartInterval, ushort[] subsamplingFactors)
        {
            _restartInterval = restartInterval;

            // Make sure everything is initialized
            if (_components.Length == 0)
            {
                throw new InvalidDataException();
            }
            foreach (ComponentInfo component in _components)
            {
                if (!component.IsInitialized)
                {
                    throw new InvalidDataException();
                }
            }

            var frameComponents = new JpegFrameComponentSpecificationParameters[_components.Length];
            var scanComponents  = new JpegScanComponentSpecificationParameters[_components.Length];

            // Special case for YCbCr.
            if (subsamplingFactors.Length == 2)
            {
                if (frameComponents.Length != 3)
                {
                    // YCbCr image must have 3 components.
                    throw new InvalidDataException();
                }
                if (subsamplingFactors[0] != 1 && subsamplingFactors[0] != 2 && subsamplingFactors[0] != 4)
                {
                    throw new InvalidDataException("Subsampling factor other than 1,2,4 is not supported.");
                }
                if (subsamplingFactors[1] != 1 && subsamplingFactors[1] != 2 && subsamplingFactors[1] != 4)
                {
                    throw new InvalidDataException("Subsampling factor other than 1,2,4 is not supported.");
                }
                ushort maxFactor = Math.Max(subsamplingFactors[0], subsamplingFactors[1]);
                frameComponents[0] = new JpegFrameComponentSpecificationParameters(0, (byte)maxFactor, (byte)maxFactor, 0);
                frameComponents[1] = new JpegFrameComponentSpecificationParameters(1, (byte)(maxFactor / subsamplingFactors[0]), (byte)(maxFactor / subsamplingFactors[1]), 1);
                frameComponents[2] = new JpegFrameComponentSpecificationParameters(2, (byte)(maxFactor / subsamplingFactors[0]), (byte)(maxFactor / subsamplingFactors[1]), 2);
            }
            else
            {
                for (int i = 0; i < frameComponents.Length; i++)
                {
                    frameComponents[i] = new JpegFrameComponentSpecificationParameters((byte)i, 1, 1, (byte)i);
                }
            }

            for (int i = 0; i < scanComponents.Length; i++)
            {
                scanComponents[i] = new JpegScanComponentSpecificationParameters((byte)i, (byte)i, (byte)i);
            }

            _frameHeader = new JpegFrameHeader(8, 0, 0, (byte)frameComponents.Length, frameComponents);
            _scanHeader  = new JpegScanHeader((byte)scanComponents.Length, scanComponents, 0, 0, 0, 0);
        }
Пример #7
0
        protected int InitDecodeComponents(JpegFrameHeader frameHeader, JpegScanHeader scanHeader, Span <JpegArithmeticDecodingComponent> components)
        {
            Debug.Assert(!(frameHeader.Components is null));
            Debug.Assert(!(scanHeader.Components is null));

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

            // Resolve each component
            if (components.Length < scanHeader.NumberOfComponents)
            {
                throw new InvalidOperationException();
            }
            for (int i = 0; i < scanHeader.NumberOfComponents; i++)
            {
                JpegScanComponentSpecificationParameters scanComponenet = scanHeader.Components ![i];
Пример #8
0
        public override void ProcessScan(ref JpegReader reader, JpegScanHeader scanHeader)
        {
            JpegFrameHeader       frameHeader  = _frameHeader;
            JpegBlockOutputWriter?outputWriter = Decoder.GetOutputWriter();

            if (frameHeader.Components is null)
            {
                ThrowInvalidDataException();
            }
            if (scanHeader.Components is null)
            {
                ThrowInvalidDataException();
            }
            if (outputWriter is null)
            {
                ThrowInvalidDataException();
            }

            // Resolve each component
            Span <JpegArithmeticDecodingComponent> components = _components.AsSpan(0, InitDecodeComponents(frameHeader, scanHeader, _components));

            foreach (JpegArithmeticDecodingComponent component in _components)
            {
                component.DcPredictor = 0;
                component.DcContext   = 0;
                component.DcStatistics?.Reset();
                component.AcStatistics?.Reset();
            }

            Reset();

            // Prepare
            int           maxHorizontalSampling = _maxHorizontalSampling;
            int           maxVerticalSampling   = _maxVerticalSampling;
            int           mcusBeforeRestart     = _restartInterval;
            int           mcusPerLine           = _mcusPerLine;
            int           mcusPerColumn         = _mcusPerColumn;
            int           levelShift            = _levelShift;
            JpegBitReader bitReader             = new JpegBitReader(reader.RemainingBytes);

            // DCT Block
            JpegBlock8x8F blockFBuffer  = default;
            JpegBlock8x8F outputFBuffer = default;
            JpegBlock8x8F tempFBuffer   = default;

            JpegBlock8x8 outputBuffer;

            for (int rowMcu = 0; rowMcu < mcusPerColumn; rowMcu++)
            {
                int offsetY = rowMcu * maxVerticalSampling;
                for (int colMcu = 0; colMcu < mcusPerLine; colMcu++)
                {
                    int offsetX = colMcu * maxHorizontalSampling;

                    // Scan an interleaved mcu... process components in order
                    foreach (JpegArithmeticDecodingComponent component in components)
                    {
                        int index = component.ComponentIndex;
                        int h     = component.HorizontalSamplingFactor;
                        int v     = component.VerticalSamplingFactor;
                        int hs    = component.HorizontalSubsamplingFactor;
                        int vs    = component.VerticalSubsamplingFactor;

                        for (int y = 0; y < v; y++)
                        {
                            int blockOffsetY = (offsetY + y) * 8;
                            for (int x = 0; x < h; x++)
                            {
                                // Read MCU
                                outputBuffer = default;
                                ReadBlock(ref bitReader, component, ref outputBuffer);

                                // Dequantization
                                DequantizeBlockAndUnZigZag(component.QuantizationTable, ref outputBuffer, ref blockFBuffer);

                                // IDCT
                                FastFloatingPointDCT.TransformIDCT(ref blockFBuffer, ref outputFBuffer, ref tempFBuffer);

                                // Level shift
                                ShiftDataLevel(ref outputFBuffer, ref outputBuffer, levelShift);

                                // CopyToOutput
                                WriteBlock(outputWriter, ref Unsafe.As <JpegBlock8x8, short>(ref outputBuffer), index, (offsetX + x) * 8, blockOffsetY, hs, vs);
                            }
                        }
                    }

                    // Handle restart
                    if (_restartInterval > 0 && (--mcusBeforeRestart) == 0)
                    {
                        bitReader.AdvanceAlignByte();

                        JpegMarker marker = bitReader.TryReadMarker();
                        if (marker == JpegMarker.EndOfImage)
                        {
                            int bytesConsumedEoi = reader.RemainingByteCount - bitReader.RemainingBits / 8;
                            reader.TryAdvance(bytesConsumedEoi - 2);
                            return;
                        }
                        if (!marker.IsRestartMarker())
                        {
                            throw new InvalidOperationException("Expect restart marker.");
                        }

                        mcusBeforeRestart = _restartInterval;

                        foreach (JpegArithmeticDecodingComponent component in components)
                        {
                            component.DcPredictor = 0;
                            component.DcContext   = 0;
                            component.DcStatistics?.Reset();
                            component.AcStatistics?.Reset();
                        }

                        Reset();
                    }
                }
            }

            bitReader.AdvanceAlignByte();
            int bytesConsumed = reader.RemainingByteCount - bitReader.RemainingBits / 8;

            if (bitReader.TryPeekMarker() != 0)
            {
                if (!bitReader.TryPeekMarker().IsRestartMarker())
                {
                    bytesConsumed -= 2;
                }
            }
            reader.TryAdvance(bytesConsumed);
        }
Пример #9
0
        public static JpegScanDecoder?Create(JpegMarker sofMarker, JpegDecoder decoder, JpegFrameHeader header)
        {
            switch (sofMarker)
            {
            case JpegMarker.StartOfFrame0:
            case JpegMarker.StartOfFrame1:
                return(new JpegHuffmanBaselineScanDecoder(decoder, header));

            case JpegMarker.StartOfFrame2:
                return(new JpegHuffmanProgressiveScanDecoder(decoder, header));

            case JpegMarker.StartOfFrame3:
                return(new JpegHuffmanLosslessScanDecoder(decoder, header));

            case JpegMarker.StartOfFrame9:
                return(new JpegArithmeticSequentialScanDecoder(decoder, header));

            case JpegMarker.StartOfFrame10:
                return(new JpegArithmeticProgressiveScanDecoder(decoder, header));

            default:
                return(null);
            }
        }