public void Dispose() { if (Target != null) { Target.Dispose(); Target = null; } }
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 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 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> /// 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; }
/// <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.RGBA: 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.ARGB: 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; }