/// <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="TPixel">The pixel format.</typeparam>
        /// <param name="pixels">The pixel accessor providing access to the image pixels.</param>
        private void Encode420 <TPixel>(Image <TPixel> pixels)
            where TPixel : struct, IPixel <TPixel>
        {
            // TODO: Need a JpegScanEncoder<TPixel> 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;

            ZigZag unzig = ZigZag.CreateUnzigTable();

            var pixelConverter = YCbCrForwardConverter <TPixel> .Create();

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

            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;

                        pixelConverter.Convert(pixels.Frames.RootFrame, x + xOff, y + yOff);

                        cbPtr[i] = pixelConverter.Cb;
                        crPtr[i] = pixelConverter.Cr;

                        prevDCY = this.WriteBlock(
                            QuantIndex.Luminance,
                            prevDCY,
                            &pixelConverter.Y,
                            &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);
                }
            }
        }
Exemple #2
0
        public static unsafe float GetScalarAt(Block8x8F *blockPtr, int idx)
        {
            float *fp = (float *)blockPtr;

            return(fp[idx]);
        }
Exemple #3
0
 public static unsafe void LoadFrom(Block8x8F *blockPtr, MutableSpan <float> source)
 {
     Marshal.Copy(source.Data, source.Offset, (IntPtr)blockPtr, ScalarCount);
 }
Exemple #4
0
 public static unsafe void CopyTo(Block8x8F *blockPtr, MutableSpan <float> dest)
 {
     Marshal.Copy((IntPtr)blockPtr, dest.Data, dest.Offset, ScalarCount);
 }
Exemple #5
0
        public static unsafe void SetScalarAt(Block8x8F *blockPtr, int idx, float value)
        {
            float *fp = (float *)blockPtr;

            fp[idx] = value;
        }