Exemple #1
0
        public string GetImageFileName(int width, int height, double dpiX, double dpiY, CancellationToken cancellationToken, string settingsSummary, string exportDirectory)
        {
            var sw = Stopwatch.StartNew();

            OutputLogEveryXPixel = (width * height / 100);

            if (AccelerationStructure)
            {
                _accelerationStructure = BVHNode.BuildTopDown(_spheres, _logger);
            }

            var bitmap = new BitmapImage(width, height, dpiX, dpiY);

            var divideX = width / (float)2;
            var alignX  = 1 - divideX;

            var divideY = height / (float)2;
            var alignY  = 1 - divideY;

            int workDone  = 0;
            int totalWork = width * height;

            if (Parallelize)
            {
                var options = new ParallelOptions()
                {
                    CancellationToken = cancellationToken, MaxDegreeOfParallelism = Environment.ProcessorCount
                };

                Parallel.For(0, width, options, i =>
                {
                    for (int j = 0; j < height; j++)
                    {
                        if (cancellationToken.IsCancellationRequested)
                        {
                            break;
                        }

                        if (AntiAliasing)
                        {
                            Vector3 result = Vector3.Zero;
                            for (int k = 0; k < AntiAliasingSampleSize; k++)
                            {
                                var dx = (float)_random.NextGaussian(0d, 0.5d);
                                var dy = (float)_random.NextGaussian(0d, 0.5d);

                                var x   = (i + alignX + dx) / divideX;
                                var y   = ((height - j) + alignY + dy) / divideY;
                                var rgb = GetColor(x, y);
                                result += rgb;
                            }

                            var avg_rgb = result * (1f / AntiAliasingSampleSize);
                            var c       = Conversions.FromRGB(avg_rgb, GammaCorrect);
                            bitmap.Set(i, j, c);
                        }
                        else
                        {
                            var x   = (i + alignX) / divideX;
                            var y   = ((height - j) + alignY) / divideY;
                            var rgb = GetColor(x, y);
                            var c   = Conversions.FromRGB(rgb, GammaCorrect);
                            bitmap.Set(i, j, c);
                        }

                        var value = Interlocked.Increment(ref workDone);

                        if (value % OutputLogEveryXPixel == 0)
                        {
                            var progress = (float)value / totalWork;
                            WriteOutput($"{(progress * 100):F3}% progress. Running {sw.Elapsed}. Remaining {TimeSpan.FromMilliseconds(sw.Elapsed.TotalMilliseconds / progress * (1f - progress))}.");
                        }
                    }
                });
            }
            else
            {
                for (int i = 0; i < width; i++)
                {
                    if (cancellationToken.IsCancellationRequested)
                    {
                        break;
                    }

                    for (int j = 0; j < height; j++)
                    {
                        if (cancellationToken.IsCancellationRequested)
                        {
                            break;
                        }

                        if (AntiAliasing)
                        {
                            Vector3 result = Vector3.Zero;
                            for (int k = 0; k < AntiAliasingSampleSize; k++)
                            {
                                var x   = (i + alignX + (float)_random.NextGaussian(0d, 0.5d)) / divideX;
                                var y   = ((height - j) + alignY + (float)_random.NextGaussian(0d, 0.5d)) / divideY;
                                var rgb = GetColor(x, y);
                                result += rgb;
                            }

                            var avg_rgb = result * (1f / AntiAliasingSampleSize);
                            var c       = Conversions.FromRGB(avg_rgb, GammaCorrect);
                            bitmap.Set(i, j, c);
                        }
                        else
                        {
                            // Question: Why is it mirrored?
                            var x   = (i + alignX) / divideX;
                            var y   = ((height - j) + alignY) / divideY;
                            var rgb = GetColor(x, y);
                            var c   = Conversions.FromRGB(rgb, GammaCorrect);
                            bitmap.Set(i, j, c);
                        }

                        ++workDone;

                        if (workDone % OutputLogEveryXPixel == 0)
                        {
                            var progress = (float)workDone / totalWork;
                            WriteOutput($"{(progress * 100):F3}% progress. Running {sw.Elapsed}. Remaining {TimeSpan.FromMilliseconds(sw.Elapsed.TotalMilliseconds / progress * (1f - progress))}.");
                        }
                    }
                }
            }

            if (cancellationToken.IsCancellationRequested)
            {
                WriteOutput("Operation canceled by user.");
                return(null);
            }

            var imageSource = bitmap.GetImageSource();

            sw.Stop();

            return(SaveImage(imageSource, sw.Elapsed, settingsSummary, exportDirectory));
        }