예제 #1
0
            public string GetMagickCommand(long memoryLimit)
            {
                var extension = Format.GetExtension();
                var limit     = memoryLimit.ToInvariantString();
                var cuts      = Cuts.ToInvariantString();

                return($"montage piece-*-*{extension} -limit memory {limit} -limit map {limit} -tile {cuts}x{cuts} -background none -geometry +0+0 out{extension}");
            }
예제 #2
0
        public SplitShotInformation SplitShot(int width, int height, double downscale, string destination, RendererShotFormat format,
                                              IProgress <Tuple <string, double?> > progress = null, CancellationToken cancellation = default(CancellationToken))
        {
            Directory.CreateDirectory(destination);
            SplitShot(width, height, downscale, format, (c, x, y, w, h) => {
                var filename = Path.Combine(destination, $"piece-{y:D2}-{x:D2}{format.GetExtension()}");
                using (var stream = File.Open(filename, FileMode.Create, FileAccess.ReadWrite)) {
                    c(stream);
                }
            }, out var cuts, progress, cancellation);

            return(new SplitShotInformation {
                Cuts = cuts,
                Format = format
            });
        }
예제 #3
0
        protected override void SplitShotPieces(Size size, bool downscale, string filename, RendererShotFormat format,
                                                IProgress <Tuple <string, double?> > progress = null,
                                                CancellationToken cancellation = default(CancellationToken))
        {
            /*if (format.IsHdr()) {
             *  throw new NotSupportedException("Can’t make an HDR-screenshot in super-resolution");
             * }*/

            PiecesBlender.OptionMaxCacheSize = SettingsHolder.Plugins.MontageVramCache;

            var plugin = PluginsManager.Instance.GetById(KnownPlugins.ImageMontage);

            if (plugin == null || !plugin.IsReady)
            {
                if (!_warningShown)
                {
                    _warningShown = true;
                    FirstFloor.ModernUI.Windows.Toast.Show("Montage plugin not installed", "You’ll have to join pieces manually");
                }

                OptionMontageMemoryLimit = SettingsHolder.Plugins.MontageMemoryLimit;
                base.SplitShotPieces(size, downscale, filename, format, progress, cancellation);
            }
            else
            {
                var dark        = (DarkKn5ObjectRenderer)Renderer;
                var destination = Path.Combine(SettingsHolder.Plugins.MontageTemporaryDirectory, Path.GetFileNameWithoutExtension(filename) ?? "image");

                // For pre-smoothed files, in case somebody would want to use super-resolution with SSLR/SSAO
                DarkKn5ObjectRenderer.OptionTemporaryDirectory = destination;

                var information = dark.SplitShot(size.Width, size.Height, downscale ? 0.5d : 1d, destination, format,
                                                 progress.SubrangeTuple(0.001, 0.95, "Rendering ({0})…"), cancellation);

                progress?.Report(new Tuple <string, double?>("Combining pieces…", 0.97));

                var magick = plugin.GetFilename("magick.exe");
                if (!File.Exists(magick))
                {
                    magick = plugin.GetFilename("montage.exe");
                    FirstFloor.ModernUI.Windows.Toast.Show("Montage plugin is obsolete", "Please, update it, and it’ll consume twice less power");
                }

                Environment.SetEnvironmentVariable(@"MAGICK_TMPDIR", destination);
                using (var process = new Process {
                    StartInfo =
                    {
                        FileName               = magick,
                        WorkingDirectory       = destination,
                        Arguments              = information.GetMagickCommand(SettingsHolder.Plugins.MontageMemoryLimit),
                        CreateNoWindow         = true,
                        RedirectStandardInput  = true,
                        RedirectStandardOutput = true,
                        UseShellExecute        = false
                    },
                    EnableRaisingEvents = true
                }) {
                    process.Start();
                    process.WaitForExit(600000);
                    if (!process.HasExited)
                    {
                        process.Kill();
                    }
                }

                progress?.Report(new Tuple <string, double?>("Cleaning up…", 0.99));

                var result = Path.Combine(destination, $"out{format.GetExtension()}");
                if (!File.Exists(result))
                {
                    throw new Exception("Combining failed, file not found");
                }

                File.Move(result, filename);
                Directory.Delete(destination, true);
            }
        }
