/// <summary> /// Resizes planar image /// </summary> /// <param name="newSize"></param> /// <returns></returns> public PlanarImage Resize(Size newSize) { PlanarImage result = new PlanarImage(newSize.Width, newSize.Height, this.PixelType); ConverterResizer.Apply(this, result); return(result); }
/// <summary> /// Performs both conversion and resize in a single operation /// </summary> /// <param name="newPixelType"></param> /// <param name="newSize"></param> /// <returns></returns> public PlanarImage ConvertAndResize(PixelAlignmentType newPixelType, Size newSize) { PlanarImage result = new PlanarImage(newSize.Width, newSize.Height, newPixelType); ConverterResizer.Apply(this, result); return(result); }
public static PlanarImage FromBitmap(Bitmap source, PixelAlignmentType format, ColorSpace colorspace = ColorSpace.DEFAULT) { IntPtr context = SwScale.sws_getContext(source.Width, source.Height, m_rgbMapper[source.PixelFormat], source.Width, source.Height, m_pixelTypeMapper[format], SwScale.ConvertionFlags.SWS_BICUBIC, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero); int *pCoef = SwScale.sws_getCoefficients(colorspace); int *inv_table; int *table; int srcRange, dstRange, brightness, contrast, saturation; int result = SwScale.sws_getColorspaceDetails(context, out inv_table, out srcRange, out table, out dstRange, out brightness, out contrast, out saturation); if (result != -1) { result = SwScale.sws_setColorspaceDetails(context, pCoef, srcRange, table, dstRange, brightness, contrast, saturation); } PlanarImage yuv = new PlanarImage(source.Width, source.Height, format); BitmapData data = source.LockBits(new Rectangle(0, 0, source.Width, source.Height), ImageLockMode.ReadOnly, source.PixelFormat); unsafe { pInput[0] = (byte *)data.Scan0.ToPointer(); result = SwScale.sws_scale(context, pInput, new int[] { data.Stride, 0, 0, 0 }, 0, source.Height, yuv.PixelDataPointer, yuv.Pitches); if (result != yuv.Height) { throw new InvalidOperationException(); } } source.UnlockBits(data); SwScale.sws_freeContext(context); return(yuv); }
/// <summary> /// Converts planar image to another pixel alignment type /// </summary> /// <param name="newPixelType"></param> /// <returns></returns> public PlanarImage Convert(PixelAlignmentType newPixelType) { PlanarImage result = new PlanarImage(this.Width, this.Height, newPixelType); ConverterResizer.Apply(this, result); return(result); }
/// <summary> /// Loads PlanarImage properties from provided stream /// </summary> /// <param name="stream"></param> /// <returns></returns> public static PlanarImage Load(Stream stream) { BinaryFormatter bf = new BinaryFormatter(); PlanarImage yuv = (PlanarImage)bf.Deserialize(stream); return(yuv); }
/// <summary> /// /// </summary> /// <param name="fileName"></param> /// <returns></returns> public static PlanarImage Load(string fileName) { FileStream fs = File.OpenRead(fileName); PlanarImage image = Load(fs); fs.Close(); return(image); }
public PlanarImage DoTheWork(PlanarImage source) { PlanarImage target = new PlanarImage(m_targetSize.Width, m_targetSize.Height, m_targetType); int result = SwScale.sws_scale(m_context, source.PixelDataPointer, source.Pitches, 0, source.Height, target.PixelDataPointer, target.Pitches); if (result != target.Height) { throw new InvalidOperationException(); } return target; }
public PlanarImage DoTheWork(PlanarImage source) { PlanarImage target = new PlanarImage(m_targetSize.Width, m_targetSize.Height, m_targetType); int result = SwScale.sws_scale(m_context, source.PixelDataPointer, source.Pitches, 0, source.Height, target.PixelDataPointer, target.Pitches); if (result != target.Height) { throw new InvalidOperationException(); } return(target); }
public static void Apply(PlanarImage source, PlanarImage target) { IntPtr context = SwScale.sws_getContext(source.Width, source.Height, m_pixelTypeMapper[source.PixelType], target.Width, target.Height, m_pixelTypeMapper[target.PixelType], SwScale.ConvertionFlags.SWS_BICUBIC, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero); int result = SwScale.sws_scale(context, source.PixelDataPointer, source.Pitches, 0, source.Height, target.PixelDataPointer, target.Pitches); if (result != target.Height) { throw new InvalidOperationException(); } SwScale.sws_freeContext(context); }
public static Bitmap ToBitmap(PlanarImage source, PixelFormat format, ColorSpace colorspace = ColorSpace.DEFAULT) { IntPtr context = SwScale.sws_getContext(source.Width, source.Height, m_pixelTypeMapper[source.PixelType], source.Width, source.Height, m_rgbMapper[format], SwScale.ConvertionFlags.SWS_BICUBIC, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero); int *pCoef = SwScale.sws_getCoefficients(colorspace); int *inv_table; int *table; int srcRange, dstRange, brightness, contrast, saturation; int result = SwScale.sws_getColorspaceDetails(context, out inv_table, out srcRange, out table, out dstRange, out brightness, out contrast, out saturation); if (result != -1) { result = SwScale.sws_setColorspaceDetails(context, pCoef, srcRange, pCoef, dstRange, brightness, contrast, saturation); } Bitmap bmp = new Bitmap(source.Width, source.Height, format); BitmapData data = bmp.LockBits(new Rectangle(0, 0, source.Width, source.Height), ImageLockMode.ReadWrite, format); unsafe { pInput[0] = (byte *)data.Scan0.ToPointer(); result = SwScale.sws_scale(context, source.PixelDataPointer, source.Pitches, 0, source.Height, pInput, new int[] { data.Stride, 0, 0, 0 }); if (result != source.Height) { throw new InvalidOperationException(); } } bmp.UnlockBits(data); if (bmp.Palette != null && bmp.Palette.Entries != null && bmp.Palette.Entries.Length > 0) { ColorPalette cp = bmp.Palette; for (int i = 0; i < cp.Entries.Length; i++) { cp.Entries[i] = Color.FromArgb(i, i, i); } bmp.Palette = cp; } SwScale.sws_freeContext(context); return(bmp); }
public static PlanarImage FromBitmap(Bitmap source, PixelAlignmentType format, ColorSpace colorspace = ColorSpace.DEFAULT) { IntPtr context = SwScale.sws_getContext(source.Width, source.Height, m_rgbMapper[source.PixelFormat], source.Width, source.Height, m_pixelTypeMapper[format], SwScale.ConvertionFlags.SWS_BICUBIC, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero); int* pCoef = SwScale.sws_getCoefficients(colorspace); int* inv_table; int* table; int srcRange, dstRange, brightness, contrast, saturation; int result = SwScale.sws_getColorspaceDetails(context, out inv_table, out srcRange, out table, out dstRange, out brightness, out contrast, out saturation); if (result != -1) { result = SwScale.sws_setColorspaceDetails(context, pCoef, srcRange, table, dstRange, brightness, contrast, saturation); } PlanarImage yuv = new PlanarImage(source.Width, source.Height, format); BitmapData data = source.LockBits(new Rectangle(0, 0, source.Width, source.Height), ImageLockMode.ReadOnly, source.PixelFormat); unsafe { pInput[0] = (byte*)data.Scan0.ToPointer(); result = SwScale.sws_scale(context, pInput, new int[] { data.Stride, 0, 0, 0 }, 0, source.Height, yuv.PixelDataPointer, yuv.Pitches); if (result != yuv.Height) { throw new InvalidOperationException(); } } source.UnlockBits(data); SwScale.sws_freeContext(context); return yuv; }
/// <summary> /// Performs both conversion and resize in a single operation /// </summary> /// <param name="newPixelType"></param> /// <param name="newSize"></param> /// <returns></returns> public PlanarImage ConvertAndResize(PixelAlignmentType newPixelType, Size newSize) { PlanarImage result = new PlanarImage(newSize.Width, newSize.Height, newPixelType); ConverterResizer.Apply(this, result); return result; }
/// <summary> /// Resizes planar image /// </summary> /// <param name="newSize"></param> /// <returns></returns> public PlanarImage Resize(Size newSize) { PlanarImage result = new PlanarImage(newSize.Width, newSize.Height, this.PixelType); ConverterResizer.Apply(this, result); return result; }
/// <summary> /// Converts planar image to another pixel alignment type /// </summary> /// <param name="newPixelType"></param> /// <returns></returns> public PlanarImage Convert(PixelAlignmentType newPixelType) { PlanarImage result = new PlanarImage(this.Width, this.Height, newPixelType); ConverterResizer.Apply(this, result); return result; }
public static PlanarImage Crop(PlanarImage source, Rectangle cropArea) { PlanarImage result = new PlanarImage(cropArea.Width, cropArea.Height, source.PixelType); switch (source.PixelType) { case PixelAlignmentType.I420: case PixelAlignmentType.YV12: IntPtr dest = result.Planes[0]; IntPtr src = source.Planes[0] + cropArea.Y * source.Width + cropArea.X; for (int i = 0; i < cropArea.Height; i++) { RtlMoveMemory(dest, src, cropArea.Width); dest += cropArea.Width; src += source.Width; } dest = result.Planes[1]; src = source.Planes[1] + cropArea.Y / 2 * source.Width / 2 + cropArea.X / 2; for (int i = 0; i < cropArea.Height / 2; i++) { RtlMoveMemory(dest, src, cropArea.Width / 2); dest += cropArea.Width / 2; src += source.Width / 2; } dest = result.Planes[2]; src = source.Planes[2] + cropArea.Y / 2 * source.Width / 2 + cropArea.X / 2; for (int i = 0; i < cropArea.Height / 2; i++) { RtlMoveMemory(dest, src, cropArea.Width / 2); dest += cropArea.Width / 2; src += source.Width / 2; } break; case PixelAlignmentType.NV12: case PixelAlignmentType.NV21: dest = result.Planes[0]; src = source.Planes[0] + cropArea.Y * source.Width + cropArea.X; for (int i = 0; i < cropArea.Height; i++) { RtlMoveMemory(dest, src, cropArea.Width); dest += cropArea.Width; src += source.Width; } dest = result.Planes[1]; src = source.Planes[1] + cropArea.Y * source.Width / 2 + cropArea.X; for (int i = 0; i < cropArea.Height / 2; i++) { RtlMoveMemory(dest, src, cropArea.Width); dest += cropArea.Width; src += source.Width; } break; case PixelAlignmentType.YUY2: case PixelAlignmentType.UYVY: dest = result.Planes[0]; src = source.Planes[0] + cropArea.Y * source.Pitches[0] + cropArea.X * 2; for (int i = 0; i < cropArea.Height; i++) { RtlMoveMemory(dest, src, source.Pitches[0]); dest += result.Pitches[0]; src += source.Pitches[0]; } break; case PixelAlignmentType.YUV: dest = result.Planes[0]; src = source.Planes[0] + cropArea.Y * source.Width + cropArea.X; for (int i = 0; i < cropArea.Height; i++) { RtlMoveMemory(dest, src, cropArea.Width); dest += cropArea.Width; src += source.Width; } dest = result.Planes[1]; src = source.Planes[1] + cropArea.Y * source.Width + cropArea.X; for (int i = 0; i < cropArea.Height; i++) { RtlMoveMemory(dest, src, cropArea.Width); dest += cropArea.Width; src += source.Width; } dest = result.Planes[2]; src = source.Planes[2] + cropArea.Y * source.Width + cropArea.X; for (int i = 0; i < cropArea.Height; i++) { RtlMoveMemory(dest, src, cropArea.Width); dest += cropArea.Width; src += source.Width; } break; case PixelAlignmentType.Y800: dest = result.Planes[0]; src = source.Planes[0] + cropArea.Y * source.Width + cropArea.X; for (int i = 0; i < cropArea.Height; i++) { RtlMoveMemory(dest, src, cropArea.Width); dest += cropArea.Width; src += source.Width; } break; case PixelAlignmentType.Y411: dest = result.Planes[0]; src = source.Planes[0] + cropArea.Y * source.Pitches[0] + cropArea.X; for (int i = 0; i < cropArea.Height; i++) { RtlMoveMemory(dest, src, result.Pitches[0]); dest += result.Pitches[0]; src += source.Pitches[0]; } dest = result.Planes[1]; src = source.Planes[1] + cropArea.Y * source.Pitches[1] + cropArea.X / 4; for (int i = 0; i < cropArea.Height; i++) { RtlMoveMemory(dest, src, result.Pitches[1]); dest += result.Pitches[1]; src += source.Pitches[1]; } dest = result.Planes[2]; src = source.Planes[2] + cropArea.Y * source.Pitches[2] + cropArea.X / 4; for (int i = 0; i < cropArea.Height; i++) { RtlMoveMemory(dest, src, result.Pitches[2]); dest += result.Pitches[2]; src += source.Pitches[2]; } break; case PixelAlignmentType.Y410: dest = result.Planes[0]; src = source.Planes[0] + cropArea.Y * source.Width + cropArea.X; for (int i = 0; i < cropArea.Height; i++) { RtlMoveMemory(dest, src, cropArea.Width); dest += cropArea.Width; src += source.Width; } dest = result.Planes[1]; src = source.Planes[1] + cropArea.Y / 4 * source.Width / 4 + cropArea.X / 4; for (int i = 0; i < cropArea.Height / 4; i++) { RtlMoveMemory(dest, src, cropArea.Width / 4); dest += cropArea.Width / 4; src += source.Width / 4; } dest = result.Planes[2]; src = source.Planes[2] + cropArea.Y / 4 * source.Width / 4 + cropArea.X / 4; for (int i = 0; i < cropArea.Height / 4; i++) { RtlMoveMemory(dest, src, cropArea.Width / 4); dest += cropArea.Width / 4; src += source.Width / 4; } break; case PixelAlignmentType.Y16: dest = result.Planes[0]; src = source.Planes[0] + cropArea.Y * source.Pitches[0] + cropArea.X; for (int i = 0; i < cropArea.Height; i++) { RtlMoveMemory(dest, src, cropArea.Width * 2); dest += cropArea.Width * 2; src += source.Width * 2; } break; case PixelAlignmentType.RGB24: dest = result.Planes[0]; src = source.Planes[0] + cropArea.Y * source.Pitches[0] + cropArea.X; for (int i = 0; i < cropArea.Height; i++) { RtlMoveMemory(dest, src, cropArea.Width * 3); dest += cropArea.Width * 3; src += source.Width * 3; } break; case PixelAlignmentType.BGRA: dest = result.Planes[0]; src = source.Planes[0] + cropArea.Y * source.Pitches[0] + cropArea.X; for (int i = 0; i < cropArea.Height; i++) { RtlMoveMemory(dest, src, cropArea.Width * 4); dest += cropArea.Width * 4; src += source.Width * 4; } break; case PixelAlignmentType.ABGR: dest = result.Planes[0]; src = source.Planes[0] + cropArea.Y * source.Pitches[0] + cropArea.X; for (int i = 0; i < cropArea.Height; i++) { RtlMoveMemory(dest, src, cropArea.Width * 4); dest += cropArea.Width * 4; src += source.Width * 4; } break; default: throw new InvalidOperationException("Unknown pixel alignment type " + source.PixelType); } return result; }
public void Render(IntPtr yBuffer, IntPtr uBuffer, IntPtr vBuffer) { PlanarImage source = null; switch (this.pixelType) { case PixelAlignmentType.YV12: case PixelAlignmentType.I420: source = new PlanarImage(this.width, this.height, this.pixelType, new IntPtr[] { yBuffer, uBuffer, vBuffer }); break; case PixelAlignmentType.NV12: source = new PlanarImage(this.width, this.height, this.pixelType, new IntPtr[] { yBuffer, uBuffer }); break; // 打包格式 case PixelAlignmentType.YUY2: case PixelAlignmentType.UYVY: case PixelAlignmentType.BGRA: case PixelAlignmentType.ABGR: case PixelAlignmentType.RGB24: source = new PlanarImage(this.width, this.height, this.pixelType, yBuffer, this.frameSize); break; default: return; } PlanarImage image = this.converter.DoTheWork(source); this.DisplayImage(image); }
public void Render(IntPtr buffer) { PlanarImage source = new PlanarImage(this.width, this.height, this.pixelType, buffer, this.frameSize); PlanarImage image = this.converter.DoTheWork(source); this.DisplayImage(image); }
public static PlanarImage Crop(PlanarImage source, Rectangle cropArea) { PlanarImage result = new PlanarImage(cropArea.Width, cropArea.Height, source.PixelType); switch (source.PixelType) { case PixelAlignmentType.I420: case PixelAlignmentType.YV12: IntPtr dest = result.Planes[0]; IntPtr src = source.Planes[0] + cropArea.Y * source.Width + cropArea.X; for (int i = 0; i < cropArea.Height; i++) { RtlMoveMemory(dest, src, cropArea.Width); dest += cropArea.Width; src += source.Width; } dest = result.Planes[1]; src = source.Planes[1] + cropArea.Y / 2 * source.Width / 2 + cropArea.X / 2; for (int i = 0; i < cropArea.Height / 2; i++) { RtlMoveMemory(dest, src, cropArea.Width / 2); dest += cropArea.Width / 2; src += source.Width / 2; } dest = result.Planes[2]; src = source.Planes[2] + cropArea.Y / 2 * source.Width / 2 + cropArea.X / 2; for (int i = 0; i < cropArea.Height / 2; i++) { RtlMoveMemory(dest, src, cropArea.Width / 2); dest += cropArea.Width / 2; src += source.Width / 2; } break; case PixelAlignmentType.NV12: case PixelAlignmentType.NV21: dest = result.Planes[0]; src = source.Planes[0] + cropArea.Y * source.Width + cropArea.X; for (int i = 0; i < cropArea.Height; i++) { RtlMoveMemory(dest, src, cropArea.Width); dest += cropArea.Width; src += source.Width; } dest = result.Planes[1]; src = source.Planes[1] + cropArea.Y * source.Width / 2 + cropArea.X; for (int i = 0; i < cropArea.Height / 2; i++) { RtlMoveMemory(dest, src, cropArea.Width); dest += cropArea.Width; src += source.Width; } break; case PixelAlignmentType.YUY2: case PixelAlignmentType.UYVY: dest = result.Planes[0]; src = source.Planes[0] + cropArea.Y * source.Pitches[0] + cropArea.X * 2; for (int i = 0; i < cropArea.Height; i++) { RtlMoveMemory(dest, src, source.Pitches[0]); dest += result.Pitches[0]; src += source.Pitches[0]; } break; case PixelAlignmentType.YUV: dest = result.Planes[0]; src = source.Planes[0] + cropArea.Y * source.Width + cropArea.X; for (int i = 0; i < cropArea.Height; i++) { RtlMoveMemory(dest, src, cropArea.Width); dest += cropArea.Width; src += source.Width; } dest = result.Planes[1]; src = source.Planes[1] + cropArea.Y * source.Width + cropArea.X; for (int i = 0; i < cropArea.Height; i++) { RtlMoveMemory(dest, src, cropArea.Width); dest += cropArea.Width; src += source.Width; } dest = result.Planes[2]; src = source.Planes[2] + cropArea.Y * source.Width + cropArea.X; for (int i = 0; i < cropArea.Height; i++) { RtlMoveMemory(dest, src, cropArea.Width); dest += cropArea.Width; src += source.Width; } break; case PixelAlignmentType.Y800: dest = result.Planes[0]; src = source.Planes[0] + cropArea.Y * source.Width + cropArea.X; for (int i = 0; i < cropArea.Height; i++) { RtlMoveMemory(dest, src, cropArea.Width); dest += cropArea.Width; src += source.Width; } break; case PixelAlignmentType.Y411: dest = result.Planes[0]; src = source.Planes[0] + cropArea.Y * source.Pitches[0] + cropArea.X; for (int i = 0; i < cropArea.Height; i++) { RtlMoveMemory(dest, src, result.Pitches[0]); dest += result.Pitches[0]; src += source.Pitches[0]; } dest = result.Planes[1]; src = source.Planes[1] + cropArea.Y * source.Pitches[1] + cropArea.X / 4; for (int i = 0; i < cropArea.Height; i++) { RtlMoveMemory(dest, src, result.Pitches[1]); dest += result.Pitches[1]; src += source.Pitches[1]; } dest = result.Planes[2]; src = source.Planes[2] + cropArea.Y * source.Pitches[2] + cropArea.X / 4; for (int i = 0; i < cropArea.Height; i++) { RtlMoveMemory(dest, src, result.Pitches[2]); dest += result.Pitches[2]; src += source.Pitches[2]; } break; case PixelAlignmentType.Y410: dest = result.Planes[0]; src = source.Planes[0] + cropArea.Y * source.Width + cropArea.X; for (int i = 0; i < cropArea.Height; i++) { RtlMoveMemory(dest, src, cropArea.Width); dest += cropArea.Width; src += source.Width; } dest = result.Planes[1]; src = source.Planes[1] + cropArea.Y / 4 * source.Width / 4 + cropArea.X / 4; for (int i = 0; i < cropArea.Height / 4; i++) { RtlMoveMemory(dest, src, cropArea.Width / 4); dest += cropArea.Width / 4; src += source.Width / 4; } dest = result.Planes[2]; src = source.Planes[2] + cropArea.Y / 4 * source.Width / 4 + cropArea.X / 4; for (int i = 0; i < cropArea.Height / 4; i++) { RtlMoveMemory(dest, src, cropArea.Width / 4); dest += cropArea.Width / 4; src += source.Width / 4; } break; case PixelAlignmentType.Y16: dest = result.Planes[0]; src = source.Planes[0] + cropArea.Y * source.Pitches[0] + cropArea.X; for (int i = 0; i < cropArea.Height; i++) { RtlMoveMemory(dest, src, cropArea.Width * 2); dest += cropArea.Width * 2; src += source.Width * 2; } break; case PixelAlignmentType.RGB24: dest = result.Planes[0]; src = source.Planes[0] + cropArea.Y * source.Pitches[0] + cropArea.X; for (int i = 0; i < cropArea.Height; i++) { RtlMoveMemory(dest, src, cropArea.Width * 3); dest += cropArea.Width * 3; src += source.Width * 3; } break; case PixelAlignmentType.BGRA: dest = result.Planes[0]; src = source.Planes[0] + cropArea.Y * source.Pitches[0] + cropArea.X; for (int i = 0; i < cropArea.Height; i++) { RtlMoveMemory(dest, src, cropArea.Width * 4); dest += cropArea.Width * 4; src += source.Width * 4; } break; case PixelAlignmentType.ABGR: dest = result.Planes[0]; src = source.Planes[0] + cropArea.Y * source.Pitches[0] + cropArea.X; for (int i = 0; i < cropArea.Height; i++) { RtlMoveMemory(dest, src, cropArea.Width * 4); dest += cropArea.Width * 4; src += source.Width * 4; } break; default: throw new InvalidOperationException("Unknown pixel alignment type " + source.PixelType); } return(result); }
public static Bitmap ToBitmap(PlanarImage source, PixelFormat format, ColorSpace colorspace = ColorSpace.DEFAULT) { IntPtr context = SwScale.sws_getContext(source.Width, source.Height, m_pixelTypeMapper[source.PixelType], source.Width, source.Height, m_rgbMapper[format], SwScale.ConvertionFlags.SWS_BICUBIC, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero); int* pCoef = SwScale.sws_getCoefficients(colorspace); int* inv_table; int* table; int srcRange, dstRange, brightness, contrast, saturation; int result = SwScale.sws_getColorspaceDetails(context, out inv_table, out srcRange, out table, out dstRange, out brightness, out contrast, out saturation); if (result != -1) { result = SwScale.sws_setColorspaceDetails(context, pCoef, srcRange, pCoef, dstRange, brightness, contrast, saturation); } Bitmap bmp = new Bitmap(source.Width, source.Height, format); BitmapData data = bmp.LockBits(new Rectangle(0, 0, source.Width, source.Height), ImageLockMode.ReadWrite, format); unsafe { pInput[0] = (byte*)data.Scan0.ToPointer(); result = SwScale.sws_scale(context, source.PixelDataPointer, source.Pitches, 0, source.Height, pInput, new int[] { data.Stride, 0, 0, 0 }); if (result != source.Height) { throw new InvalidOperationException(); } } bmp.UnlockBits(data); if (bmp.Palette != null && bmp.Palette.Entries != null && bmp.Palette.Entries.Length > 0) { ColorPalette cp = bmp.Palette; for (int i = 0; i < cp.Entries.Length; i++) { cp.Entries[i] = Color.FromArgb(i, i, i); } bmp.Palette = cp; } SwScale.sws_freeContext(context); return bmp; }
private void DisplayImage(PlanarImage image) { if (!this.imageSource.Dispatcher.CheckAccess()) { this.imageSource.Dispatcher.Invoke((Action)(() => this.DisplayImage(image))); return; } this.imageSource.Lock(); Interop.Memcpy(this.imageSource.BackBuffer, image.Planes[0], image.PlaneSizes[0]); this.imageSource.AddDirtyRect(this.imageSourceRect); this.imageSource.Unlock(); }