/// <summary>
        /// Dequantize, perform the inverse DCT and store the blocks to the into the corresponding <see cref="JpegPixelArea"/> instances.
        /// </summary>
        /// <param name="decoder">The <see cref="JpegDecoderCore"/> instance</param>
        public void ProcessAllBlocks(JpegDecoderCore decoder)
        {
            DecodedBlockArray blockArray = decoder.DecodedBlocks[this.componentIndex];

            for (int i = 0; i < blockArray.Count; i++)
            {
                this.ProcessBlockColors(decoder, ref blockArray.Buffer[i]);
            }
        }
Exemple #2
0
        /// <summary>
        /// Read Huffman data from Jpeg scans in <see cref="JpegDecoderCore.InputStream"/>,
        /// and decode it as <see cref="Block8x8F"/> into <see cref="JpegDecoderCore.DecodedBlocks"/>.
        ///
        /// The blocks are traversed one MCU at a time. For 4:2:0 chroma
        /// subsampling, there are four Y 8x8 blocks in every 16x16 MCU.
        /// For a baseline 32x16 pixel image, the Y blocks visiting order is:
        /// 0 1 4 5
        /// 2 3 6 7
        /// For progressive images, the interleaved scans (those with component count &gt; 1)
        /// are traversed as above, but non-interleaved scans are traversed left
        /// to right, top to bottom:
        /// 0 1 2 3
        /// 4 5 6 7
        /// Only DC scans (zigStart == 0) can be interleave AC scans must have
        /// only one component.
        /// To further complicate matters, for non-interleaved scans, there is no
        /// data for any blocks that are inside the image at the MCU level but
        /// outside the image at the pixel level. For example, a 24x16 pixel 4:2:0
        /// progressive image consists of two 16x16 MCUs. The interleaved scans
        /// will process 8 Y blocks:
        /// 0 1 4 5
        /// 2 3 6 7
        /// The non-interleaved scans will process only 6 Y blocks:
        /// 0 1 2
        /// 3 4 5
        /// </summary>
        /// <param name="decoder">The <see cref="JpegDecoderCore"/> instance</param>
        public void DecodeBlocks(JpegDecoderCore decoder)
        {
            int  blockCount  = 0;
            int  mcu         = 0;
            byte expectedRst = JpegConstants.Markers.RST0;

            for (int my = 0; my < decoder.MCUCountY; my++)
            {
                for (int mx = 0; mx < decoder.MCUCountX; mx++)
                {
                    for (int scanIndex = 0; scanIndex < this.componentScanCount; scanIndex++)
                    {
                        this.ComponentIndex = this.pointers.ComponentScan[scanIndex].ComponentIndex;
                        this.hi             = decoder.ComponentArray[this.ComponentIndex].HorizontalFactor;
                        int vi = decoder.ComponentArray[this.ComponentIndex].VerticalFactor;

                        for (int j = 0; j < this.hi * vi; j++)
                        {
                            if (this.componentScanCount != 1)
                            {
                                this.bx = (this.hi * mx) + (j % this.hi);
                                this.by = (vi * my) + (j / this.hi);
                            }
                            else
                            {
                                int q = decoder.MCUCountX * this.hi;
                                this.bx = blockCount % q;
                                this.by = blockCount / q;
                                blockCount++;
                                if (this.bx * 8 >= decoder.ImageWidth || this.by * 8 >= decoder.ImageHeight)
                                {
                                    continue;
                                }
                            }

                            // Take an existing block (required when progressive):
                            int blockIndex = this.GetBlockIndex(decoder);
                            this.data.Block = decoder.DecodedBlocks[this.ComponentIndex].Buffer[blockIndex].Block;

                            if (!decoder.InputProcessor.UnexpectedEndOfStreamReached)
                            {
                                this.DecodeBlock(decoder, scanIndex);
                            }

                            // Store the decoded block
                            DecodedBlockArray blocks = decoder.DecodedBlocks[this.ComponentIndex];
                            blocks.Buffer[blockIndex].SaveBlock(this.bx, this.by, ref this.data.Block);
                        }

                        // for j
                    }

                    // for i
                    mcu++;

                    if (decoder.RestartInterval > 0 && mcu % decoder.RestartInterval == 0 && mcu < decoder.TotalMCUCount)
                    {
                        // A more sophisticated decoder could use RST[0-7] markers to resynchronize from corrupt input,
                        // but this one assumes well-formed input, and hence the restart marker follows immediately.
                        if (!decoder.InputProcessor.UnexpectedEndOfStreamReached)
                        {
                            DecoderErrorCode errorCode = decoder.InputProcessor.ReadFullUnsafe(decoder.Temp, 0, 2);
                            if (decoder.InputProcessor.CheckEOFEnsureNoError(errorCode))
                            {
                                if (decoder.Temp[0] != 0xff || decoder.Temp[1] != expectedRst)
                                {
                                    throw new ImageFormatException("Bad RST marker");
                                }

                                expectedRst++;
                                if (expectedRst == JpegConstants.Markers.RST7 + 1)
                                {
                                    expectedRst = JpegConstants.Markers.RST0;
                                }
                            }
                        }

                        // Reset the Huffman decoder.
                        decoder.InputProcessor.Bits = default(Bits);

                        // Reset the DC components, as per section F.2.1.3.1.
                        this.ResetDc();

                        // Reset the progressive decoder state, as per section G.1.2.2.
                        this.eobRun = 0;
                    }
                }

                // for mx
            }
        }