예제 #4
0
        private void SplitShot(int width, int height, double downscale, RendererShotFormat format, SplitCallback callback, out int cuts,
                               [CanBeNull] IProgress <Tuple <string, double?> > progress, CancellationToken cancellation)
        {
            ShotInProcessValue++;

            var original = new { Width, Height, ResolutionMultiplier, TimeFactor };

            ResolutionMultiplier = 1d;
            AutoAdjustTarget     = false;
            AutoRotate           = false;
            TimeFactor           = 0f;

            cuts = Math.Ceiling(width / OptionMaxWidth).FloorToInt();
            if (cuts < 1)
            {
                cuts = 1;
            }

            width  /= cuts;
            height /= cuts;

            var expand = UseSslr || UseAo;
            int extraWidth, extraHeight;

            if (expand)
            {
                extraWidth  = (width * OptionGBufferExtra).RoundToInt();
                extraHeight = (height * OptionGBufferExtra).RoundToInt();
            }
            else
            {
                extraWidth  = width;
                extraHeight = height;
            }

            Width  = extraWidth;
            Height = extraHeight;

            var baseCut = expand ?
                          Matrix.Transformation2D(Vector2.Zero, 0f, new Vector2(1f / OptionGBufferExtra), Vector2.Zero, 0f, Vector2.Zero) :
                          Matrix.Identity;

            try {
                var temporary = OptionTemporaryDirectory;
                if (expand && temporary != null)
                {
                    FileUtils.EnsureDirectoryExists(temporary);

                    for (var i = 0; i < cuts * cuts; i++)
                    {
                        var x = i % cuts;
                        var y = i / cuts;
                        progress?.Report(new Tuple <string, double?>($"x={x}, y={y}, piece by piece", (double)i / (cuts * cuts) * 0.5));
                        if (cancellation.IsCancellationRequested)
                        {
                            return;
                        }

                        SetCutProjection(cuts, x, y, baseCut);
                        var filename = Path.Combine(temporary, $"tmp-{y:D2}-{x:D2}{format.GetExtension()}");
                        using (var stream = File.Open(filename, FileMode.Create, FileAccess.ReadWrite)) {
                            Shot(extraWidth, extraHeight, downscale, 1d, stream, format);
                        }
                    }

                    var shotWidth  = (width * downscale).RoundToInt();
                    var shotHeight = (height * downscale).RoundToInt();
                    AcToolsLogging.Write($"Rendered: downscale={downscale}, {shotWidth}×{shotHeight}, {LastShotWidth}×{LastShotHeight}");

                    using (var blender = new PiecesBlender(shotWidth, shotHeight, OptionGBufferExtra)) {
                        blender.Initialize();

                        for (var i = 0; i < cuts * cuts; i++)
                        {
                            var x = i % cuts;
                            var y = i / cuts;
                            progress?.Report(new Tuple <string, double?>($"X={x}, Y={y}, smoothing", (double)i / (cuts * cuts) * 0.5 + 0.5));
                            if (cancellation.IsCancellationRequested)
                            {
                                return;
                            }

                            callback(s => blender.Process(new Pieces(temporary, $"tmp-{{0:D2}}-{{1:D2}}{format.GetExtension()}", y, x), s),
                                     x, y, shotWidth, shotHeight);
                        }
                    }

                    AcToolsLogging.Write("Blended");
                }
                else
                {
                    for (var i = 0; i < cuts * cuts; i++)
                    {
                        var x = i % cuts;
                        var y = i / cuts;
                        progress?.Report(new Tuple <string, double?>($"X={x}, Y={y}", (double)i / (cuts * cuts)));
                        if (cancellation.IsCancellationRequested)
                        {
                            return;
                        }

                        SetCutProjection(cuts, x, y, baseCut);
                        callback(s => Shot(extraWidth, extraHeight, downscale, expand ? OptionGBufferExtra : 1d, s, format),
                                 x, y, (original.Width * downscale).RoundToInt(), (original.Height * downscale).RoundToInt());
                    }
                }
            } finally {
                Camera.CutProj = null;
                Camera.SetLens(Camera.Aspect);

                Width  = original.Width;
                Height = original.Height;
                ResolutionMultiplier = original.ResolutionMultiplier;
                TimeFactor           = original.TimeFactor;

                ShotInProcessValue--;
            }
        }