private void ProcessPlane(ImagePlane plane, ProcessingBounds bounds) { ProcessingHelper.ProcessMono(plane, bounds, (b) => { return((byte)(b >= Threshold ? 255 : 0)); }, PixelFilter); }
private void ProcessPlane(ImagePlane plane, ProcessingBounds bounds) { ProcessingHelper.ProcessMono(plane, bounds, (b) => { return(ValueProvider.Provide()); }, PixelFilter); }
private void ProcessPlane(ImagePlane plane, ProcessingBounds bounds) { var valueDic = BuildValueDictionary(Mode, plane, bounds); ProcessingHelper.ProcessMono(plane, bounds, (b, y, x) => { return((Mode == SmearMode.VerticalFromTop || Mode == SmearMode.VerticalFromBottom) ? valueDic[x] : valueDic[y]); }, PixelFilter); }
private void ProcessPlane(ImagePlane plane, ProcessingBounds bounds) { if (plane.TryGetLinearAccess(out LinearAccessData data)) { int startY = bounds.StartY; int startX = bounds.StartX; int boundsY = startY + bounds.Height; int boundsX = startX + bounds.Width; int imageHeight = plane.Parent.Height; int imageWidth = plane.Parent.Width; var yInc = (int)data.YInc; var xInc = (int)data.XInc; unsafe { var pBase = (byte *)data.BasePtr; for (int yy = bounds.StartY; yy < boundsY; yy += PixelateSize) { int offsetY = PixelateSize / 2; int yyPixelateSize = yy + PixelateSize; for (int xx = bounds.StartX; xx < boundsX; xx += PixelateSize) { int offsetX = PixelateSize / 2; int xxPixelateSize = xx + PixelateSize; while (xx + offsetX >= imageWidth) { offsetX--; } while (yy + offsetY >= imageHeight) { offsetY--; } byte *pPixelatedPixel = pBase + ((yy + offsetY) * yInc) + ((xx + offsetX) * xInc); for (int y = yy; y < yyPixelateSize && y < imageHeight; y++) { byte *pLine = pBase + yInc * y; for (int x = xx; x < xxPixelateSize && x < imageWidth; x++) { byte *pPixel = pLine + xInc * x; if (PixelFilter.Check(*pPixel, y * boundsY + x)) { *pPixel = *pPixelatedPixel; } } } } } } } else { throw new ArgumentException("Plane could not be accessed linearly", nameof(plane)); } }
private void ProcessPlane(ImagePlane plane, int[] weights, ProcessingBounds bounds, int weightSum) { var outputPlane = ProcessingHelper.ProcessMonoKernel(plane, (kl) => { return(ApplyWeights(kl, weights, weightSum)); }, KernelSize, bounds, PixelFilter); outputPlane.CopyTo(plane.Parent.Planes[plane.Plane]); }
private void ProcessPlane(ImagePlane plane, ProcessingBounds bounds) { var outputPlane = ProcessingHelper.ProcessMonoKernel(plane, (kl) => { return(kl.Where(b => b.HasValue).Min(b => b.Value)); }, KernelSize, bounds, PixelFilter); outputPlane.CopyTo(plane.Parent.Planes[plane.Plane]); }
private void ProcessPlane(ImagePlane plane, ProcessingBounds bounds) { var outputPlane = ProcessingHelper.ProcessMonoKernel(plane, (kl) => { var stripped = kl.Where(b => b.HasValue); return((byte)(stripped.Sum(b => b.Value) / stripped.Count())); }, KernelSize, bounds, PixelFilter); outputPlane.CopyTo(plane.Parent.Planes[plane.Plane]); }
private void ProcessPlane(ImagePlane plane, ProcessingBounds bounds) { var outputPlane = ProcessingHelper.ProcessMonoKernel(plane, (kl) => { var stripped = kl.Where(b => b.HasValue).ToArray(); Array.Sort(stripped); return(UseHigherMedian ? stripped[stripped.Length / 2].Value : stripped[(stripped.Length / 2) - 1].Value); }, KernelSize, bounds, PixelFilter); outputPlane.CopyTo(plane.Parent.Planes[plane.Plane]); }
/// <summary> /// Processes the pixels of the given <paramref name="plane"/> /// in the given <paramref name="bounds"/> with the /// given <paramref name="processorFunc"/>. /// </summary> /// <param name="plane">The plane whose pixels to process.</param> /// <param name="bounds">Bounds defining which pixels to process.</param> /// <param name="processorFunc">Func that takes a byte, processes /// it and returns a byte.</param> /// <param name="filterChain">Optional filter chain.</param> public static void ProcessMono(ImagePlane plane, ProcessingBounds bounds, Func <byte, byte> processorFunc, PixelFilterChain filterChain) { if (filterChain == null || !filterChain.HasActiveFilter) { ProcessMono(plane, bounds, processorFunc); return; } if (processorFunc == null) { throw new ArgumentNullException(nameof(processorFunc)); } if (plane.TryGetLinearAccess(out LinearAccessData data)) { var yInc = (int)data.YInc; var xInc = (int)data.XInc; int startY = bounds.StartY; int startX = bounds.StartX; int boundsY = startY + bounds.Height; int boundsX = startX + bounds.Width; unsafe { var pBase = (byte *)data.BasePtr; Parallel.For(startY, boundsY, (y) => { byte *pLine = pBase + yInc * y; for (int x = startX; x < boundsX; x++) { byte *pPixel = pLine + xInc * x; if (filterChain.Check(*pPixel, y * boundsY + x)) { *pPixel = processorFunc.Invoke(*pPixel); } } }); } } else { throw new ArgumentException("Plane could not be accessed linear", nameof(plane)); } }
private void ProcessPlane(ImagePlane plane, ProcessingBounds bounds) { ProcessingHelper.ProcessMono(plane, bounds, (b) => { if (ShiftDirection == BitShiftDirection.Left) { int pixelValue = b << ValueProvider.Provide(); if (WrapAround && pixelValue > 255) { return(255); } else { return((byte)pixelValue); } } else { return((byte)(b >> ValueProvider.Provide())); } }, PixelFilter); }
private void ProcessPlane(ImagePlane plane, ProcessingBounds bounds) { int byteCounter = 0; byte[] sortedBytes; unsafe { if (UseAOI) { if (Mode == SortMode.Ascending) { sortedBytes = plane.GetAllPixelsIn(AOI).Select(p => *(byte *)p).OrderBy(i => i).ToArray(); } else { sortedBytes = plane.GetAllPixelsIn(AOI).Select(p => *(byte *)p).OrderByDescending(i => i).ToArray(); } } else { if (Mode == SortMode.Ascending) { sortedBytes = plane.AllPixels.Select(p => *(byte *)p).OrderBy(i => i).ToArray(); } else { sortedBytes = plane.AllPixels.Select(p => *(byte *)p).OrderByDescending(i => i).ToArray(); } } } ProcessingHelper.ProcessMono(plane, bounds, (b) => { return(sortedBytes[byteCounter++]); }, PixelFilter); }
private void ProcessPlane(ImagePlane plane, ProcessingBounds bounds) { var rnd = new Random(DateTime.Now.Ticks.GetHashCode()); int byteCounter = 0; byte[] shuffledBytes; unsafe { if (UseAOI) { shuffledBytes = plane.GetAllPixelsIn(AOI).Select(p => *(byte *)p).OrderBy(i => rnd.Next()).ToArray(); } else { shuffledBytes = plane.AllPixels.Select(p => *(byte *)p).OrderBy(i => rnd.Next()).ToArray(); } } ProcessingHelper.ProcessMono(plane, bounds, (b) => { return(shuffledBytes[byteCounter++]); }, PixelFilter); }
private static IDictionary <int, byte> BuildValueDictionary(SmearMode mode, ImagePlane plane, ProcessingBounds bounds) { var dic = new Dictionary <int, byte>(); if (mode == SmearMode.VerticalFromTop) { for (int x = bounds.StartX; x < bounds.StartX + bounds.Width; x++) { dic.Add(x, (byte)plane.GetPixel(x, bounds.StartY)); } } else if (mode == SmearMode.VerticalFromBottom) { for (int x = bounds.StartX; x < bounds.StartX + bounds.Width; x++) { dic.Add(x, (byte)plane.GetPixel(x, bounds.StartY + bounds.Height - 1)); } } else if (mode == SmearMode.HorizontalFromLeft) { for (int y = bounds.StartY; y < bounds.StartY + bounds.Height; y++) { dic.Add(y, (byte)plane.GetPixel(bounds.StartX, y)); } } else if (mode == SmearMode.HorizontalFromRight) { for (int y = bounds.StartY; y < bounds.StartY + bounds.Height; y++) { dic.Add(y, (byte)plane.GetPixel(bounds.StartX + bounds.Width - 1, y)); } } else { throw new ArgumentException("Unknown Smear Mode", nameof(mode)); } return(dic); }
/// <summary> /// Processes the given rgb <paramref name="img"/> in the /// given <paramref name="bounds"/> with /// the given <paramref name="processingFunc"/>. /// </summary> /// <param name="img">Image to process.</param> /// <param name="processingFunc">Processing function to process /// the <paramref name="img"/> with.</param> /// <param name="bounds">Bounds defining which pixels to process.</param> /// <param name="filterChain">Optional filter chain.</param> public static void ProcessRGB(Image img, Func <RGBPixel, RGBPixel> processingFunc, ProcessingBounds bounds, PixelFilterChain filterChain) { if (filterChain == null || !filterChain.HasActiveFilter) { ProcessRGB(img, processingFunc, bounds); return; } if (img == null) { throw new ArgumentNullException(nameof(img)); } if (img.Planes.Count < 3) { throw new ArgumentException("Image is no rgb image", nameof(img)); } if (processingFunc == null) { throw new ArgumentNullException(nameof(processingFunc)); } if (img.Planes[0].TryGetLinearAccess(out LinearAccessData rData) && img.Planes[1].TryGetLinearAccess(out LinearAccessData gData) && img.Planes[2].TryGetLinearAccess(out LinearAccessData bData)) { int startY = bounds.StartY; int startX = bounds.StartX; int boundsY = startY + bounds.Height; int boundsX = startX + bounds.Width; var rYInc = (int)rData.YInc; var gYInc = (int)gData.YInc; var bYInc = (int)bData.YInc; var rXInc = (int)rData.XInc; var gXInc = (int)gData.XInc; var bXInc = (int)bData.XInc; unsafe { var pBaseR = (byte *)rData.BasePtr; var pBaseG = (byte *)gData.BasePtr; var pBaseB = (byte *)bData.BasePtr; Parallel.For(startY, boundsY, (y) => { byte *rLine = pBaseR + rYInc * y; byte *gLine = pBaseG + gYInc * y; byte *bLine = pBaseB + bYInc * y; for (int x = startX; x < boundsX; x++) { byte *rPixel = rLine + rXInc * x; byte *gPixel = gLine + gXInc * x; byte *bPixel = bLine + bXInc * x; if (filterChain.Check(*rPixel, *gPixel, *bPixel, y * boundsY + x)) { var result = processingFunc.Invoke(new RGBPixel(*rPixel, *gPixel, *bPixel)); *rPixel = result.R; *gPixel = result.G; *bPixel = result.B; } } }); } }
public static ImagePlane ProcessMonoKernel(ImagePlane plane, Func <byte?[], byte> processingFunc, KernelSize kernel, ProcessingBounds bounds) { if (plane.TryGetLinearAccess(out LinearAccessData data)) { var newImage = Image.FromPlanes(MappingOption.CopyPixels, plane); var newData = newImage.Planes[0].GetLinearAccess(); var yInc = (int)data.YInc; var xInc = (int)data.XInc; var newYInc = (int)newData.YInc; var newXInc = (int)newData.XInc; int boundHeight = plane.Parent.Height - 1; int boundWidth = plane.Parent.Width - 1; int startY = bounds.StartY; int startX = bounds.StartX; int boundsY = startY + bounds.Height; int boundsX = startX + bounds.Width; int kernelSize = kernel.GetKernelNumber(); int kernelArrSize = kernelSize * kernelSize; var kernelFac = (int)System.Math.Floor(kernelSize / 2.0); unsafe { var pBase = (byte *)data.BasePtr; var pBaseNew = (byte *)newData.BasePtr; Parallel.For(startY, boundsY, (y) => { var kernelValues = new byte?[kernelArrSize]; var pLine = pBase + y * yInc; int newLineInc = newYInc * y; for (int x = startX; x < boundsX; x++) { int kernelCounter = -1; var pMiddle = pLine + xInc * x; for (int kRow = -kernelFac; kRow <= kernelFac; kRow++) { byte *pKLine = pMiddle + kRow * yInc; int yKRow = y + kRow; for (int kColumn = -kernelFac; kColumn <= kernelFac; kColumn++) { kernelCounter++; int xKColumn = x + kColumn; if (yKRow < 0 || yKRow > boundHeight || xKColumn < 0 || xKColumn > boundWidth) { continue; } byte *pPixel = pKLine + kColumn * xInc; kernelValues[kernelCounter] = *pPixel; } } if (kernelValues.Any(b => b.HasValue)) { var pTargetLine = pBaseNew + newLineInc; var pTargetPixel = pTargetLine + newXInc * x; // current "middle pixel" in the target image *pTargetPixel = processingFunc.Invoke(kernelValues); } } }); } return(newImage.Planes[0]); } else { throw new ArgumentException("Plane could not be accessed linear", nameof(plane)); } }
private void ProcessPlane(ImagePlane inputPlane, ImagePlane newPlane, ProcessingBounds bounds) { if (inputPlane.TryGetLinearAccess(out LinearAccessData inputData)) { if (newPlane.TryGetLinearAccess(out LinearAccessData newData)) { var inputYInc = (int)inputData.YInc; var inputXInc = (int)inputData.XInc; var newYInc = (int)newData.YInc; var newXInc = (int)newData.XInc; int boundsY = bounds.StartY + bounds.Height; int boundsX = bounds.StartX + bounds.Width; unsafe { var inputPBase = (byte *)inputData.BasePtr; var newPBase = (byte *)newData.BasePtr; for (int y = bounds.StartY; y < boundsY; y++) { byte *inputPLine = inputPBase + inputYInc * y; byte *newPLine; int newY = y + ShiftY; if (newY < boundsY) { newPLine = newPBase + newYInc * newY; } else if (Wrap) { newPLine = newPBase + newYInc * (newY - boundsY); } else { continue; } for (int x = bounds.StartX; x < boundsX; x++) { byte *inputPPixel = inputPLine + inputXInc * x; byte *newPPixel; int newX = x + ShiftX; if (newX < boundsX) { newPPixel = newPLine + newXInc * newX; } else if (Wrap) { newPPixel = newPLine + newXInc * (newX - boundsX); } else { continue; } if (PixelFilter.Check(*inputPPixel, y * boundsY + x)) { *newPPixel = *inputPPixel; } } } } } else { throw new ArgumentException("New plane could not be accessed linear"); } } else { throw new ArgumentException("Input plane could not be accessed linear"); } }
private void ProcessPlane(ImagePlane plane, Func <int, byte, byte> calculationFunc, ProcessingBounds bounds) { ProcessingHelper.ProcessMono(plane, bounds, (b) => { return(calculationFunc(ValueProvider.Provide(), b)); }, PixelFilter); }