Пример #1
0
        /// <summary>
        /// Writes a block of pixel data using the given quantization table,
        /// returning the post-quantized DC value of the DCT-transformed block.
        /// The block is in natural (not zig-zag) order.
        /// </summary>
        /// <param name="index">The quantization table index.</param>
        /// <param name="prevDC">The previous DC value.</param>
        /// <param name="src">Source block</param>
        /// <param name="tempDest1">Temporal block to be used as FDCT Destination</param>
        /// <param name="tempDest2">Temporal block 2</param>
        /// <param name="quant">Quantization table</param>
        /// <param name="unzigPtr">The 8x8 Unzig block pointer</param>
        /// <returns>
        /// The <see cref="int"/>
        /// </returns>
        private int WriteBlock(
            QuantIndex index,
            int prevDC,
            Block8x8F *src,
            Block8x8F *tempDest1,
            Block8x8F *tempDest2,
            Block8x8F *quant,
            int *unzigPtr)
        {
            DCT.TransformFDCT(ref *src, ref *tempDest1, ref *tempDest2);

            Block8x8F.UnzigDivRound(tempDest1, tempDest2, quant, unzigPtr);
            float *unziggedDestPtr = (float *)tempDest2;

            int dc = (int)unziggedDestPtr[0];

            // Emit the DC delta.
            this.EmitHuffRLE((HuffIndex)((2 * (int)index) + 0), 0, dc - prevDC);

            // Emit the AC components.
            HuffIndex h         = (HuffIndex)((2 * (int)index) + 1);
            int       runLength = 0;

            for (int zig = 1; zig < Block8x8F.ScalarCount; zig++)
            {
                int ac = (int)unziggedDestPtr[zig];

                if (ac == 0)
                {
                    runLength++;
                }
                else
                {
                    while (runLength > 15)
                    {
                        this.EmitHuff(h, 0xf0);
                        runLength -= 16;
                    }

                    this.EmitHuffRLE(h, runLength, ac);
                    runLength = 0;
                }
            }

            if (runLength > 0)
            {
                this.EmitHuff(h, 0x00);
            }

            return(dc);
        }
Пример #2
0
        /// <summary>
        /// Initializes quantization table.
        /// </summary>
        /// <param name="i">The quantization index.</param>
        /// <param name="scale">The scaling factor.</param>
        /// <param name="quant">The quantization table.</param>
        private static void InitQuantizationTable(int i, int scale, ref Block8x8F quant)
        {
            for (int j = 0; j < Block8x8F.ScalarCount; j++)
            {
                int x = UnscaledQuant[i, j];
                x = ((x * scale) + 50) / 100;
                if (x < 1)
                {
                    x = 1;
                }

                if (x > 255)
                {
                    x = 255;
                }

                quant[j] = x;
            }
        }
Пример #3
0
 internal void Clear()
 {
     // The cheapest way to do this in C#:
     this = new Block8x8F();
 }
Пример #4
0
        /// <summary>
        /// Encodes the image with subsampling. The Cb and Cr components are each subsampled
        /// at a factor of 2 both horizontally and vertically.
        /// </summary>
        /// <typeparam name="TColor">The pixel format.</typeparam>
        /// <param name="pixels">The pixel accessor providing access to the image pixels.</param>
        private void Encode420 <TColor>(PixelAccessor <TColor> pixels)
            where TColor : struct, IPackedPixel, IEquatable <TColor>
        {
            // TODO: Need a JpegScanEncoder<TColor> class or struct that encapsulates the scan-encoding implementation. (Similar to JpegScanDecoder.)
            Block8x8F b = default(Block8x8F);

            BlockQuad  cb    = default(BlockQuad);
            BlockQuad  cr    = default(BlockQuad);
            Block8x8F *cbPtr = (Block8x8F *)cb.Data;
            Block8x8F *crPtr = (Block8x8F *)cr.Data;

            Block8x8F temp1 = default(Block8x8F);
            Block8x8F temp2 = default(Block8x8F);

            Block8x8F onStackLuminanceQuantTable   = this.luminanceQuantTable;
            Block8x8F onStackChrominanceQuantTable = this.chrominanceQuantTable;

            UnzigData unzig = UnzigData.Create();

            // ReSharper disable once InconsistentNaming
            int prevDCY = 0, prevDCCb = 0, prevDCCr = 0;

            using (PixelArea <TColor> rgbBytes = new PixelArea <TColor>(8, 8, ComponentOrder.Xyz))
            {
                for (int y = 0; y < pixels.Height; y += 16)
                {
                    for (int x = 0; x < pixels.Width; x += 16)
                    {
                        for (int i = 0; i < 4; i++)
                        {
                            int xOff = (i & 1) * 8;
                            int yOff = (i & 2) * 4;

                            ToYCbCr(pixels, x + xOff, y + yOff, &b, cbPtr + i, crPtr + i, rgbBytes);

                            prevDCY = this.WriteBlock(
                                QuantIndex.Luminance,
                                prevDCY,
                                &b,
                                &temp1,
                                &temp2,
                                &onStackLuminanceQuantTable,
                                unzig.Data);
                        }

                        Block8x8F.Scale16X16To8X8(&b, cbPtr);
                        prevDCCb = this.WriteBlock(
                            QuantIndex.Chrominance,
                            prevDCCb,
                            &b,
                            &temp1,
                            &temp2,
                            &onStackChrominanceQuantTable,
                            unzig.Data);

                        Block8x8F.Scale16X16To8X8(&b, crPtr);
                        prevDCCr = this.WriteBlock(
                            QuantIndex.Chrominance,
                            prevDCCr,
                            &b,
                            &temp1,
                            &temp2,
                            &onStackChrominanceQuantTable,
                            unzig.Data);
                    }
                }
            }
        }