public int GetHighColor(int bits, YUVPlanes plane) { if (!LimitedRange) { return((1 << bits) - 1); } var sdr = plane == YUVPlanes.PLANAR_U || plane == YUVPlanes.PLANAR_V ? 240 : 235; return(sdr << (bits - 8)); }
unsafe private void ProcessPlane(VideoFrame src, VideoFrame dst, YUVPlanes plane) { byte *SrcPtr = (byte *)src.GetReadPtr(plane); byte *DstPtr = (byte *)dst.GetWritePtr(plane); int SrcPitch = src.GetPitch(plane); int DstPitch = dst.GetPitch(plane); Step1(SrcPtr, DstPtr, SrcPitch, DstPitch); Step2(DstPtr, DstPitch); Step3(DstPtr, DstPitch); }
public static string GetKey(this YUVPlanes plane) { switch (plane) { case YUVPlanes.PLANAR_Y: return("y"); case YUVPlanes.PLANAR_V: return("v"); case YUVPlanes.PLANAR_U: return("u"); default: return(null); } }
public static void CopyPlane(VideoFrame from, VideoFrame to, YUVPlanes plane = default(YUVPlanes)) { if (from.GetPitch(plane) == to.GetPitch(plane)) { CopyMemory(to.GetWritePtr(plane), from.GetReadPtr(plane), from.GetHeight(plane) * from.GetRowSize(plane)); } else { var src = from.GetReadPtr(); var dest = to.GetWritePtr(); for (var y = 0; y < from.GetHeight(plane); y++, src += from.GetPitch(plane), dest += to.GetPitch(plane)) { CopyMemory(dest, src, from.GetRowSize(plane)); } } }
private ColorMap GetTransitionMap(int[] sampleHist, int[] referenceHist, int n, YUVPlanes plane) { var map = new ColorMap(sampleBits, n, Intensity < 1 ? 1 : Dither); var highRefColor = GetHighColor(referenceBits, plane); for (int newColor = GetLowColor(referenceBits), oldColor = -1, restPixels = 0; newColor <= highRefColor; newColor++) { var refCount = referenceHist[newColor]; //var excludeReference = (double) refCount / int.MaxValue < Exclude; while (refCount > 0) { var add = Math.Min(restPixels, refCount); if (add > 0) { var exclude = (((double)add) / int.MaxValue) < Exclude; if (!exclude) { var weight = add / (double)sampleHist[oldColor]; map.Add(oldColor, newColor, weight); } refCount -= add; restPixels -= add; } else { restPixels = sampleHist[++oldColor]; } } } return(map); }
private int[] GetHistogram(IEnumerable <VideoFrame> frames, VideoFrame maskFrame, int pixelSize, int channel, YUVPlanes plane, ColorSpaces pixelType, int bits, bool limitedRange) { var hist = new int[1 << bits]; var chroma = plane == YUVPlanes.PLANAR_U || plane == YUVPlanes.PLANAR_V; var widthMult = chroma ? pixelType.GetWidthSubsample() : 1; var heightMult = chroma ? pixelType.GetHeightSubsample() : 1; var maskPitch = maskFrame?.GetPitch() * heightMult ?? 0; var maskPtr = maskFrame?.GetReadPtr() + channel ?? IntPtr.Zero; foreach (var frame in frames) { NativeUtils.FillHistogram(hist, frame.GetRowSize(plane), frame.GetHeight(plane), channel, frame.GetReadPtr(plane), frame.GetPitch(plane), pixelSize, maskPtr, maskPitch, widthMult); } if (limitedRange) { var min = GetLowColor(bits); for (var color = 0; color < min; color++) { hist[min] += hist[color]; hist[color] = 0; } var max = GetHighColor(bits, plane); for (var color = max + 1; color < 1 << bits; color++) { hist[max] += hist[color]; hist[color] = 0; } } return(GetUniHistogram(hist)); }
private ColorMap GetTransitionMap(int[] sampleHist, int[] referenceHist, int n, YUVPlanes plane) { var map = new ColorMap(sampleBits, n, Dither); var highRefColor = GetHighColor(referenceBits, plane); for (int newColor = GetLowColor(referenceBits), oldColor = -1, lastOldColor = -1, lastNewColor = GetLowColor(referenceBits) - 1, restPixels = 0; newColor <= highRefColor; newColor++) { void MissedColors(double newColorLimit, double oldColorLimit) { var step = (newColorLimit - lastNewColor - 1) / (oldColorLimit - lastOldColor); for (var tempColor = lastOldColor + 1; tempColor < oldColorLimit; tempColor++) { var actualColor = lastNewColor + step * (tempColor - lastOldColor); var intergerColor = Math.Truncate(actualColor); var val = 1 - (actualColor - intergerColor); if (tempColor == highRefColor) { val = 1; } map.Add(tempColor, (int)intergerColor, val); if (val <= 1 - double.Epsilon) { map.Add(tempColor, (int)intergerColor + 1, 1 - val); } } } var refCount = referenceHist[newColor]; var notEmpty = refCount > 0; while (refCount > 0) { var add = Math.Min(restPixels, refCount); if (add > 0) { map.Add(oldColor, newColor, add / (double)sampleHist[oldColor]); refCount -= add; restPixels -= add; lastOldColor = oldColor; } else { restPixels = sampleHist[++oldColor]; if (restPixels != 0 && oldColor - lastOldColor > 1) { MissedColors(newColor, oldColor); } } } if (notEmpty) { lastNewColor = newColor; } if (newColor == highRefColor) { MissedColors(highRefColor + 1, 1 << sampleBits); } } return(map); }
public OverlayContext(OverlayRender render, YUVPlanes plane) { Plane = plane; Mode = render.Mode; Static = render.Invert ? new StaticContext(render.Overlay, render.Source, render.OverlayMask, render.SourceMask, plane) : new StaticContext(render.Source, render.Overlay, render.SourceMask, render.OverlayMask, plane); Source = Static.Source.Dynamic(); Overlay = Static.Overlay.Dynamic(); SourceInfo = Static.Source.GetVideoInfo(); OverlayInfo = Static.Overlay.GetVideoInfo(); TargetInfo = render.GetVideoInfo(); SourceMask = PrepareMask(Static.SourceMask, render.Source.GetVideoInfo()); OverlayMask = PrepareMask(Static.OverlayMask, render.Overlay.GetVideoInfo()); disposables.Add(render.Source); disposables.Add(render.Overlay); disposables.Add(render.SourceMask); disposables.Add(render.OverlayMask); disposables.Add(Static.Source); disposables.Add(Static.Overlay); disposables.Add(Static.SourceMask); disposables.Add(Static.OverlayMask); if (plane.IsChroma()) { TargetInfo = TargetInfo.Chroma; } DefaultColor = Plane.IsChroma() ? 0x808080 : TargetInfo.Info.IsRGB() ? 0 : 0x008080; BlankColor = render.BlankColor >= 0 ? render.BlankColor : TargetInfo.Info.IsRGB() ? 0 : 0x008080; if (Plane == YUVPlanes.PLANAR_U) { BlankColor <<= 8; } else if (Plane == YUVPlanes.PLANAR_V) { BlankColor <<= 16; } BlankColor &= 0xFFFFFF; dynamic PrepareMask(Clip mask, ExtraVideoInfo target) { if (mask != null) { if (!target.Info.IsRGB() && mask.IsRealPlanar()) { mask = mask.Dynamic().ExtractY(); } if (plane.IsChroma() && !target.ColorSpace.WithoutSubSample()) { mask = mask.Dynamic().BilinearResize(target.Chroma.Size); } disposables.Add(mask); } return(mask?.Dynamic()); } int Round(double val) => (int)Math.Round(val); }
Clip ExtractPlane(Clip clip, YUVPlanes plane) { return(plane == default ? clip : clip.Dynamic().Invoke("Extract" + plane.GetLetter())); }
public StaticContext(Clip source, Clip overlay, Clip sourceMask, Clip overlayMask, YUVPlanes plane) { Source = ExtractPlane(source, plane); Overlay = ExtractPlane(overlay, plane); SourceMask = sourceMask; OverlayMask = overlayMask; }
public static Bitmap ToBitmap(this VideoFrame frame, PixelFormat pixelFormat, YUVPlanes plane = default(YUVPlanes)) { Bitmap bmp; switch (pixelFormat) { case PixelFormat.Format8bppIndexed: bmp = new Bitmap(frame.GetRowSize(plane), frame.GetHeight(plane), frame.GetPitch(plane), pixelFormat, frame.GetReadPtr(plane)); var palette = bmp.Palette; unchecked { for (var i = 0; i < 256; i++) { palette.Entries[i] = Color.FromArgb(i, i, i); } } bmp.Palette = palette; break; case PixelFormat.Format24bppRgb: bmp = new Bitmap(frame.GetRowSize() / 3, frame.GetHeight(), frame.GetPitch(), pixelFormat, frame.GetReadPtr()); bmp.RotateFlip(RotateFlipType.Rotate180FlipX); break; default: throw new NotImplementedException(); } return(bmp); }
public static string GetLetter(this YUVPlanes plane) { return(plane.ToString().Last().ToString()); }
public static bool IsChroma(this YUVPlanes plane) { return(plane == YUVPlanes.PLANAR_U || plane == YUVPlanes.PLANAR_V); }
public static bool IsLuma(this YUVPlanes plane) { return(plane != YUVPlanes.PLANAR_U && plane != YUVPlanes.PLANAR_V); }
private static int[] GetHistogram(VideoFrame frame, VideoFrame maskFrame, int pixelSize, int channel, YUVPlanes plane) { var hist = new int[256]; unsafe { var data = (byte *)frame.GetReadPtr(plane) + channel; var mask = (byte *)(maskFrame?.GetReadPtr(plane) ?? IntPtr.Zero) + channel; for (var y = 0; y < frame.GetHeight(plane); y++, data += frame.GetPitch(plane), mask += maskFrame?.GetPitch(plane) ?? 0) { for (var x = 0; x < frame.GetRowSize(plane); x += pixelSize) { if (maskFrame == null || mask[x] > 0) { hist[data[x]]++; } } } } return(hist); }
public bool Equal(YUVPlanes plane, int channel) { return(Channel == channel && (Plane == plane || SAME.Contains(Plane) && SAME.Contains(plane))); }