UNPKG

waifu2x

Version:

2x upscaling of images with waifu2x

886 lines 82.8 kB
"use strict"; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (_) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; var __spreadArrays = (this && this.__spreadArrays) || function () { for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length; for (var r = Array(s), k = 0, i = 0; i < il; i++) for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) r[k] = a[j]; return r; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; exports.__esModule = true; var util_1 = __importDefault(require("util")); var fs_1 = __importDefault(require("fs")); var image_size_1 = require("image-size"); var fluent_ffmpeg_1 = __importDefault(require("fluent-ffmpeg")); var path_1 = __importDefault(require("path")); var child_process_1 = __importDefault(require("child_process")); var gif_encoder_1 = __importDefault(require("gif-encoder")); var get_pixels_1 = __importDefault(require("get-pixels")); var gif_frames_1 = __importDefault(require("gif-frames")); // @ts-ignore var pdfkit_1 = __importDefault(require("@react-pdf/pdfkit")); var pdf_images_1 = require("./pdf-images"); var rife_fps_1 = __importDefault(require("rife-fps")); var exec = util_1["default"].promisify(child_process_1["default"].exec); var Waifu2x = /** @class */ (function () { function Waifu2x() { } Waifu2x.processes = []; Waifu2x.addProcess = function (process) { Waifu2x.processes.push(process); }; Waifu2x.removeProcess = function (process) { Waifu2x.processes = Waifu2x.processes.filter(function (p) { return p.pid !== process.pid; }); }; Waifu2x.chmod777 = function (waifu2xPath, webpPath, esrganPath, cuganPath, anime4kPath, rifePath) { if (process.platform === "win32") return; var waifu2x = waifu2xPath ? path_1["default"].normalize(waifu2xPath).replace(/\\/g, "/") : path_1["default"].join(__dirname, "../waifu2x"); var esrgan = esrganPath ? path_1["default"].normalize(esrganPath).replace(/\\/g, "/") : path_1["default"].join(__dirname, "../real-esrgan"); var cugan = cuganPath ? path_1["default"].normalize(cuganPath).replace(/\\/g, "/") : path_1["default"].join(__dirname, "../real-cugan"); var anime4k = anime4kPath ? path_1["default"].normalize(anime4kPath).replace(/\\/g, "/") : path_1["default"].join(__dirname, "../anime4k"); var webp = webpPath ? path_1["default"].normalize(webpPath).replace(/\\/g, "/") : path_1["default"].join(__dirname, "../webp"); fs_1["default"].chmodSync(waifu2x + "/waifu2x-ncnn-vulkan.app", "777"); fs_1["default"].chmodSync(esrgan + "/realesrgan-ncnn-vulkan.app", "777"); fs_1["default"].chmodSync(cugan + "/realcugan-ncnn-vulkan.app", "777"); fs_1["default"].chmodSync(anime4k + "/Anime4KCPP_CLI.app", "777"); fs_1["default"].chmodSync(webp + "/anim_dump.app", "777"); fs_1["default"].chmodSync(webp + "/cwebp.app", "777"); fs_1["default"].chmodSync(webp + "/dwebp.app", "777"); fs_1["default"].chmodSync(webp + "/img2webp.app", "777"); fs_1["default"].chmodSync(webp + "/webpmux.app", "777"); rife_fps_1["default"].chmod777(rifePath); }; Waifu2x.parseFilename = function (source, dest, rename) { var _a = ["", ""], image = _a[0], folder = _a[1]; if (!dest) { image = null; folder = null; } else if (path_1["default"].basename(dest).includes(".")) { image = path_1["default"].basename(dest); folder = dest.replace(image, ""); } else { image = null; folder = dest; } if (!folder) folder = "./"; if (folder.endsWith("/")) folder = folder.slice(0, -1); if (!image) { image = "" + path_1["default"].basename(source, path_1["default"].extname(source)) + rename + path_1["default"].extname(source); } return { folder: folder, image: image }; }; Waifu2x.recursiveRename = function (folder, fileNames, rename) { var _a; if (folder.endsWith("/")) folder = folder.slice(0, -1); for (var i = 0; i < fileNames.length; i++) { var fullPath = folder + "/" + fileNames[i]; var check = fs_1["default"].statSync(fullPath); if (check.isDirectory()) { var subFiles = fs_1["default"].readdirSync(fullPath); Waifu2x.recursiveRename(fullPath, subFiles, rename); } else { var pathSplit = fileNames[i].split("."); var newName = ((_a = pathSplit === null || pathSplit === void 0 ? void 0 : pathSplit[0].split("_")) === null || _a === void 0 ? void 0 : _a[0]) + rename; var newPath = folder + "/" + newName + "." + pathSplit.pop(); fs_1["default"].renameSync(fullPath, newPath); } } }; Waifu2x.parseDest = function (source, dest, options) { options = __assign({}, options); if (!dest) dest = "./"; if (options.rename === undefined) options.rename = "2x"; var _a = Waifu2x.parseFilename(source, dest, options.rename), folder = _a.folder, image = _a.image; if (!path_1["default"].isAbsolute(source) && !path_1["default"].isAbsolute(dest)) { var local = __dirname.includes("node_modules") ? path_1["default"].join(__dirname, "../../../") : path_1["default"].join(__dirname, ".."); folder = path_1["default"].join(local, folder); } return path_1["default"].normalize(folder + "/" + image).replace(/\\/g, "/"); }; Waifu2x.timeout = function (ms) { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) { return [2 /*return*/, new Promise(function (resolve) { return setTimeout(resolve, ms); })]; }); }); }; Waifu2x.convertToWebp = function (source, dest, webpPath, quality) { return __awaiter(void 0, void 0, void 0, function () { var absolute, program, command, child; return __generator(this, function (_a) { switch (_a.label) { case 0: if (!quality) quality = 75; absolute = webpPath ? path_1["default"].normalize(webpPath).replace(/\\/g, "/") : path_1["default"].join(__dirname, "../webp"); program = "cd \"" + absolute + "\" && ./cwebp.exe"; if (process.platform === "darwin") program = "cd \"" + absolute + "\" && ./cwebp.app"; if (process.platform === "linux") program = "cd \"" + absolute + "\" && ./cwebp"; command = program + " -q " + quality + " \"" + source + "\" -o \"" + dest + "\""; child = child_process_1["default"].exec(command); Waifu2x.addProcess(child); return [4 /*yield*/, new Promise(function (resolve, reject) { child.on("close", function () { Waifu2x.removeProcess(child); resolve(); }); })]; case 1: _a.sent(); return [2 /*return*/, dest]; } }); }); }; Waifu2x.convertFromWebp = function (source, dest, webpPath) { return __awaiter(void 0, void 0, void 0, function () { var absolute, program, command, child, error; return __generator(this, function (_a) { switch (_a.label) { case 0: absolute = webpPath ? path_1["default"].normalize(webpPath).replace(/\\/g, "/") : path_1["default"].join(__dirname, "../webp"); program = "cd \"" + absolute + "\" && ./dwebp.exe"; if (process.platform === "darwin") program = "cd \"" + absolute + "\" && ./dwebp.app"; if (process.platform === "linux") program = "cd \"" + absolute + "\" && ./dwebp"; command = program + " \"" + source + "\" -o \"" + dest + "\""; child = child_process_1["default"].exec(command); Waifu2x.addProcess(child); error = ""; return [4 /*yield*/, new Promise(function (resolve, reject) { child.stderr.on("data", function (chunk) { return error += chunk; }); child.on("close", function () { Waifu2x.removeProcess(child); resolve(); }); })]; case 1: _a.sent(); if (error.includes("animated WebP")) return [2 /*return*/, Promise.reject(error)]; return [2 /*return*/, dest]; } }); }); }; Waifu2x.upscaleImage = function (source, dest, options, progress) { return __awaiter(void 0, void 0, void 0, function () { var sourcePath, _a, folder, image, local, destPath, absolute, buffer, dimensions, error_1, command, program, ext, program, ext, program, ext, program, python, program, child, stopped, poll, error; return __generator(this, function (_b) { switch (_b.label) { case 0: options = __assign({}, options); if (!dest) dest = "./"; if (!options.upscaler) options.upscaler = "waifu2x"; sourcePath = source; if (options.rename === undefined) options.rename = "2x"; _a = Waifu2x.parseFilename(source, dest, options.rename), folder = _a.folder, image = _a.image; if (!fs_1["default"].existsSync(folder)) fs_1["default"].mkdirSync(folder, { recursive: true }); local = __dirname.includes("node_modules") ? path_1["default"].join(__dirname, "../../../") : path_1["default"].join(__dirname, ".."); if (!path_1["default"].isAbsolute(source) && !path_1["default"].isAbsolute(dest)) { sourcePath = path_1["default"].join(local, source); folder = path_1["default"].join(local, folder); } destPath = path_1["default"].join(folder, image).replace(/\\/g, "/"); absolute = ""; if (options.upscaler === "waifu2x") { absolute = options.waifu2xPath ? path_1["default"].normalize(options.waifu2xPath).replace(/\\/g, "/") : path_1["default"].join(__dirname, "../waifu2x"); } else if (options.upscaler === "real-esrgan") { absolute = options.esrganPath ? path_1["default"].normalize(options.esrganPath).replace(/\\/g, "/") : path_1["default"].join(__dirname, "../real-esrgan"); } else if (options.upscaler === "real-cugan") { absolute = options.cuganPath ? path_1["default"].normalize(options.cuganPath).replace(/\\/g, "/") : path_1["default"].join(__dirname, "../real-cugan"); } else if (options.upscaler === "anime4k") { absolute = options.anime4kPath ? path_1["default"].normalize(options.anime4kPath).replace(/\\/g, "/") : path_1["default"].join(__dirname, "../anime4k"); } else { absolute = options.scriptsPath ? path_1["default"].normalize(options.scriptsPath).replace(/\\/g, "/") : path_1["default"].join(__dirname, "../scripts"); } buffer = fs_1["default"].readFileSync(sourcePath); dimensions = image_size_1.imageSize(buffer); if (!(dimensions.type === "webp")) return [3 /*break*/, 4]; _b.label = 1; case 1: _b.trys.push([1, 3, , 4]); return [4 /*yield*/, Waifu2x.convertFromWebp(sourcePath, destPath, options.webpPath)]; case 2: _b.sent(); sourcePath = destPath; return [3 /*break*/, 4]; case 3: error_1 = _b.sent(); return [2 /*return*/, Promise.reject("Animated webp: " + error_1)]; case 4: command = ""; if (options.upscaler === "waifu2x") { program = "cd \"" + absolute + "\" && waifu2x-ncnn-vulkan.exe"; if (process.platform === "darwin") program = "cd \"" + absolute + "\" && ./waifu2x-ncnn-vulkan.app"; if (process.platform === "linux") program = "cd \"" + absolute + "\" && ./waifu2x-ncnn-vulkan"; ext = path_1["default"].extname(source).replace(".", ""); command = program + " -i \"" + sourcePath + "\" -o \"" + destPath + "\" -f " + ext; if (options.scale) command += " -s " + options.scale; if (options.threads) command += " -j " + options.threads + ":" + options.threads + ":" + options.threads; if (options.waifu2xModel) command += " -m \"" + options.waifu2xModel + "\""; } else if (options.upscaler === "real-esrgan") { program = "cd \"" + absolute + "\" && realesrgan-ncnn-vulkan.exe"; if (process.platform === "darwin") program = "cd \"" + absolute + "\" && ./realesrgan-ncnn-vulkan.app"; if (process.platform === "linux") program = "cd \"" + absolute + "\" && ./realesrgan-ncnn-vulkan"; ext = path_1["default"].extname(source).replace(".", ""); command = program + " -i \"" + sourcePath + "\" -o \"" + destPath + "\" -f " + ext + " -n " + (options.scale === 4 ? "realesrgan-x4plus-anime" : "realesr-animevideov3"); if (options.scale) command += " -s " + options.scale; if (options.threads) command += " -j " + options.threads + ":" + options.threads + ":" + options.threads; } else if (options.upscaler === "real-cugan") { program = "cd \"" + absolute + "\" && realcugan-ncnn-vulkan.exe"; if (process.platform === "darwin") program = "cd \"" + absolute + "\" && ./realcugan-ncnn-vulkan.app"; if (process.platform === "linux") program = "cd \"" + absolute + "\" && ./realcugan-ncnn-vulkan"; ext = path_1["default"].extname(source).replace(".", ""); command = program + " -i \"" + sourcePath + "\" -o \"" + destPath + "\" -f " + ext; if (options.noise) { if (Number(options.scale) > 2) { if (Number(options.noise) === 2) options.noise = 3; if (Number(options.noise) === 1) options.noise = 0; } command += " -n " + options.noise; } if (options.scale) command += " -s " + options.scale; if (options.threads) command += " -j " + options.threads + ":" + options.threads + ":" + options.threads; } else if (options.upscaler === "anime4k") { program = "cd \"" + absolute + "\" && Anime4KCPP_CLI.exe"; if (process.platform === "darwin") program = "cd \"" + absolute + "\" && ./Anime4KCPP_CLI.app"; if (process.platform === "linux") program = "cd \"" + absolute + "\" && ./Anime4KCPP_CLI"; command = program + " -i \"" + sourcePath + "\" -o \"" + destPath + "\" -A"; if (options.scale) command += " -z " + options.scale; } else { python = process.platform === "darwin" ? "PYTORCH_ENABLE_MPS_FALLBACK=1 /usr/local/bin/python3" : "python3"; program = "cd \"" + absolute + "\" && " + python + " upscale.py"; command = program + " -i \"" + sourcePath + "\" -o \"" + destPath + "\" -m \"" + options.upscaler + "\""; if (options.pythonDownscale && Number(options.pythonDownscale > 0)) command += " -d " + options.pythonDownscale; } child = child_process_1["default"].exec(command); Waifu2x.addProcess(child); stopped = false; poll = function () { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { case 0: if (progress()) { stopped = true; child.stdio.forEach(function (s) { return s.destroy(); }); child.kill("SIGINT"); } return [4 /*yield*/, Waifu2x.timeout(1000)]; case 1: _a.sent(); if (!stopped) poll(); return [2 /*return*/]; } }); }); }; if (progress) poll(); error = ""; return [4 /*yield*/, new Promise(function (resolve, reject) { child.stderr.on("data", function (chunk) { if (options.upscaler === "real-esrgan") { var percent = Number(chunk.replace("%", "").replace(",", ".")); if (!Number.isNaN(percent)) progress === null || progress === void 0 ? void 0 : progress(percent); } }); child.on("close", function () { stopped = true; Waifu2x.removeProcess(child); resolve(); }); })]; case 5: _b.sent(); if (error) return [2 /*return*/, Promise.reject(error)]; if (!(path_1["default"].extname(destPath) === ".webp")) return [3 /*break*/, 7]; return [4 /*yield*/, Waifu2x.convertToWebp(destPath, destPath, options.webpPath, options.jpgWebpQuality)]; case 6: _b.sent(); _b.label = 7; case 7: return [2 /*return*/, path_1["default"].normalize(destPath).replace(/\\/g, "/")]; } }); }); }; Waifu2x.searchFiles = function (dir, recursive) { if (recursive === void 0) { recursive = false; } var files = fs_1["default"].readdirSync(dir); var fileMap = files.map(function (file) { return dir + "/" + file; }).filter(function (f) { return fs_1["default"].lstatSync(f).isFile(); }); if (!recursive) return fileMap; var dirMap = files.map(function (file) { return dir + "/" + file; }).filter(function (f) { return fs_1["default"].lstatSync(f).isDirectory(); }); return fileMap.concat(dirMap.flatMap(function (dirEntry) { return Waifu2x.searchFiles(dirEntry, true); })); }; Waifu2x.upscaleImages = function (sourceFolder, destFolder, options, progress) { return __awaiter(void 0, void 0, void 0, function () { var fileMap, retArray, cancel, counter, total, queue, i; return __generator(this, function (_a) { switch (_a.label) { case 0: options = __assign({}, options); if (sourceFolder.endsWith("/")) sourceFolder = sourceFolder.slice(0, -1); fileMap = Waifu2x.searchFiles(sourceFolder, options === null || options === void 0 ? void 0 : options.recursive); if (!options.limit) options.limit = fileMap.length; retArray = []; cancel = false; counter = 1; total = fileMap.length; queue = []; if (!options.parallelFrames) options.parallelFrames = 1; while (fileMap.length) queue.push(fileMap.splice(0, options.parallelFrames)); if (progress) progress(0, total); i = 0; _a.label = 1; case 1: if (!(i < queue.length)) return [3 /*break*/, 4]; return [4 /*yield*/, Promise.all(queue[i].map(function (f) { return __awaiter(void 0, void 0, void 0, function () { var ret, stop; return __generator(this, function (_a) { switch (_a.label) { case 0: if (counter >= options.limit) cancel = true; return [4 /*yield*/, Waifu2x.upscaleImage(f, destFolder, options)]; case 1: ret = _a.sent(); retArray.push(ret); stop = progress ? progress(counter++, total) : false; if (stop) cancel = true; return [2 /*return*/]; } }); }); }))]; case 2: _a.sent(); if (cancel) return [3 /*break*/, 4]; _a.label = 3; case 3: i++; return [3 /*break*/, 1]; case 4: return [2 /*return*/, retArray]; } }); }); }; Waifu2x.parseTransparentColor = function (color) { return Number("0x" + color.replace(/^#/, "")); }; Waifu2x.encodeGIF = function (files, delays, dest, quality, transparentColor) { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) { if (!quality) quality = 10; return [2 /*return*/, new Promise(function (resolve) { var dimensions = image_size_1.imageSize(files === null || files === void 0 ? void 0 : files[0]); var gif = new gif_encoder_1["default"](dimensions.width, dimensions.height, { highWaterMark: 5 * 1024 * 1024 }); var file = fs_1["default"].createWriteStream(dest); gif.pipe(file); gif.setQuality(quality); gif.setRepeat(0); gif.writeHeader(); if (transparentColor) gif.setTransparent(Waifu2x.parseTransparentColor(transparentColor)); var counter = 0; var addToGif = function (frames) { get_pixels_1["default"](frames[counter], function (err, pixels) { if (err) throw err; gif.setDelay(10 * delays[counter]); gif.addFrame(pixels.data); if (counter >= frames.length - 1) { gif.finish(); } else { counter++; addToGif(files); } }); }; addToGif(files); gif.on("end", resolve); })]; }); }); }; Waifu2x.awaitStream = function (writeStream) { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) { return [2 /*return*/, new Promise(function (resolve, reject) { writeStream.on("finish", resolve); writeStream.on("error", reject); })]; }); }); }; Waifu2x.newDest = function (dest) { var i = 1; var newDest = dest; while (fs_1["default"].existsSync(newDest)) { newDest = dest + "_" + i; i++; } return newDest; }; Waifu2x.findMatchingSettings = function (dest, options) { var i = 1; var newDest = dest; if (fs_1["default"].existsSync(newDest)) { var settings = JSON.parse(fs_1["default"].readFileSync(newDest + "/settings.json", "utf8")); if (JSON.stringify(settings) === JSON.stringify(options)) { return newDest; } } newDest = dest + "_" + i; while (fs_1["default"].existsSync(newDest) || i < 10) { if (fs_1["default"].existsSync(newDest)) { var settings = JSON.parse(fs_1["default"].readFileSync(newDest + "/settings.json", "utf8")); if (JSON.stringify(settings) === JSON.stringify(options)) { return newDest; } } i++; newDest = dest + "_" + i; } return null; }; Waifu2x.upscaleGIF = function (source, dest, options, progress) { return __awaiter(void 0, void 0, void 0, function () { function downloadFrames(frames) { return __awaiter(this, void 0, void 0, function () { var promiseArray, i, writeStream; return __generator(this, function (_a) { promiseArray = []; for (i = 0; i < frames.length; i += step) { writeStream = fs_1["default"].createWriteStream(frameDest + "/frame" + i + "." + frameExt); frames[i].getImage().pipe(writeStream); frameArray.push(frameDest + "/frame" + i + "." + frameExt); delayArray.push(frames[i].frameInfo.delay); promiseArray.push(Waifu2x.awaitStream(writeStream)); } return [2 /*return*/, Promise.all(promiseArray)]; }); }); } var frameExt, frames, _a, folder, image, local, frameDest, resume, matching, constraint, step, frameArray, delayArray, upScaleDest, scaledFrames, cancel, counter_1, total_1, queue, i, finalDest; return __generator(this, function (_b) { switch (_b.label) { case 0: options = __assign({}, options); if (!dest) dest = "./"; frameExt = options.pngFrames ? "png" : "jpg"; return [4 /*yield*/, gif_frames_1["default"]({ url: source, frames: "all", outputType: frameExt })]; case 1: frames = _b.sent(); _a = Waifu2x.parseFilename(source, dest, "2x"), folder = _a.folder, image = _a.image; if (!path_1["default"].isAbsolute(source) && !path_1["default"].isAbsolute(dest)) { local = __dirname.includes("node_modules") ? path_1["default"].join(__dirname, "../../../") : path_1["default"].join(__dirname, ".."); folder = path_1["default"].join(local, folder); } frameDest = folder + "/" + path_1["default"].basename(source, path_1["default"].extname(source)) + "Frames"; resume = 0; if (fs_1["default"].existsSync(frameDest)) { matching = Waifu2x.findMatchingSettings(frameDest, options); if (matching) { frameDest = matching; resume = fs_1["default"].readdirSync(frameDest + "/upscaled").length; } else { frameDest = Waifu2x.newDest(frameDest); fs_1["default"].mkdirSync(frameDest, { recursive: true }); fs_1["default"].writeFileSync(frameDest + "/settings.json", JSON.stringify(options)); } } else { fs_1["default"].mkdirSync(frameDest, { recursive: true }); fs_1["default"].writeFileSync(frameDest + "/settings.json", JSON.stringify(options)); } constraint = options.speed > 1 ? frames.length / options.speed : frames.length; step = Math.ceil(frames.length / constraint); frameArray = []; delayArray = []; return [4 /*yield*/, downloadFrames(frames)]; case 2: _b.sent(); if (options.speed < 1) delayArray = delayArray.map(function (n) { return n / options.speed; }); upScaleDest = frameDest + "/upscaled"; if (!fs_1["default"].existsSync(upScaleDest)) fs_1["default"].mkdirSync(upScaleDest, { recursive: true }); options.rename = ""; scaledFrames = fs_1["default"].readdirSync(upScaleDest).map(function (f) { return upScaleDest + "/" + path_1["default"].basename(f); }); cancel = false; if (!(options.scale !== 1)) return [3 /*break*/, 7]; counter_1 = resume; total_1 = frameArray.length; queue = []; if (!options.parallelFrames) options.parallelFrames = 1; frameArray = frameArray.slice(resume); while (frameArray.length) queue.push(frameArray.splice(0, options.parallelFrames)); if (progress) progress(counter_1++, total_1); i = 0; _b.label = 3; case 3: if (!(i < queue.length)) return [3 /*break*/, 6]; return [4 /*yield*/, Promise.all(queue[i].map(function (f) { return __awaiter(void 0, void 0, void 0, function () { var destPath, stop; return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, Waifu2x.upscaleImage(f, upScaleDest + "/" + path_1["default"].basename(f), options)]; case 1: destPath = _a.sent(); scaledFrames.push(destPath); stop = progress ? progress(counter_1++, total_1) : false; if (stop) cancel = true; return [2 /*return*/]; } }); }); }))]; case 4: _b.sent(); if (cancel) return [3 /*break*/, 6]; _b.label = 5; case 5: i++; return [3 /*break*/, 3]; case 6: return [3 /*break*/, 8]; case 7: scaledFrames = frameArray; _b.label = 8; case 8: scaledFrames = scaledFrames.sort(new Intl.Collator(undefined, { numeric: true, sensitivity: "base" }).compare); if (options.reverse) { scaledFrames = scaledFrames.reverse(); delayArray = delayArray.reverse(); } finalDest = path_1["default"].join(folder, image); return [4 /*yield*/, Waifu2x.encodeGIF(scaledFrames, delayArray, finalDest, options.quality, options.transparentColor)]; case 9: _b.sent(); if (options.noResume || !cancel) Waifu2x.removeDirectory(frameDest); return [2 /*return*/, path_1["default"].normalize(finalDest).replace(/\\/g, "/")]; } }); }); }; Waifu2x.upscaleGIFs = function (sourceFolder, destFolder, options, totalProgress, progress) { return __awaiter(void 0, void 0, void 0, function () { var files, fileMap, retArray, i, ret, stop_1, err_1; return __generator(this, function (_a) { switch (_a.label) { case 0: options = __assign({}, options); files = fs_1["default"].readdirSync(sourceFolder); if (sourceFolder.endsWith("/")) sourceFolder = sourceFolder.slice(0, -1); fileMap = files.map(function (file) { return sourceFolder + "/" + file; }); if (!options.limit) options.limit = fileMap.length; retArray = []; if (totalProgress) totalProgress(0, options.limit); i = 0; _a.label = 1; case 1: if (!(i < options.limit)) return [3 /*break*/, 6]; if (!fileMap[i]) return [3 /*break*/, 6]; _a.label = 2; case 2: _a.trys.push([2, 4, , 5]); return [4 /*yield*/, Waifu2x.upscaleGIF(fileMap[i], destFolder, options, progress)]; case 3: ret = _a.sent(); stop_1 = totalProgress ? totalProgress(i + 1, options.limit) : false; retArray.push(ret); if (stop_1) return [3 /*break*/, 6]; return [3 /*break*/, 5]; case 4: err_1 = _a.sent(); return [3 /*break*/, 5]; case 5: i++; return [3 /*break*/, 1]; case 6: return [2 /*return*/, retArray]; } }); }); }; Waifu2x.dumpWebpFrames = function (source, frameDest, webpPath) { return __awaiter(void 0, void 0, void 0, function () { var absolute, program, command, child; return __generator(this, function (_a) { switch (_a.label) { case 0: absolute = webpPath ? path_1["default"].normalize(webpPath).replace(/\\/g, "/") : path_1["default"].join(__dirname, "../webp"); program = "cd \"" + absolute + "\" && ./anim_dump.exe"; if (process.platform === "darwin") program = "cd \"" + absolute + "\" && ./anim_dump.app"; if (process.platform === "linux") program = "cd \"" + absolute + "\" && ./anim_dump"; command = program + " -folder \"" + frameDest + "\" -prefix \"frame\" \"" + source + "\""; child = child_process_1["default"].exec(command); Waifu2x.addProcess(child); return [4 /*yield*/, new Promise(function (resolve, reject) { child.on("close", function () { Waifu2x.removeProcess(child); resolve(); }); })]; case 1: _a.sent(); return [2 /*return*/, fs_1["default"].readdirSync(frameDest).sort(new Intl.Collator(undefined, { numeric: true, sensitivity: "base" }).compare) .filter(function (s) { return s !== "settings.json"; })]; } }); }); }; Waifu2x.parseWebpDelays = function (source, webpPath) { return __awaiter(void 0, void 0, void 0, function () { var absolute, program, command, child, data; return __generator(this, function (_a) { switch (_a.label) { case 0: absolute = webpPath ? path_1["default"].normalize(webpPath).replace(/\\/g, "/") : path_1["default"].join(__dirname, "../webp"); program = "cd \"" + absolute + "\" && ./webpmux.exe"; if (process.platform === "darwin") program = "cd \"" + absolute + "\" && ./webpmux.app"; if (process.platform === "linux") program = "cd \"" + absolute + "\" && ./webpmux"; command = program + " -info \"" + source + "\""; child = child_process_1["default"].exec(command); data = ""; Waifu2x.addProcess(child); return [4 /*yield*/, new Promise(function (resolve, reject) { child.stdout.on("data", function (chunk) { return data += chunk; }); child.on("close", function () { Waifu2x.removeProcess(child); resolve(); }); })]; case 1: _a.sent(); return [2 /*return*/, data.split("\n").slice(5).map(function (r) { return parseInt(r.split(/ +/g)[7]); }).filter(Boolean)]; } }); }); }; Waifu2x.encodeAnimatedWebp = function (files, delays, dest, webpPath, quality) { return __awaiter(void 0, void 0, void 0, function () { var frames, absolute, program, command, child, error; return __generator(this, function (_a) { switch (_a.label) { case 0: if (!quality) quality = 75; frames = files.map(function (f, i) { return "-d " + delays[i] + " \"" + f + "\""; }).join(" "); absolute = webpPath ? path_1["default"].normalize(webpPath).replace(/\\/g, "/") : path_1["default"].join(__dirname, "../webp"); program = "cd \"" + absolute + "\" && ./img2webp.exe"; if (process.platform === "darwin") program = "cd \"" + absolute + "\" && ./img2webp.app"; if (process.platform === "linux") program = "cd \"" + absolute + "\" && ./img2webp"; command = program + " -loop \"0\" " + frames + " -o \"" + dest + "\""; child = child_process_1["default"].exec(command); Waifu2x.addProcess(child); error = ""; return [4 /*yield*/, new Promise(function (resolve, reject) { child.stderr.on("data", function (chunk) { return error += chunk; }); child.on("close", function () { Waifu2x.removeProcess(child); resolve(); }); })]; case 1: _a.sent(); return [2 /*return*/, dest]; } }); }); }; Waifu2x.upscaleAnimatedWebp = function (source, dest, options, progress) { return __awaiter(void 0, void 0, void 0, function () { var _a, folder, image, local, frameDest, resume, matching, frames, delays, constraint, step, frameArray, delayArray, i, upScaleDest, scaledFrames, cancel, counter_2, total_2, queue, i, finalDest; return __generator(this, function (_b) { switch (_b.label) { case 0: options = __assign({}, options); if (!dest) dest = "./"; _a = Waifu2x.parseFilename(source, dest, "2x"), folder = _a.folder, image = _a.image; if (!path_1["default"].isAbsolute(source) && !path_1["default"].isAbsolute(dest)) { local = __dirname.includes("node_modules") ? path_1["default"].join(__dirname, "../../../") : path_1["default"].join(__dirname, ".."); folder = path_1["default"].join(local, folder); source = path_1["default"].join(local, source); } frameDest = folder + "/" + path_1["default"].basename(source, path_1["default"].extname(source)) + "Frames"; resume = 0; if (fs_1["default"].existsSync(frameDest)) { matching = Waifu2x.findMatchingSettings(frameDest, options); if (matching) { frameDest = matching; resume = fs_1["default"].readdirSync(frameDest + "/upscaled").length; } else { frameDest = Waifu2x.newDest(frameDest); fs_1["default"].mkdirSync(frameDest, { recursive: true }); fs_1["default"].writeFileSync(frameDest + "/settings.json", JSON.stringify(options)); } } else { fs_1["default"].mkdirSync(frameDest, { recursive: true }); fs_1["default"].writeFileSync(frameDest + "/settings.json", JSON.stringify(options)); } return [4 /*yield*/, Waifu2x.dumpWebpFrames(source, frameDest, options.webpPath)]; case 1: frames = _b.sent(); return [4 /*yield*/, Waifu2x.parseWebpDelays(source, options.webpPath)]; case 2: delays = _b.sent(); constraint = options.speed > 1 ? frames.length / options.speed : frames.length; step = Math.ceil(frames.length / constraint); frameArray = []; delayArray = []; for (i = 0; i < frames.length; i += step) { frameArray.push(frameDest + "/" + frames[i]); delayArray.push(delays[i]); } if (options.speed < 1) delayArray = delayArray.map(function (n) { return n / options.speed; }); upScaleDest = frameDest + "/upscaled"; if (!fs_1["default"].existsSync(upScaleDest)) fs_1["default"].mkdirSync(upScaleDest, { recursive: true }); options.rename = ""; scaledFrames = fs_1["default"].readdirSync(upScaleDest).map(function (f) { return upScaleDest + "/" + path_1["default"].basename(f); }); cancel = false; if (!(options.scale !== 1)) return [3 /*break*/, 7]; counter_2 = resume; total_2 = frameArray.length; queue = []; if (!options.parallelFrames) options.parallelFrames = 1; frameArray = frameArray.slice(resume); while (frameArray.length) queue.push(frameArray.splice(0, options.parallelFrames)); if (progress) progress(counter_2++, total_2); i = 0; _b.label = 3; case 3: if (!(i < queue.length)) return [3 /*break*/, 6]; return [4 /*yield*/, Promise.all(queue[i].map(function (f) { return __awaiter(void 0, void 0, void 0, function () { var destPath, stop; return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, Waifu2x.upscaleImage(f, upScaleDest + "/" + path_1["default"].basename(f), options)]; case 1: destPath = _a.sent(); scaledFrames.push(destPath); stop = progress ? progress(counter_2++, total_2) : false; if (stop) cancel = true; return [2 /*return*/]; } }); }); }))]; case 4: _b.sent(); if (cancel) return [3 /*break*/, 6]; _b.label = 5; case 5: i++; return [3 /*break*/, 3]; case 6: return [3 /*break*/, 8]; case 7: scaledFrames = frameArray; _b.label = 8; case 8: scaledFrames = scaledFrames.sort(new Intl.Collator(undefined, { numeric: true, sensitivity: "base" }).compare); if (options.reverse) { sc