Exemple #1
0
        protected override async Task <bool> Start(string tempInputFolderPath, string tempOutputFolderPath, string waifu2xCaffePath, string ffmpegPath)
        {
            _isRunning    = true;
            _tempInputDir = tempInputFolderPath;

            this._taskState = "extracting animation frames";
            InvokeTaskStateChanged();

            var extractResult = await AnimationFrameExtractor.ExtractFrames(InputFilePath, tempInputFolderPath, () => this._canceled);

            if (this._canceled)
            {
                Logger.Information("Terminating frame extraction for {AnimationPath} since this task has been cancelled", this.InputFilePath);
                _isRunning = false;
                return(false);
            }

            if (extractResult == null)
            {
                Logger.Error("An error occurred while extracting the animation frames for {InputFilePath} using {TaskExtractorTypeName}", this.InputFilePath, AnimationFrameExtractor.GetType().Name);
                _isRunning = false;
                return(false);
            }

            TaskQueue tasks = new TaskQueue();

            int            numCompleted    = 0;
            int            numStarted      = 0;
            Queue <string> remainingImages = new Queue <string>(extractResult.ExtractedFiles);

            var outputResolutionResolver = this.OutputResolutionResolver;

            ImageResolution inputImageResolution = null;
            ImageResolution previousResultOutputImageResolution = null;
            ImageResolution outputImageResolution;
            bool            canUseOldFrames = false;

            using (var firstFrame = Image.FromFile(extractResult.ExtractedFiles.First()))
            {
                inputImageResolution = new ImageResolution
                {
                    WidthInt  = firstFrame.Width,
                    HeightInt = firstFrame.Height
                };

                outputImageResolution = outputResolutionResolver.Resolve(inputImageResolution);
                var resolvedResolutionSize = outputImageResolution.Width * outputImageResolution.Height / 1e6;
                var maxResolution          = CompileProcess.MaxOutputResolutionMegapixels;
                if (resolvedResolutionSize > maxResolution) // Max output resolution is 8MP
                {
                    Logger.Warning("Output resolution for animation frame {InputAnimation} is too high for the {ImageCompiler} animation frame compiler at {OutputResolutionMegapixels} megapixels, limiting output size to {MaxCompileResolutionMegapixels} megapixels.", InputFilePath, CompileProcess.GetType().Name, resolvedResolutionSize, maxResolution);

                    outputResolutionResolver = new TargetPixelCountResolutionResolver(maxResolution * 1e6f);
                    outputImageResolution    = outputResolutionResolver.Resolve(inputImageResolution);
                }
            }

            //  Take into account how output images are resized to have even dimensions after upscaling
            outputImageResolution.WidthInt  += outputImageResolution.WidthInt % 2;
            outputImageResolution.HeightInt += outputImageResolution.HeightInt % 2;

            string firstPreviousResultOutputFramePath = Path.Combine(tempOutputFolderPath, Path.GetFileName(extractResult.ExtractedFiles.First()));

            if (File.Exists(firstPreviousResultOutputFramePath))
            {
                previousResultOutputImageResolution = ImageHelper.GetImageResolution(firstPreviousResultOutputFramePath);
            }

            if (previousResultOutputImageResolution != null &&
                previousResultOutputImageResolution.Distance(outputImageResolution) < 20)
            {
                canUseOldFrames = true;
            }


            List <string> outputImageFiles = new List <string>();


            do
            {
                tasks.QueueLength = MaxWaifuTaskThreads;

                while (tasks.CanQueueTask && remainingImages.Count > 0)
                {
                    this._taskState = $"{numCompleted}/{extractResult.ExtractedFiles.Count} frames complete, {MaxWaifuTaskThreads} at a time";
                    InvokeTaskStateChanged();

                    int frameIdx = ++numStarted;
                    Logger.Debug("Starting frame {@FrameIndex}/{@NumFrames}", frameIdx, extractResult.ExtractedFiles.Count);

                    string nextImgPath = remainingImages.Dequeue();
                    string fileName    = Path.GetFileName(nextImgPath);

                    string inputFramePath  = Path.Combine(tempInputFolderPath, fileName);
                    string outputFramePath = Path.Combine(tempOutputFolderPath, fileName);

                    outputImageFiles.Add(outputFramePath);

                    if (File.Exists(outputFramePath))
                    {
                        Logger.Information("Found old output frame {FrameIndex} for {OutputAnimationPath}", frameIdx, OutputFilePath);

                        if (!canUseOldFrames)
                        {
                            Logger.Information("Not using previous output frame {FrameIndex} for {OutputAnimationPath} since they do not match the current target resolution", frameIdx, this.OutputFilePath);

                            Logger.Information("Current output resolution: {@CurrentOutputResolution}", outputImageResolution);
                            Logger.Information("Previous output resolution: {@OldOutputResolution}", previousResultOutputImageResolution);

                            File.Delete(outputFramePath);
                        }
                        else
                        {
                            var outputFrameRes = ImageHelper.GetImageResolution(outputFramePath);
                            if (outputFrameRes != outputImageResolution)
                            {
                                Logger.Information("Using previous output frame {FrameIndex} for {OutputAnimationPath} but the image resolution is *slightly* off, resizing..");
                                ImageHelper.ResizeImage(outputFramePath, outputImageResolution);
                            }

                            numCompleted += 1;

                            continue;
                        }
                    }

                    var imageTask = new ImageTask(inputFramePath, outputFramePath, this.OutputResolutionResolver, this.ConvertMode);
                    imageTask.TaskCompleted += (task) =>
                    {
                        Interlocked.Increment(ref numCompleted);
                        tasks.TryCompleteTask(task);
                    };

                    imageTask.TaskFaulted += (task, reason) =>
                    {
                        Logger.Debug("ImageTask failed for frame {@FrameIndex}/{@NumFrames} while upscaling {@InputFile} to {@OutputFile}", frameIdx, extractResult.ExtractedFiles.Count, inputFramePath, outputFramePath);
                    };

                    imageTask.StartTask(tempInputFolderPath, tempOutputFolderPath, waifu2xCaffePath, ffmpegPath);

                    tasks.TryQueueTask(imageTask);
                }

                numSubTasks = tasks.RunningTasks.Count;

                await Task.Delay(10);
            } while (numCompleted < extractResult.ExtractedFiles.Count && !_canceled);



            if (this._canceled)
            {
                Logger.Debug("Canceling frame upconversion");

                foreach (var task in tasks.RunningTasks)
                {
                    task.CancelTask();
                }

                while (tasks.RunningTasks.Count > 0)
                {
                    await Task.Delay(1);
                }

                this._isRunning = false;
                Logger.Debug("AnimationTask has been canceled");
                return(false);
            }



            Logger.Information("Resizing output frames for {OutputAnimationPath} to have the same even dimensions");
            foreach (var image in outputImageFiles)
            {
                var imageSize = ImageHelper.GetImageResolution(image);
                if (imageSize == outputImageResolution)
                {
                    continue;
                }

                ImageHelper.ResizeImage(image, outputImageResolution);
            }


            this._taskState = $"Combining {extractResult.ExtractedFiles.Count} frames to {Path.GetExtension(OutputFilePath)}";
            InvokeTaskStateChanged();

            bool success = await CompileProcess.Run(InputFilePath, OutputFilePath, tempOutputFolderPath, extractResult.Fps);

            Cleanup();

            _isRunning = false;
            return(success);
        }
        internal override void GatherCompileInfo(App mainAppWithInfo)
        {
            ProjectProcess c;

            c = new ProjectProcess();
            if (!CompileProcess.CanOperate(mainAppWithInfo.TempPath))
            {
                string tempPath = Path.GetFullPath(Path.Combine(Path.GetTempPath(), "LuaSTG Editor/"));
                if (!Directory.Exists(tempPath))
                {
                    Directory.CreateDirectory(tempPath);
                }
                c.currentTempPath = tempPath;
            }
            else
            {
                c.currentTempPath = mainAppWithInfo.TempPath;
            }
            CompileProcess = c;

            c.projLuaPath = c.currentTempPath + "_editor_output.lua";

            c.source          = this;
            c.rootLuaPath     = c.currentTempPath + "root.lua";
            c.rootZipPackPath = c.currentTempPath + "pack.bat";

            c.projPath = "";
            if (!string.IsNullOrEmpty(DocPath))
            {
                c.projPath = Path.GetDirectoryName(DocPath);
            }

            c.projMetaPath = DocPath + ".meta";

            c.rootCode = "Include\'THlib.lua\'\nInclude\'_editor_output.lua\'";

            c.zipExePath    = mainAppWithInfo.ZipExecutablePath;
            c.luaSTGExePath = mainAppWithInfo.LuaSTGExecutablePath;

            if (!mainAppWithInfo.IsEXEPathSet)
            {
                throw new EXEPathNotSetException();
            }

            c.projName = Path.GetFileNameWithoutExtension(RawDocName);

            //Find mod name
            foreach (TreeNode t in TreeNodes[0].Children)
            {
                if (t is ProjSettings)
                {
                    if (!string.IsNullOrEmpty(t.attributes[0].AttrInput))
                    {
                        c.projName = t.attributes[0].AttrInput;
                    }
                    break;
                }
            }

            c.luaSTGFolder  = Path.GetDirectoryName(c.luaSTGExePath);
            c.targetZipPath = c.luaSTGFolder + "\\mod\\" + c.projName + ".zip";

            foreach (IDocumentWithMeta idwm in referencedDoc)
            {
                if (idwm is PlainDocumentData pdd)
                {
                    pdd.GatherCompileInfo(mainAppWithInfo);
                    c.fileProcess.Add(pdd.CompileProcess as PartialProjectProcess);
                    //MessageBox.Show(pdd.CompileProcess.GetType().ToString());
                }
                else if (idwm is VirtualDoc vd)
                {
                    string s = vd.DocPath;
                    //try
                    {
                        DocumentData newDoc = GetNewByExtension(Path.GetExtension(s), -1
                                                                , Path.GetFileNameWithoutExtension(s), s, true);
                        TreeNode t = newDoc.CreateNodeFromFile(s);
                        newDoc.TreeNodes.Add(t);
                        (newDoc as PlainDocumentData).parentProj = this;
                        newDoc.GatherCompileInfo(mainAppWithInfo);
                        c.fileProcess.Add(newDoc.CompileProcess as PartialProjectProcess);
                        //MessageBox.Show(newDoc.CompileProcess.GetType().ToString());
                    }
                    //catch { }
                }
            }
        }
