static void SaveImage(int percentage, RenderTask task) { if (task.Exception != null) { Console.WriteLine("{0}: Error rendering image:", task.RelativeName); Console.Error.WriteLine("{0}: {1}", task.Exception.GetType().Name, task.Exception); } else { if (!p.AlwaysOverwrite && File.Exists(task.TargetPath)) { Console.WriteLine(); if (!ShowYesNo("File \"{0}\" already exists. Overwrite?", Path.GetFileName(task.TargetPath))) { Console.WriteLine("[{0}%] {1}: Skipped (image file already exists)", percentage.ToString(CultureInfo.InvariantCulture).PadLeft(3), task.RelativeName); return; } } using (FileStream fs = File.OpenWrite(task.TargetPath)) { fs.Write(task.Result, 0, task.Result.Length); } Console.WriteLine("[{0}%] {1}: ok", percentage.ToString(CultureInfo.InvariantCulture).PadLeft(3), task.RelativeName); } }
void RenderLoop() { renderer = MakeRenderer(); using (MemoryStream ms = new MemoryStream()) { // loop terminates with the rest of the program (this is a background thread) while (true) { // wait (block) until a map is available for drawing RenderTask task = inQueue.WaitDequeue(); try { // render the map IsoCatResult result = renderer.Draw(task.Map); task.Map = null; // crop image (if needed) Image image; if (p.Uncropped) { image = result.Bitmap; } else { image = result.Bitmap.Clone(result.CropRectangle, result.Bitmap.PixelFormat); result.Bitmap.Dispose(); } // encode image if (p.ExportFormat.Equals(ImageFormat.Jpeg)) { EncoderParameters encoderParams = new EncoderParameters(); encoderParams.Param[0] = new EncoderParameter(Encoder.Quality, p.JpegQuality); image.Save(ms, p.ImageEncoder, encoderParams); } else if (p.ExportFormat.Equals(ImageFormat.Gif)) { OctreeQuantizer q = new OctreeQuantizer(255, 8); image = q.Quantize(image); image.Save(ms, p.ExportFormat); } else { image.Save(ms, p.ExportFormat); } image.Dispose(); // store result as a byte[] task.Result = ms.ToArray(); } catch (Exception ex) { task.Exception = ex; } // send stack to the results queue outQueue.Enqueue(task); ms.SetLength(0); } } }
static bool LoadMap(RenderTask task) { try { Map map; if (p.MapImporter != null) { map = p.MapImporter.Load(task.MapPath); } else { map = MapUtility.Load(task.MapPath, p.TryHard); } task.Map = map; return(true); } catch (NoMapConverterFoundException) { Console.WriteLine("{0}: Skipped (no compatible converter found).", task.RelativeName); return(false); } catch (Exception ex) { Console.WriteLine("{0}: Error loading map file:", task.RelativeName); Console.Error.WriteLine(ex); return(false); } }
static void SaveImage(int percentage, RenderTask task) { if (task.Exception != null) { Console.WriteLine("{0}: Error rendering image:", task.RelativeName); Console.Error.WriteLine("{0}: {1}", task.Exception.GetType().Name, task.Exception); } else { if (p.OverwritePolicy == OverwritePolicy.Ask && File.Exists(task.TargetPath)) { Console.WriteLine(); if (!ConsoleUtil.ShowYesNo("File \"{0}\" already exists. Overwrite?", Path.GetFileName(task.TargetPath))) { Console.WriteLine("[{0}%] {1}: Skipped (image file already exists)", percentage.ToString(CultureInfo.InvariantCulture).PadLeft(3), task.RelativeName); return; } } using (FileStream fs = File.OpenWrite(task.TargetPath)) { fs.Write(task.Result, 0, task.Result.Length); } Console.WriteLine("[{0}%] {1}: ok", percentage.ToString(CultureInfo.InvariantCulture).PadLeft(3), task.RelativeName); } }
static bool LoadMap(RenderTask task) { try { Map map; if (p.MapImporter != null) { map = p.MapImporter.Load(task.MapPath); } else { map = MapUtility.Load(task.MapPath, p.TryHard); } task.Map = map; return true; } catch (NoMapConverterFoundException) { Console.WriteLine("{0}: Skipped (no compatible converter found).", task.RelativeName); return false; } catch (Exception ex) { Console.WriteLine("{0}: Error loading map file:", task.RelativeName); Console.Error.WriteLine(ex); return false; } }
static int Main(string[] args) { Logger.Logged += OnLogged; Logger.DisableFileLogging(); ReturnCode optionParsingResult = ParseOptions(args); if (optionParsingResult != ReturnCode.Success) { return((int)optionParsingResult); } // parse importer name if (importerName != null && !importerName.Equals("auto", StringComparison.OrdinalIgnoreCase)) { MapFormat importFormat; if (!EnumUtil.TryParse(importerName, out importFormat, true)) { Console.Error.WriteLine("Unsupported importer \"{0}\"", importerName); PrintUsage(); return((int)ReturnCode.UnrecognizedImporter); } p.MapImporter = MapUtility.GetImporter(importFormat); if (p.MapImporter == null) { Console.Error.WriteLine("Loading from \"{0}\" is not supported", importFormat); PrintUsage(); return((int)ReturnCode.UnsupportedLoadFormat); } } // check input paths bool hadFile = false, hadDir = false; foreach (string inputPath in p.InputPathList) { if (hadDir) { Console.Error.WriteLine("MapRenderer: Only one directory may be specified at a time."); return((int)ReturnCode.ArgumentError); } // check if input path exists, and if it's a file or directory try { if (File.Exists(inputPath)) { hadFile = true; } else if (Directory.Exists(inputPath)) { hadDir = true; if (hadFile) { Console.Error.WriteLine("MapRenderer: Cannot mix directories and files in input."); return((int)ReturnCode.ArgumentError); } p.DirectoryMode = true; if (!p.OutputDirGiven) { p.OutputDirName = inputPath; } } else { Console.Error.WriteLine("MapRenderer: Cannot locate \"{0}\"", inputPath); return((int)ReturnCode.InputPathNotFound); } } catch (Exception ex) { Console.Error.WriteLine("MapRenderer: {0}: {1}", ex.GetType().Name, ex.Message); return((int)ReturnCode.PathError); } } // initialize image encoder ImageCodecInfo[] codecs = ImageCodecInfo.GetImageDecoders(); p.ImageEncoder = codecs.FirstOrDefault(codec => codec.FormatID == p.ExportFormat.Guid); if (p.ImageEncoder == null) { Console.Error.WriteLine("MapRenderer: Specified image encoder is not supported."); return((int)ReturnCode.UnsupportedSaveFormat); } // check recursive flag if (p.Recursive && !p.DirectoryMode) { Console.Error.WriteLine("MapRenderer: Recursive flag is given, but input is not a directory."); return((int)ReturnCode.ArgumentError); } // check input filter if (p.InputFilter != null && !p.DirectoryMode) { Console.Error.WriteLine("MapRenderer: Filter param is given, but input is not a directory."); return((int)ReturnCode.ArgumentError); } // check regex filter if (p.UseRegex) { try { p.FilterRegex = new Regex(p.InputFilter); } catch (ArgumentException ex) { Console.Error.WriteLine("MapRenderer: Cannot parse filter regex: {0}", ex.Message); return((int)ReturnCode.ArgumentError); } } // check if output dir exists; create it if needed if (p.OutputDirName != null) { try { if (!Directory.Exists(p.OutputDirName)) { Directory.CreateDirectory(p.OutputDirName); } } catch (Exception ex) { Console.Error.WriteLine("MapRenderer: Error checking output directory: {0}: {1}", ex.GetType().Name, ex.Message); } } Console.Write("Counting files... "); // process inputs, one path at a time foreach (string inputPath in p.InputPathList) { ProcessInputPath(inputPath); } int totalFiles = InputPaths.Count; Console.WriteLine(totalFiles); if (totalFiles > 0) { int actualThreadCount = Math.Min(p.ThreadCount, InputPaths.Count); RenderWorker[] workers = new RenderWorker[actualThreadCount]; for (int i = 0; i < workers.Length; i++) { workers[i] = new RenderWorker(WorkQueue, ResultQueue, p); workers[i].Start(); } int inputsProcessed = 0; int resultsProcessed = 0; while (resultsProcessed < totalFiles) { if (inputsProcessed < totalFiles) { // load and enqueue another map for rendering if (WorkQueue.Count < actualThreadCount) { RenderTask newTask = InputPaths.Dequeue(); if (LoadMap(newTask)) { WorkQueue.Enqueue(newTask); } else { resultsProcessed++; } inputsProcessed++; } else { Thread.Sleep(1); } // try dequeue a rendered image for saving RenderTask resultTask; if (ResultQueue.TryDequeue(out resultTask)) { int percent = (resultsProcessed * 100 + 100) / totalFiles; SaveImage(percent, resultTask); resultsProcessed++; } } else { // no more maps to load -- just wait for results int percent = (resultsProcessed * 100 + 100) / totalFiles; SaveImage(percent, ResultQueue.WaitDequeue()); resultsProcessed++; } } } Console.WriteLine("MapRenderer: Processed {0} files in {1:0.00} seconds", totalFiles, DateTime.UtcNow.Subtract(StartTime).TotalSeconds); return((int)ReturnCode.Success); }