Esempio n. 1
0
        /// <summary>
        /// Initializes <see cref="SpectralBlocks"/>
        /// </summary>
        /// <param name="memoryManager">The <see cref="MemoryManager"/> to use for buffer allocations.</param>
        /// <param name="decoder">The <see cref="OrigJpegDecoderCore"/> instance</param>
        public void InitializeDerivedData(MemoryManager memoryManager, OrigJpegDecoderCore decoder)
        {
            // For 4-component images (either CMYK or YCbCrK), we only support two
            // hv vectors: [0x11 0x11 0x11 0x11] and [0x22 0x11 0x11 0x22].
            // Theoretically, 4-component JPEG images could mix and match hv values
            // but in practice, those two combinations are the only ones in use,
            // and it simplifies the applyBlack code below if we can assume that:
            // - for CMYK, the C and K channels have full samples, and if the M
            // and Y channels subsample, they subsample both horizontally and
            // vertically.
            // - for YCbCrK, the Y and K channels have full samples.
            this.SizeInBlocks = decoder.ImageSizeInMCU.MultiplyBy(this.SamplingFactors);

            if (this.Index == 0 || this.Index == 3)
            {
                this.SubSamplingDivisors = new Size(1, 1);
            }
            else
            {
                OrigComponent c0 = decoder.Components[0];
                this.SubSamplingDivisors = c0.SamplingFactors.DivideBy(this.SamplingFactors);
            }

            this.SpectralBlocks = memoryManager.Allocate2D <Block8x8>(this.SizeInBlocks.Width, this.SizeInBlocks.Height, true);
        }
        private void DecodeBlocksAtMcuIndex(OrigJpegDecoderCore decoder, int mx, int my)
        {
            for (int scanIndex = 0; scanIndex < this.componentScanCount; scanIndex++)
            {
                this.ComponentIndex = this.pointers.ComponentScan[scanIndex].ComponentIndex;
                OrigComponent component = decoder.Components[this.ComponentIndex];

                this.hi = component.HorizontalSamplingFactor;
                int vi = component.VerticalSamplingFactor;

                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 = this.blockCounter % q;
                        this.by = this.blockCounter / q;
                        this.blockCounter++;
                        if (this.bx * 8 >= decoder.ImageWidth || this.by * 8 >= decoder.ImageHeight)
                        {
                            continue;
                        }
                    }

                    // Find the block at (bx,by) in the component's buffer:
                    ref Block8x8 blockRefOnHeap = ref component.GetBlockReference(this.bx, this.by);

                    // Copy block to stack
                    this.data.Block = blockRefOnHeap;

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

                    // Store the result block:
                    blockRefOnHeap = this.data.Block;
                }
            }
Esempio n. 3
0
        /// <summary>
        /// Read Huffman data from Jpeg scans in <see cref="OrigJpegDecoderCore.InputStream"/>,
        /// and decode it as <see cref="Block8x8"/> into <see cref="OrigComponent.SpectralBlocks"/>.
        ///
        /// 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="OrigJpegDecoderCore"/> instance</param>
        public void DecodeBlocks(OrigJpegDecoderCore decoder)
        {
            decoder.InputProcessor.ResetErrorState();

            int  blockCount  = 0;
            int  mcu         = 0;
            byte expectedRst = OrigJpegConstants.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;
                        OrigComponent component = decoder.Components[this.ComponentIndex];

                        this.hi = component.HorizontalSamplingFactor;
                        int vi = component.VerticalSamplingFactor;

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

                            // Find the block at (bx,by) in the component's buffer:
                            ref Block8x8 blockRefOnHeap = ref component.GetBlockReference(this.bx, this.by);

                            // Copy block to stack
                            this.data.Block = blockRefOnHeap;

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

                            // Store the result block:
                            blockRefOnHeap = 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.ReachedEOF)
                        {
                            decoder.InputProcessor.ReadFullUnsafe(decoder.Temp, 0, 2);
                            if (decoder.InputProcessor.CheckEOFEnsureNoError())
                            {
                                if (decoder.Temp[0] != 0xff || decoder.Temp[1] != expectedRst)
                                {
                                    throw new ImageFormatException("Bad RST marker");
                                }

                                expectedRst++;
                                if (expectedRst == OrigJpegConstants.Markers.RST7 + 1)
                                {
                                    expectedRst = OrigJpegConstants.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
            }