private static void ReflectionLoadPixelRows <TPixelFrom, TPixelTo>( IReadOnlyPixelRows pixels, IPixelBuffer destination, Rectangle?sourceRectangle) where TPixelFrom : unmanaged, IPixel where TPixelTo : unmanaged, IPixel <TPixelTo> { LoadPixels <TPixelFrom, TPixelTo>(pixels, (IPixelBuffer <TPixelTo>)destination, sourceRectangle); }
private void ResultFunc( IPixelBuffer pixelBuffer, RendererData rendererData, ConcurrentQueue <RenderLineResult> resultQueue, AutoResetEvent queueDataAvailableEvent) { var incompleteRows = new HashSet <int>(); for (var y = 0; y < pixelBuffer.Height; y++) { incompleteRows.Add(y); } while (incompleteRows.Count > 0) { queueDataAvailableEvent.WaitOne(TimeSpan.FromMilliseconds(1000)); while (resultQueue.TryDequeue(out var renderLineResult)) { foreach (var data in renderLineResult.RowPixels) { rendererData.SetPixelData(data); } // assert pixelArray.Width == renderLineResult.Count pixelBuffer.SetPixelRowColors(renderLineResult.Y, renderLineResult.RowPixels.Select(x => x.Color)); incompleteRows.Remove(renderLineResult.Y); var totalRows = Convert.ToSingle(pixelBuffer.Height); var completeRows = Convert.ToSingle(pixelBuffer.Height - incompleteRows.Count); var percentComplete = completeRows / totalRows * 100.0f; Console.WriteLine($"Percent Complete: {percentComplete:F}%"); Progress?.Invoke(this, new RenderProgressEventArgs(percentComplete)); } } }
public static void MutateBuffer(this IPixelBuffer pixels, ImagingConfig imagingConfig, PixelBufferMutatorCallback mutator) { if (mutator == null) { throw new ArgumentNullException(nameof(mutator)); } mutator.Invoke(new PixelBufferContext(imagingConfig, pixels)); }
public void Return(IPixelBuffer buffer) { if (buffer is not TBuffer b) { throw new ArgumentException("Invalid buffer type!"); } _pool.Return(b); }
public RendererData Render(IPixelBuffer pixelArray, IScene scene, RenderConfig renderConfig) { return(Render( pixelArray, scene.GetCamera(pixelArray.Width, pixelArray.Height), scene.GetWorld(), scene.GetLightHitable(), renderConfig, scene.GetBackgroundFunc())); }
public static void MutateBuffer <TPixel>(this IPixelBuffer <TPixel> pixels, ImagingConfig imagingConfig, PixelBufferMutatorCallback <TPixel> mutator) where TPixel : unmanaged, IPixel { if (mutator == null) { throw new ArgumentNullException(nameof(mutator)); } mutator.Invoke(new PixelBufferContext <TPixel>(imagingConfig, pixels)); }
private void ResultFunc( IPixelBuffer pixelBuffer, RendererData rendererData, ConcurrentQueue <RenderResult> resultQueue, AutoResetEvent queueDataAvailableEvent) { try { var incompletePixels = new HashSet <Tuple <int, int> >(); for (var y = 0; y < pixelBuffer.Height; y++) { for (int x = 0; x < pixelBuffer.Width; x++) { incompletePixels.Add(Tuple.Create(x, y)); } } var totalPixels = Convert.ToSingle(pixelBuffer.Height * pixelBuffer.Width); int previousPercent = 0; while (incompletePixels.Count > 0) { queueDataAvailableEvent.WaitOne(TimeSpan.FromMilliseconds(1000)); while (resultQueue.TryDequeue(out var renderResult)) { rendererData.SetPixelData(renderResult.PixelData); // assert pixelArray.Width == renderLineResult.Count pixelBuffer.SetPixelColor(renderResult.X, renderResult.Y, renderResult.PixelData.Color); incompletePixels.Remove(Tuple.Create(renderResult.X, renderResult.Y)); var completePixels = Convert.ToSingle(totalPixels - incompletePixels.Count); var percentComplete = completePixels / totalPixels * 100.0f; int intPercent = Convert.ToInt32(percentComplete); if (intPercent > previousPercent) { previousPercent = intPercent; Console.WriteLine($"Percent Complete: {percentComplete:F}%"); Progress?.Invoke(this, new RenderProgressEventArgs(percentComplete)); } } } } catch (Exception ex) { Console.WriteLine(ex); } }
private RendererData RenderMultiThreaded( IPixelBuffer pixelArray, Camera camera, IHitable world, IHitable lightHitable, RenderConfig renderConfig, Func <Ray, ColorVector> backgroundFunc) { var rendererData = new RendererData(pixelArray.Width, pixelArray.Height); var rayTracer = new RayTracer(camera, world, lightHitable, renderConfig, pixelArray.Width, pixelArray.Height, backgroundFunc); ThreadPool.SetMinThreads(renderConfig.NumThreads * 3, renderConfig.NumThreads * 3); var queueDataAvailableEvent = new AutoResetEvent(false); var inputQueue = new ConcurrentQueue <RenderInput>(); var resultQueue = new ConcurrentQueue <RenderResult>(); for (var y = pixelArray.Height - 1; y >= 0; y--) { for (var x = 0; x < pixelArray.Width; x++) { inputQueue.Enqueue(new RenderInput(x, y)); } } var tasks = new List <Task>(); try { for (var thid = 0; thid < renderConfig.NumThreads; thid++) { Console.WriteLine($"Creating task for thread id: {thid}"); tasks.Add( Task.Run(() => RenderFunc(rayTracer, inputQueue, resultQueue, queueDataAvailableEvent))); } tasks.Add(Task.Run(() => ResultFunc(pixelArray, rendererData, resultQueue, queueDataAvailableEvent))); Task.WaitAll(tasks.ToArray()); } catch (Exception ex) { Console.WriteLine(ex); } return(rendererData); }
public async Task HighlightAsync(Image target, IPixelBuffer pixels, int limit, IDiffProgressObserver progress = null) { using var g = Graphics.FromImage(target); await foreach (var cluster in _clusteringAlgorithm.GetClustersAsync(pixels, limit)) { g.DrawRectangle(_pen, cluster); if (progress == null) { continue; } using var report = new ReportBuilder(target).AddRectangle(cluster, _pen).Build(); await progress.ReportAsync(report, "rect"); } }
public static void LoadPixelData <TPixelFrom, TPixelTo>( ReadOnlySpan <byte> pixelData, Rectangle sourceRectangle, IPixelBuffer destination, int?byteStride) where TPixelFrom : unmanaged, IPixel where TPixelTo : unmanaged, IPixel <TPixelTo> { if (destination == null) { throw new ArgumentNullException(nameof(destination)); } int srcOffsetX = sourceRectangle.X * Unsafe.SizeOf <TPixelFrom>(); int srcByteStride = byteStride ?? (sourceRectangle.Width * Unsafe.SizeOf <TPixelFrom>()); for (int y = 0; y < sourceRectangle.Height; y++) { var srcByteRow = pixelData.Slice(srcOffsetX + (sourceRectangle.Y + y) * srcByteStride, srcByteStride); var dstByteRow = destination.GetPixelByteRowSpan(y); ConvertPixelData <TPixelFrom, TPixelTo>(srcByteRow, dstByteRow); } }
// TODO: move these out of Image class // AND ALSO make them into extenions for Image class public static void LoadPixels <TPixelFrom, TPixelTo>( ReadOnlySpan <TPixelFrom> pixels, IPixelBuffer <TPixelTo> destination, Rectangle sourceRectangle, int?pixelStride = null) where TPixelFrom : unmanaged, IPixel where TPixelTo : unmanaged, IPixel <TPixelTo> { if (destination == null) { throw new ArgumentNullException(nameof(destination)); } ImagingArgumentGuard.AssertNonEmptyRectangle(sourceRectangle, nameof(sourceRectangle)); int srcStride = pixelStride ?? sourceRectangle.Width; for (int y = 0; y < sourceRectangle.Height; y++) { var srcRow = pixels.Slice(sourceRectangle.X + (sourceRectangle.Y + y) * srcStride, srcStride); var dstRow = destination.GetPixelRow(y); ConvertPixels(srcRow, dstRow); } }
public static void LoadPixels <TPixelFrom, TPixelTo>( IReadOnlyPixelRows pixels, IPixelBuffer <TPixelTo> destination, Rectangle?sourceRectangle = null) where TPixelFrom : unmanaged, IPixel where TPixelTo : unmanaged, IPixel <TPixelTo> { if (pixels == null) { throw new ArgumentNullException(nameof(pixels)); } if (destination == null) { throw new ArgumentNullException(nameof(destination)); } var rect = sourceRectangle ?? pixels.GetBounds(); ImagingArgumentGuard.AssertNonEmptyRectangle(rect, nameof(sourceRectangle)); Span <byte> rowByteBuffer = stackalloc byte[4096]; var rowBuffer = MemoryMarshal.Cast <byte, TPixelFrom>(rowByteBuffer); for (int y = 0; y < rect.Height; y++) { var dstRow = destination.GetPixelRowSpan(y); int offsetX = 0; do { int left = rect.Width - offsetX; int count = Math.Min(rowBuffer.Length, left); var slice = rowBuffer.Slice(0, count); pixels.GetPixelByteRow(rect.X + offsetX, rect.Y + y, MemoryMarshal.AsBytes(slice)); ConvertPixels(slice, dstRow); dstRow = dstRow[count..];
public RendererData Render( IPixelBuffer pixelArray, Camera camera, IHitable world, IHitable lightHitable, RenderConfig renderConfig, Func <Ray, ColorVector> backgroundFunc) { Progress?.Invoke(this, new RenderProgressEventArgs(0.0f)); if (renderConfig.TwoPhase) { // do a much lighter weight first pass first. RenderMultiThreaded( pixelArray, camera, world, lightHitable, new RenderConfig(renderConfig.NumThreads, 5, 1), backgroundFunc); } return(RenderMultiThreaded(pixelArray, camera, world, lightHitable, renderConfig, backgroundFunc)); }
public RendererData Render(IPixelBuffer pixelArray, Camera camera, IHitable world, IHitable lightHitable, RenderConfig renderConfig, Func <Ray, ColorVector> backgroundFunc) { Progress?.Invoke(this, new RenderProgressEventArgs(0.0f)); return(RenderMultiThreaded(pixelArray, camera, world, lightHitable, renderConfig, backgroundFunc)); }
public static TPixel GetPixel <TPixel>(this IPixelBuffer <TPixel> buffer, int x, int y) where TPixel : unmanaged, IPixel { return(buffer.GetPixelRowSpan(y)[x]); }
public static Span <TPixel> GetPixelRow <TPixel>(this IPixelBuffer <TPixel> buffer, int x, int y) where TPixel : unmanaged, IPixel { return(buffer.GetPixelRow(y)[x..]);
public static void SetPixel <TPixel>(this IPixelBuffer <TPixel> buffer, int x, int y, TPixel value) where TPixel : unmanaged, IPixel { buffer.GetPixelRowSpan(y)[x] = value; }
public PixelBufferContext(IImagingConfig imagingConfig, IPixelBuffer <TPixel> pixels) : base(imagingConfig, pixels) { }
public CropBuffer( IPixelBuffer buffer, Rectangle sourceRectangle) : base(buffer, sourceRectangle) { }
public ImageFrame(IPixelBuffer <TPixel> pixels, int delay) : base(pixels, delay) { Pixels = pixels ?? throw new ArgumentNullException(nameof(pixels)); }
public ImageTexture(IPixelBuffer pixelBuffer) { _pixelBuffer = pixelBuffer; }
public static void MutateBuffer <TPixel>(this IPixelBuffer <TPixel> pixels, PixelBufferMutatorCallback <TPixel> mutator) where TPixel : unmanaged, IPixel { MutateBuffer(pixels, ImagingConfig.Default, mutator); }
public static void MutateBuffer(this IPixelBuffer pixels, PixelBufferMutatorCallback mutator) { MutateBuffer(pixels, ImagingConfig.Default, mutator); }