Exemple #3
0
        public static void Run()
        {
            ConsoleColorState state = RC.ColorState;

            try
            {
                if (!Parser.HelpMode)
                {
                    #region Setup

                    if (VerboseSwitch.Defined)
                    {
                        RC.Verbosity = (ConsoleVerbosity)VerboseSwitch.Value;
                    }
                    else if (QuietSwitch.Defined)
                    {
                        RC.Verbosity = ConsoleVerbosity.Quiet;
                    }

                    if (WarningsAsErrors.Defined)
                    {
                        RC.WarningsAsErrors = WarningsAsErrors.Value;
                        RC.ReportWarnings   = WarningsAsErrors.Value;
                    }

                    RC.IsBuildMode = BuildSwitch.Defined;

                    RC.WriteLine(ConsoleVerbosity.Normal, "");
                    RC.WriteLine(ConsoleVerbosity.Minimal, ConsoleThemeColor.TitleText, Title);
                    //RC.WriteLine(ConsoleVerbosity.Minimal, "");

                    RC.ForegroundThemeColor = ConsoleThemeColor.Text;

                    #endregion

                    #region Check First Argument

                    if (Helper.IsNullOrEmpty(PathString.Value))
                    {
                        RC.WriteError(0101, Strings.Error_0101);
                        return;
                    }

                    #endregion

                    #region Create Process

                    CompileProcess compressionProcess = new CompileProcess();

                    compressionProcess.LogToConsole = true;

                    // ExecutableTypeMode
                    if (ConsoleSwitch.Defined)
                    {
                        compressionProcess.ExecutableTypeLookupMode = ExecutableTypeMode.Explicit;
                        compressionProcess.ExecutableType           = ConsoleSwitch.Value ? ExecutableType.Console : ExecutableType.Forms;
                    }
                    else
                    {
                        compressionProcess.ExecutableTypeLookupMode = ExecutableTypeMode.Reflected;
                        compressionProcess.ExecutableType           = ExecutableType.Console;
                    }

                    #endregion

                    #region Parse Optional Arguments

                    #region ToolsCsv Argument Switch Arround

                    if (ToolsCsv.Defined)
                    {
                        if (!OutputPath.Defined)
                        {
                            // If the output path argument has not been defined then manually set its value
                            // to the value of the first argument. e.g. 'rug-tool.exe'
                            OutputPath.Defined = true;
                            OutputPath.SetValue(PathString.Value);
                        }
                        else
                        {
                            // if the output path argument has been defined then the fist argument must be an
                            // additional .dll file so move the value to additional file list argument
                            FileList.Value.Add(PathString.Value);
                        }

                        // Zero the value of the fist argument
                        PathString.Reset();

                        if (compressionProcess.ExecutableTypeLookupMode != ExecutableTypeMode.Explicit)
                        {
                            compressionProcess.ExecutableTypeLookupMode = ExecutableTypeMode.Default;
                        }
                    }

                    #endregion

                    #region Additional Assembly Paths

                    List <string> assemblyPaths = new List <string>(FileList.Value.Count + 1);

                    if (PathString.Defined)
                    {
                        assemblyPaths.Add(PathString.Value);
                    }

                    foreach (object obj in FileList.Value)
                    {
                        assemblyPaths.Add(obj.ToString());
                    }

                    compressionProcess.Assemblys.AddRange(assemblyPaths);
                    compressionProcess.Compression.Files.AddRange(assemblyPaths);

                    #endregion

                    #region Output Path

                    string output;

                    if (OutputPath.Defined)
                    {
                        output = OutputPath.Value;
                    }
                    else if (PathString.Defined)
                    {
                        output = PathString.Value;
                    }
                    else
                    {
                        RC.WriteError(0104, Strings.Error_0104);
                        return;
                    }

                    #endregion

                    #region Initial Assembly Path

                    string initial;

                    if (PathString.Defined)
                    {
                        initial = PathString.Value;
                        initial = "/" + initial.Substring(initial.LastIndexOf('\\') + 1);
                    }
                    else
                    {
                        initial = null;
                    }

                    compressionProcess.InitialAssemblyPath = initial;

                    #endregion

                    #region Icon Path

                    string icon = "";

                    if (IconPath.Defined)
                    {
                        icon = IconPath.Value;
                    }

                    compressionProcess.IconFile = icon;

                    #endregion

                    #region AssemblyInfoPath

                    string assemblyinfoFile = null;

                    if (AssemblyInfoPath.Defined)
                    {
                        if (!File.Exists(AssemblyInfoPath.Value))
                        {
                            RC.WriteError(0102, string.Format(Strings.Error_0102, AssemblyInfoPath.Value));
                            return;
                        }

                        assemblyinfoFile = AssemblyInfoPath.Value;
                    }
                    else if (!PathString.Defined)
                    {
                        RC.WriteError(0106, Strings.Error_0106);
                        return;
                    }

                    compressionProcess.AssembyInfoSourceFilePath = assemblyinfoFile;

                    #endregion

                    #region Pass Arguments

                    bool passArgs = compressionProcess.ExecutableType == ExecutableType.Console ? true : false;

                    if (PassArgsSwitch.Defined)
                    {
                        passArgs = PassArgsSwitch.Value;
                    }

                    compressionProcess.PassArguments = passArgs;

                    #endregion

                    #region Decorate

                    compressionProcess.Decorate = DecorateSwitch.Defined;

                    #endregion

                    #region Protect Zip

                    compressionProcess.Compression.Protected = ProtectZipSwitch.Defined;
                    compressionProcess.Compression.Password  = ProtectZipSwitch.Value;

                    #endregion

                    #region Build Tools

                    foreach (string toolString in ToolsCsv.Value)
                    {
                        int index = toolString.IndexOf(':');

                        if (index < 1)
                        {
                            RC.WriteError(0105, string.Format(Strings.Error_0105, toolString));
                            return;
                        }

                        string toolName = toolString.Substring(0, index);
                        string toolPath = toolString.Substring(index + 1);

                        compressionProcess.Tools.Add(toolName, toolPath);
                        compressionProcess.Compression.Files.Add(toolPath);
                    }

                    #endregion

                    #endregion

                    #region Execute Bundle and Compile

                    RC.ForegroundThemeColor = ConsoleThemeColor.Text;

                    compressionProcess.Compression.CreatePackage();

                    #endregion

                    if (compressionProcess.RunProcess(output))
                    {
                        #region Print Size Summary

                        RC.WriteLine(ConsoleVerbosity.Verbose, ConsoleThemeColor.TitleText, "\n\n" + Strings.Text_FinalSummary);
                        RC.WriteLine(ConsoleThemeColor.SubText, " " + new string(ConsoleChars.SingleLines[1], 41));

                        Rug.Cmd.CmdHelper.WriteInfoToConsole(Strings.Text_UncompressedSize, CmdHelper.GetMemStringFromBytes(compressionProcess.InitialSize, true), RC.Theme[ConsoleThemeColor.Text]);

                        if (compressionProcess.IconFileSize > 0)
                        {
                            Rug.Cmd.CmdHelper.WriteInfoToConsole(Strings.Text_IconFileSize, CmdHelper.GetMemStringFromBytes(compressionProcess.IconFileSize, true), RC.Theme[ConsoleThemeColor.Text]);
                            Rug.Cmd.CmdHelper.WriteInfoToConsole(Strings.Text_TotalSize, CmdHelper.GetMemStringFromBytes(compressionProcess.InitialSize + compressionProcess.IconFileSize, true), RC.Theme[ConsoleThemeColor.Text]);
                        }

                        Rug.Cmd.CmdHelper.WriteInfoToConsole(Strings.Text_StartupOverhead, CmdHelper.GetMemStringFromBytes(compressionProcess.OverheadSize, true), RC.Theme[ConsoleThemeColor.Text]);

                        ConsoleThemeColor compColor = ConsoleThemeColor.Text;

                        if (compressionProcess.FinalFileSize < compressionProcess.TotalInitialFileSize / 2)
                        {
                            compColor = ConsoleThemeColor.TextGood;
                        }
                        else if (compressionProcess.FinalFileSize < (compressionProcess.TotalInitialFileSize / 4) * 3)
                        {
                            compColor = ConsoleThemeColor.SubTextGood;
                        }
                        else if ((compressionProcess.FinalFileSize >= ((compressionProcess.TotalInitialFileSize / 4) * 3)) &&
                                 (compressionProcess.FinalFileSize < compressionProcess.TotalInitialFileSize))
                        {
                            compColor = ConsoleThemeColor.SubTextNutral;
                        }
                        else if (compressionProcess.FinalFileSize == compressionProcess.TotalInitialFileSize)
                        {
                            compColor = ConsoleThemeColor.Text;
                        }
                        else if (compressionProcess.FinalFileSize > compressionProcess.TotalInitialFileSize)
                        {
                            compColor = ConsoleThemeColor.TextBad;
                        }

                        Rug.Cmd.CmdHelper.WriteInfoToConsole(Strings.Text_FinalSize, CmdHelper.GetMemStringFromBytes(compressionProcess.FinalFileSize, true), RC.Theme[compColor]);

                        RC.WriteLine(ConsoleThemeColor.SubText, " " + new string(ConsoleChars.SingleLines[1], 41));

                        RC.Write(ConsoleVerbosity.Minimal, ConsoleThemeColor.TitleText, " " + Strings.Text_OverallCompression);

                        #endregion

                        if (compressionProcess.FinalFileSize > 0)
                        {
                            #region Print Final Success Message

                            string valueString = ((100 - (((double)compressionProcess.FinalFileSize / (double)compressionProcess.TotalInitialFileSize) * 100.0)).ToString("N2") + "%");

                            RC.Write(ConsoleVerbosity.Minimal, ConsoleThemeColor.SubText, " :".PadRight(22 - valueString.Length, '.'));
                            RC.WriteLine(ConsoleVerbosity.Minimal, compColor, valueString);

                            int offset = 6;

                            if (compColor == ConsoleThemeColor.TextBad)
                            {
                                offset += 3;
                                RC.WriteLine("");
                                RC.WriteWarning(0103, " " + Strings.Error_0103);
                            }

                            if (RC.CanManipulateBuffer && (int)RC.Verbosity >= (int)ConsoleVerbosity.Normal)
                            {
                                Rug.Cmd.CmdHelper.WriteRuglandLogo(48, RC.CursorTop - offset, 3, 2, false, ConsoleShade.Opaque);
                            }

                            #endregion
                        }
                        else
                        {
                            #region The Final Size Is Invlaid So Print A Message

                            RC.Write(ConsoleVerbosity.Minimal, ConsoleThemeColor.SubText, new string('.', 19 - Strings.Text_Invalid.Length));
                            RC.WriteLine(ConsoleVerbosity.Minimal, ConsoleThemeColor.ErrorColor1, Strings.Text_Invalid);

                            #endregion
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                RC.WriteException(0199, ex);
            }
            finally
            {
                #region Reset The Color State

                RC.ColorState = state;
                RC.WriteLine(ConsoleVerbosity.Minimal, "");

                #endregion
            }
        }