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}"); }
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 }); }
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); } }
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--; } }