public WicPlanarSplitter(WicPlanarTransform prev, WicPlane plane) : base(prev.Context) { Frame = prev.Frame; Source = plane == WicPlane.Luma ? prev.SourceY : prev.SourceCbCr; Source.GetSize(out Context.Width, out Context.Height); }
unsafe public void CopyPixels(WicPlane plane, WICRect prc, uint cbStride, uint cbBufferSize, IntPtr pbBuffer) { if (lineBuffY.Array == null || (plane == WicPlane.Luma && prc.Y + prc.Height > loadedY) || (plane == WicPlane.Chroma && prc.Y + prc.Height > loadedC)) { loadBuffer(plane, prc); } switch (plane) { case WicPlane.Luma: fixed(byte *pBuffY = lineBuffY.Array) for (int y = 0; y < prc.Height; y++) { Buffer.MemoryCopy(pBuffY + (prc.Y - startY) * strideY + y * strideY + prc.X, (byte *)pbBuffer + y * cbStride, cbStride, prc.Width); } nextY = prc.Y + prc.Height - startY; break; case WicPlane.Chroma: fixed(byte *pBuffC = lineBuffC.Array) for (int y = 0; y < prc.Height; y++) { Buffer.MemoryCopy(pBuffC + (prc.Y - startC) * strideC + y * strideC + prc.X * 2, (byte *)pbBuffer + y * cbStride, cbStride, prc.Width * 2); } nextC = prc.Y + prc.Height - startC; break; } }
public PlanarPixelSource(WicPlanarCache cache, WicPlane plane, WICBitmapPlaneDescription planeDesc) { Width = planeDesc.Width; Height = planeDesc.Height; Format = PixelFormat.Cache[planeDesc.Format]; cacheSource = cache; cachePlane = plane; }
public WicPlanarSource(WicPlanarCacheSource cache, WicPlane plane, WICBitmapPlaneDescription planeDesc) { Width = planeDesc.Width; Height = planeDesc.Height; Format = planeDesc.Format; cacheSource = cache; cachePlane = plane; }
unsafe private void loadBuffer(WicPlane plane, WICRect prc) { if (lineBuffY.Array == null || nextY < buffHeightY / 4 || nextC < buffHeightC / 4) { if (lineBuffY.Array != null) { buffHeightY = Math.Min(buffHeightY * 2, (int)scaledHeight); buffHeightC = Math.Min(buffHeightC * 2, (int)Math.Ceiling(buffHeightY / subsampleRatioY)); } var tbuffY = new ArraySegment <byte>(ArrayPool <byte> .Shared.Rent(buffHeightY * strideY), 0, buffHeightY * strideY); var tbuffC = new ArraySegment <byte>(ArrayPool <byte> .Shared.Rent(buffHeightC * strideC), 0, buffHeightC * strideC); if (lineBuffY.Array != null) { fixed(byte *ptbuffY = tbuffY.Array, ptbuffC = tbuffC.Array, pcbuffY = lineBuffY.Array, pcbuffC = lineBuffC.Array) { Buffer.MemoryCopy(pcbuffY, ptbuffY, tbuffY.Array.Length, lineBuffY.Count); Buffer.MemoryCopy(pcbuffC, ptbuffC, tbuffC.Array.Length, lineBuffC.Count); } ArrayPool <byte> .Shared.Return(lineBuffY.Array); ArrayPool <byte> .Shared.Return(lineBuffC.Array); } lineBuffY = tbuffY; lineBuffC = tbuffC; } fixed(byte *pBuffY = lineBuffY.Array, pBuffC = lineBuffC.Array) { int offsY = 0, offsC = 0; if (startY == -1) { startY = prc.Y; if (startY % subsampleRatioY > 0) { startY = (int)(startY / subsampleRatioY) * (int)subsampleRatioY; } startC = (int)(startY / subsampleRatioY); } else if (nextY < buffHeightY || nextC < buffHeightC) { int minY = (int)Math.Min(nextC * subsampleRatioY, nextY); int minC = (int)(minY / subsampleRatioY); minY = minC * (int)subsampleRatioY; Buffer.MemoryCopy(pBuffY + minY * strideY, pBuffY, lineBuffY.Array.Length, (buffHeightY - minY) * strideY); Buffer.MemoryCopy(pBuffC + minC * strideC, pBuffC, lineBuffC.Array.Length, (buffHeightC - minC) * strideC); offsY = loadedY - startY - minY; offsC = (int)(loadedY / subsampleRatioY) - startC - minC; startY += minY; startC += minC; nextY -= minY; nextC -= minC; } else { startY += buffHeightY; startC += buffHeightC; } var rect = new WICRect { X = scaledCrop.X, Y = Math.Max(0, Math.Max(scaledCrop.Y + startY + offsY, loadedY)), Width = scaledCrop.Width, Height = Math.Min(buffHeightY - offsY, scaledCrop.Height - (plane == WicPlane.Luma ? prc.Y : (int)Math.Ceiling(prc.Y * subsampleRatioY))) }; var planes = new[] { new WICBitmapPlane { Format = sourceY.Format.FormatGuid, pbBuffer = (IntPtr)(pBuffY + offsY * strideY), cbStride = (uint)strideY, cbBufferSize = (uint)lineBuffY.Count }, new WICBitmapPlane { Format = sourceC.Format.FormatGuid, pbBuffer = (IntPtr)(pBuffC + offsC * strideC), cbStride = (uint)strideC, cbBufferSize = (uint)lineBuffC.Count } }; sourceTransform.CopyPixels(rect, scaledWidth, scaledHeight, sourceTransformOptions, WICPlanarOptions.WICPlanarOptionsDefault, planes, (uint)planes.Length); loadedY = rect.Y + rect.Height - scaledCrop.Y; loadedC = (int)Math.Ceiling(loadedY / subsampleRatioY); } }
public PixelSource GetPlane(WicPlane plane) => plane == WicPlane.Luma ? sourceY : sourceC;
public IWICBitmapSource GetPlane(WicPlane plane) => plane == WicPlane.Luma ? sourceY : sourceC;
unsafe public void CopyPixels(WicPlane plane, WICRect prc, uint cbStride, uint cbBufferSize, IntPtr pbBuffer) { if (prc.X < 0 || prc.Y < 0 || prc.X + prc.Width > scaledWidth || prc.Y + prc.Height > scaledHeight) { throw new ArgumentOutOfRangeException(nameof(prc), "Requested rectangle does not fall within the image bounds"); } bool load = (lineBuffY.Array == null || (plane == WicPlane.Luma && prc.Y + prc.Height > startY + buffHeightY) || (plane == WicPlane.Chroma && prc.Y + prc.Height > startC + buffHeightC)); if (load && (lineBuffY.Array == null || posY < buffHeightY / 4 || posC < buffHeightC / 4)) { if (lineBuffY.Array != null) { buffHeightY = Math.Min(buffHeightY * 2, (int)scaledHeight); buffHeightC = Math.Min(buffHeightC * 2, (int)Math.Ceiling(buffHeightY / subsampleRatioY)); } var tbuffY = new ArraySegment <byte>(ArrayPool <byte> .Shared.Rent(buffHeightY * strideY), 0, buffHeightY * strideY); var tbuffC = new ArraySegment <byte>(ArrayPool <byte> .Shared.Rent(buffHeightC * strideC), 0, buffHeightC * strideC); if (lineBuffY.Array != null) { fixed(byte *ptbuffY = tbuffY.Array, ptbuffC = tbuffC.Array, pcbuffY = lineBuffY.Array, pcbuffC = lineBuffC.Array) { Buffer.MemoryCopy(pcbuffY, ptbuffY, tbuffY.Array.Length, lineBuffY.Count); Buffer.MemoryCopy(pcbuffC, ptbuffC, tbuffC.Array.Length, lineBuffC.Count); var rect = new WICRect { X = scaledCrop.X, Y = scaledCrop.Y + startY + posY, Width = scaledCrop.Width, Height = Math.Min(buffHeightY - posY, scaledCrop.Height - (plane == WicPlane.Luma ? prc.Y : (int)Math.Ceiling(prc.Y * subsampleRatioY))) }; loadBuffer(ptbuffY + lineBuffY.Count, ptbuffC + lineBuffC.Count, rect); } load = false; ArrayPool <byte> .Shared.Return(lineBuffY.Array); ArrayPool <byte> .Shared.Return(lineBuffC.Array); } lineBuffY = tbuffY; lineBuffC = tbuffC; } fixed(byte *pBuffY = lineBuffY.Array, pBuffC = lineBuffC.Array) { if (load) { int offsY = 0, offsC = 0; if (startY == -1) { startY = prc.Y; if (startY % subsampleRatioY > 0) { startY = (int)(startY / subsampleRatioY) * (int)subsampleRatioY; } startC = (int)(startY / subsampleRatioY); posY = prc.Y - startY; posC = (int)(posY / subsampleRatioY); } else if (posY < buffHeightY || posC < buffHeightC) { int posMin = (int)Math.Min(posC * subsampleRatioY, posY); int posMins = (int)(posMin / subsampleRatioY); posMin = posMins * (int)subsampleRatioY; Buffer.MemoryCopy(pBuffY + posMin * strideY, pBuffY, lineBuffY.Array.Length, (buffHeightY - posMin) * strideY); Buffer.MemoryCopy(pBuffC + posMins * strideC, pBuffC, lineBuffC.Array.Length, (buffHeightC - posMins) * strideC); startY += posMin; startC += posMins; posY -= posMin; posC -= posMins; offsY = buffHeightY - posMin; offsC = buffHeightC - posMins; } else { startY += buffHeightY; startC += buffHeightC; posY = posC = 0; } var rect = new WICRect { X = scaledCrop.X, Y = scaledCrop.Y + startY + offsY, Width = scaledCrop.Width, Height = Math.Min(buffHeightY - offsY, scaledCrop.Height - (plane == WicPlane.Luma ? prc.Y : (int)Math.Ceiling(prc.Y * subsampleRatioY))) }; loadBuffer(pBuffY + offsY * strideY, pBuffC + offsC * strideC, rect); } if (plane == WicPlane.Luma) { for (int y = 0; y < prc.Height; y++) { Buffer.MemoryCopy(pBuffY + posY * strideY + y * strideY, (byte *)pbBuffer + y * cbStride, cbBufferSize, cbStride); } posY += prc.Height; } else { for (int y = 0; y < prc.Height; y++) { Buffer.MemoryCopy(pBuffC + posC * strideC + y * strideC, (byte *)pbBuffer + y * cbStride, cbBufferSize, cbStride); } posC += prc.Height; } } }
public IWICBitmapSource GetPlane(WicPlane plane) { return(plane == WicPlane.Luma ? sourceY : sourceC); }
unsafe public void CopyPixels(WicPlane plane, WICRect prc, uint cbStride, uint cbBufferSize, IntPtr pbBuffer) { var load = (lineBuffY == null || (plane == WicPlane.Luma && prc.Y + prc.Height > startY + buffHeightY) || (plane == WicPlane.Chroma && prc.Y + prc.Height > startC + buffHeightC)); if (load && (lineBuffY == null || posY < buffHeightY / 4 || posC < buffHeightC / 4)) { if (lineBuffY != null) { buffHeightY *= 2; buffHeightC *= 2; } var tbuffY = new byte[strideY * buffHeightY]; var tbuffC = new byte[strideC * buffHeightC]; if (lineBuffY != null) { fixed(byte *ptbuffY = tbuffY, ptbuffC = tbuffC, pcbuffY = lineBuffY, pcbuffC = lineBuffC) { Buffer.MemoryCopy(pcbuffY, ptbuffY, tbuffY.Length, lineBuffY.Length); Buffer.MemoryCopy(pcbuffC, ptbuffC, tbuffC.Length, lineBuffC.Length); var rect = new WICRect { X = scaledCrop.X, Y = scaledCrop.Y + startY + posY, Width = scaledCrop.Width, Height = Math.Min((int)buffHeightY - posY, scaledCrop.Height - prc.Y) }; loadBuffer(ptbuffY + (buffHeightY / 2) * strideY, ptbuffC + (buffHeightC / 2) * strideC, rect); } load = false; } lineBuffY = tbuffY; lineBuffC = tbuffC; } fixed(byte *pBuffY = lineBuffY, pBuffC = lineBuffC) { if (load) { int offsY = 0, offsC = 0; if (startY == -1) { startY = prc.Y; if (startY % subsampleRatioY > 0) { startY = (int)(startY / subsampleRatioY) * (int)subsampleRatioY; } startC = (int)(startY / subsampleRatioY); posY = prc.Y - startY; posC = (int)(posY / subsampleRatioY); } else if (posY < buffHeightY || posC < buffHeightC) { int posMin = (int)Math.Min(posC * subsampleRatioY, posY); int posMins = (int)(posMin / subsampleRatioY); posMin = posMins * (int)subsampleRatioY; Buffer.MemoryCopy(pBuffY + posMin * strideY, pBuffY, lineBuffY.Length, (buffHeightY - posMin) * strideY); Buffer.MemoryCopy(pBuffC + posMins * strideC, pBuffC, lineBuffC.Length, (buffHeightC - posMins) * strideC); startY += posMin; startC += posMins; posY -= posMin; posC -= posMins; offsY = (int)buffHeightY - posMin; offsC = (int)buffHeightC - posMins; } else { startY += (int)buffHeightY; startC += (int)buffHeightC; posY = posC = 0; } var rect = new WICRect { X = scaledCrop.X, Y = scaledCrop.Y + startY + posY, Width = scaledCrop.Width, Height = Math.Min((int)buffHeightY - posY, scaledCrop.Height - prc.Y) }; loadBuffer(pBuffY + offsY * strideY, pBuffC + offsC * strideC, rect); } if (plane == WicPlane.Luma) { Buffer.MemoryCopy(pBuffY + (posY * strideY), (void *)pbBuffer, cbBufferSize, cbBufferSize); posY += prc.Height; } else { Buffer.MemoryCopy(pBuffC + (posC * strideC), (void *)pbBuffer, cbBufferSize, cbBufferSize); posC += prc.Height; } } }