/// <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); } } }
public static unsafe float GetScalarAt(Block8x8F *blockPtr, int idx) { float *fp = (float *)blockPtr; return(fp[idx]); }
public static unsafe void LoadFrom(Block8x8F *blockPtr, MutableSpan <float> source) { Marshal.Copy(source.Data, source.Offset, (IntPtr)blockPtr, ScalarCount); }
public static unsafe void CopyTo(Block8x8F *blockPtr, MutableSpan <float> dest) { Marshal.Copy((IntPtr)blockPtr, dest.Data, dest.Offset, ScalarCount); }
public static unsafe void SetScalarAt(Block8x8F *blockPtr, int idx, float value) { float *fp = (float *)blockPtr; fp[idx] = value; }