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);
 }
Пример #2
0
        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));
 }
Пример #4
0
        public void Return(IPixelBuffer buffer)
        {
            if (buffer is not TBuffer b)
            {
                throw new ArgumentException("Invalid buffer type!");
            }

            _pool.Return(b);
        }
Пример #5
0
 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));
 }
Пример #7
0
        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);
            }
        }
Пример #8
0
        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);
        }
Пример #9
0
        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");
            }
        }
Пример #10
0
        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);
            }
        }
Пример #11
0
        // 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..];
Пример #13
0
        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));
        }
Пример #14
0
        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));
        }
Пример #15
0
 public static TPixel GetPixel <TPixel>(this IPixelBuffer <TPixel> buffer, int x, int y)
     where TPixel : unmanaged, IPixel
 {
     return(buffer.GetPixelRowSpan(y)[x]);
 }
Пример #16
0
 public static Span <TPixel> GetPixelRow <TPixel>(this IPixelBuffer <TPixel> buffer, int x, int y)
     where TPixel : unmanaged, IPixel
 {
     return(buffer.GetPixelRow(y)[x..]);
Пример #17
0
 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)
 {
 }
Пример #20
0
 public ImageFrame(IPixelBuffer <TPixel> pixels, int delay) : base(pixels, delay)
 {
     Pixels = pixels ?? throw new ArgumentNullException(nameof(pixels));
 }
Пример #21
0
 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);
 }