private void dlgSave_FileOk(object sender, CancelEventArgs e) { if (this.LoadedBlueprint != null) { SaveFileDialog dlg = (SaveFileDialog)sender; string fName = dlg.FileName; int chosenFilterIndex = dlg.FilterIndex; if (fName.ToLower().EndsWith(".schem")) { Schem2Formatter.writeBlueprint(fName, this.LoadedBlueprint); } else if (fName.ToLower().EndsWith(".schematic")) { if (Materials.List.Any(x => x.IsEnabled && string.IsNullOrWhiteSpace(x.SchematicaMaterialName))) { DialogResult result = MessageBox.Show(this, "Cannot create a 1.12 schematic when 1.13+ blocks are selected. Do you want to automatically " + "disable invalid materials and restart from the beginning of the rendering process. This " + "will remove any material choice overrides or post rendering changes.\n\nYou will need to " + "re-render the image.", ".schematic does not support 1.13+ blocks!" , MessageBoxButtons.YesNo, MessageBoxIcon.Warning ); if (result == DialogResult.Yes) { Materials.List.Where(x => x.IsEnabled && string.IsNullOrWhiteSpace(x.SchematicaMaterialName)) .ToList().ForEach(x => x.IsEnabled = false); Options.Save(); this.InvokeEx(c => c.MaterialOptions.Refresh()); #pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed TaskManager.Get.StartAsync((token) => { ColorMatcher.Get.CompileColorPalette(token, true, Materials.List) .ConfigureAwait(true).GetAwaiter().GetResult(); }); #pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed return; } } else { SchematicFormatter.writeBlueprint(fName, this.LoadedBlueprint); } } else if (fName.ToLower().EndsWith(".png")) { if (this.renderedImagePanel != null) { this.renderedImagePanel.SaveToPNG(fName); } } else if (fName.ToLower().EndsWith(".pxlzip")) { PixelStackerProjectFormatter.SaveProject(fName); } else if (fName.ToLower().EndsWith(".csv")) { Dictionary <Material, int> materialCounts = new Dictionary <Material, int>(); bool isv = Options.Get.IsSideView; int xM = this.LoadedBlueprint.Mapper.GetXLength(isv); int yM = this.LoadedBlueprint.Mapper.GetYLength(isv); int zM = this.LoadedBlueprint.Mapper.GetZLength(isv); for (int x = 0; x < xM; x++) { for (int y = 0; y < yM; y++) { for (int z = 0; z < zM; z++) { Material m = this.LoadedBlueprint.Mapper.GetMaterialAt(isv, x, y, z); if (m != Materials.Air) { if (!materialCounts.ContainsKey(m)) { materialCounts.Add(m, 0); } materialCounts[m] = materialCounts[m] + 1; } } } } StringBuilder sb = new StringBuilder(); sb.AppendLine("\"Material\",\"Block Count\",\"Full Stacks needed\""); sb.AppendLine("\"Total\"," + materialCounts.Values.Sum()); foreach (var kvp in materialCounts.OrderByDescending(x => x.Value)) { sb.AppendLine($"\"{kvp.Key.GetBlockNameAndData(isv).Replace("\"", "\"\"")}\",{kvp.Value},{kvp.Value / 64} stacks and {kvp.Value % 64} remaining blocks"); } File.WriteAllText(fName, sb.ToString()); } } else { this.exportSchematicToolStripMenuItem.Enabled = false; } }
static void Main(string[] args) { if (!args.Any()) { Application.ThreadException += MainForm.OnThreadException; AppDomain.CurrentDomain.UnhandledException += MainForm.OnUnhandledException; Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException); //SetLocaleByTextureSize(Constants.TextureSize); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new MainForm()); return; } else { Bitmap inputImage = null; string outputPath = null; string format = null; foreach (var arg in args) { string lArg = arg.ToLowerInvariant(); if (lArg.StartsWith("--options=")) { Options.Import(arg.Substring("--options=".Length)); } else if (lArg.StartsWith("--input=")) { inputImage = (Bitmap)Bitmap.FromFile(arg.Substring("--input=".Length)); } else if (lArg.StartsWith("--output=")) { outputPath = arg.Substring("--output=".Length); string ext = arg.Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries).LastOrDefault(); if (ext != null && format == null) { switch (ext.ToUpperInvariant()) { case "SCHEMATIC": case "PNG": case "SCHEM": format = ext.ToUpperInvariant(); break; } } } else if (lArg.StartsWith("--format=")) { format = arg.Substring("--format=".Length).ToUpperInvariant(); } else { if (lArg.StartsWith("--help")) { Console.WriteLine(@" ------------------ PixelStacker Help ---------------------------------------- The following options are available for CLI usage. If no CLI params are provided, the standard program GUI will be used instead. --format Specify the output format to use. Available values are: SCHEM, PNG Example: '--format=PNG' --output Where to output the file. Bitmap.Save({your value}) Example: '--output=C:\git\my-output-file.png' --input Where to load the file. Bitmap.FromFile({your value}) Example: '--input=C:\git\myfile.png' --options Path to the options.json file to use. If not provided, your most recently used settings will be applied. Example: '--options=C:\git\myfile.json' "); return; } } } if (string.IsNullOrWhiteSpace(format)) { Console.Error.WriteLine($"No value given for the --format argument. Valid values: [PNG, SCHEM]"); return; } if (string.IsNullOrWhiteSpace(outputPath)) { Console.Error.WriteLine($"No value given for the --output argument. Must be a full file path."); return; } else if (File.Exists(outputPath)) { Console.Error.WriteLine($"Warning, the output file already exists. It will be erased."); File.Delete(outputPath); } if (inputImage == null) { Console.Error.WriteLine($"File path for --input was invalid. File not found, or file could not be loaded."); return; } TaskManager.Get.TryTaskCatchCancelSync(() => { switch (format) { case "PNG": PngFormatter.writePNG(CancellationToken.None, outputPath, inputImage).ConfigureAwait(true).GetAwaiter().GetResult(); Console.WriteLine("Finished!"); break; case "SCHEM": Schem2Formatter.writeSchemFromImage(CancellationToken.None, outputPath, inputImage).ConfigureAwait(true).GetAwaiter().GetResult(); Console.WriteLine("Finished!"); break; } }); } }