UNPKG

waifu2x

Version:

2x upscaling of images with waifu2x

871 lines 84.6 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 (g && (g = 0, op[0] && (_ = 0)), _) 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 __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { if (ar || !(i in from)) { if (!ar) ar = Array.prototype.slice.call(from, 0, i); ar[i] = from[i]; } } return to.concat(ar || Array.prototype.slice.call(from)); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: 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")); 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() { } var _a; _a = Waifu2x; Waifu2x.processes = []; Waifu2x.addProcess = function (process) { _a.processes.push(process); }; Waifu2x.removeProcess = function (process) { _a.processes = _a.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("".concat(waifu2x, "/waifu2x-ncnn-vulkan.app"), "777"); fs_1.default.chmodSync("".concat(esrgan, "/realesrgan-ncnn-vulkan.app"), "777"); fs_1.default.chmodSync("".concat(cugan, "/realcugan-ncnn-vulkan.app"), "777"); fs_1.default.chmodSync("".concat(anime4k, "/Anime4KCPP_CLI.app"), "777"); fs_1.default.chmodSync("".concat(webp, "/anim_dump.app"), "777"); fs_1.default.chmodSync("".concat(webp, "/cwebp.app"), "777"); fs_1.default.chmodSync("".concat(webp, "/dwebp.app"), "777"); fs_1.default.chmodSync("".concat(webp, "/img2webp.app"), "777"); fs_1.default.chmodSync("".concat(webp, "/webpmux.app"), "777"); rife_fps_1.default.chmod777(rifePath); }; Waifu2x.parseFilename = function (source, dest, rename) { var _b = ["", ""], image = _b[0], folder = _b[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 = "".concat(path_1.default.basename(source, path_1.default.extname(source))).concat(rename).concat(path_1.default.extname(source)); } return { folder: folder, image: image }; }; Waifu2x.recursiveRename = function (folder, fileNames, rename) { var _b; if (folder.endsWith("/")) folder = folder.slice(0, -1); for (var i = 0; i < fileNames.length; i++) { var fullPath = "".concat(folder, "/").concat(fileNames[i]); var check = fs_1.default.statSync(fullPath); if (check.isDirectory()) { var subFiles = fs_1.default.readdirSync(fullPath); _a.recursiveRename(fullPath, subFiles, rename); } else { var pathSplit = fileNames[i].split("."); var newName = ((_b = pathSplit === null || pathSplit === void 0 ? void 0 : pathSplit[0].split("_")) === null || _b === void 0 ? void 0 : _b[0]) + rename; var newPath = "".concat(folder, "/").concat(newName, ".").concat(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 _b = _a.parseFilename(source, dest, options.rename), folder = _b.folder, image = _b.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("".concat(folder, "/").concat(image)).replace(/\\/g, "/"); }; Waifu2x.timeout = function (ms) { return __awaiter(void 0, void 0, void 0, function () { return __generator(_a, function (_b) { 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(_a, function (_b) { switch (_b.label) { case 0: if (!quality) quality = 75; absolute = webpPath ? path_1.default.normalize(webpPath).replace(/\\/g, "/") : path_1.default.join(__dirname, "../webp"); program = "cd \"".concat(absolute, "\" && ./cwebp.exe"); if (process.platform === "darwin") program = "cd \"".concat(absolute, "\" && ./cwebp.app"); if (process.platform === "linux") program = "cd \"".concat(absolute, "\" && ./cwebp"); command = "".concat(program, " -q ").concat(quality, " \"").concat(source, "\" -o \"").concat(dest, "\""); child = child_process_1.default.exec(command); _a.addProcess(child); return [4 /*yield*/, new Promise(function (resolve, reject) { child.on("close", function () { _a.removeProcess(child); resolve(); }); })]; case 1: _b.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(_a, function (_b) { switch (_b.label) { case 0: absolute = webpPath ? path_1.default.normalize(webpPath).replace(/\\/g, "/") : path_1.default.join(__dirname, "../webp"); program = "cd \"".concat(absolute, "\" && ./dwebp.exe"); if (process.platform === "darwin") program = "cd \"".concat(absolute, "\" && ./dwebp.app"); if (process.platform === "linux") program = "cd \"".concat(absolute, "\" && ./dwebp"); command = "".concat(program, " \"").concat(source, "\" -o \"").concat(dest, "\""); child = child_process_1.default.exec(command); _a.addProcess(child); error = ""; return [4 /*yield*/, new Promise(function (resolve, reject) { child.stderr.on("data", function (chunk) { return error += chunk; }); child.on("close", function () { _a.removeProcess(child); resolve(); }); })]; case 1: _b.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, _b, 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(_a, function (_c) { switch (_c.label) { case 0: options = __assign({}, options); if (!dest) dest = "./"; if (!options.upscaler) options.upscaler = "waifu2x"; sourcePath = source; if (options.rename === undefined) options.rename = "2x"; _b = _a.parseFilename(source, dest, options.rename), folder = _b.folder, image = _b.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 = (0, image_size_1.imageSize)(buffer); if (!(dimensions.type === "webp")) return [3 /*break*/, 4]; _c.label = 1; case 1: _c.trys.push([1, 3, , 4]); return [4 /*yield*/, _a.convertFromWebp(sourcePath, destPath, options.webpPath)]; case 2: _c.sent(); sourcePath = destPath; return [3 /*break*/, 4]; case 3: error_1 = _c.sent(); return [2 /*return*/, Promise.reject("Animated webp: ".concat(error_1))]; case 4: command = ""; if (options.upscaler === "waifu2x") { program = "cd \"".concat(absolute, "\" && waifu2x-ncnn-vulkan.exe"); if (process.platform === "darwin") program = "cd \"".concat(absolute, "\" && ./waifu2x-ncnn-vulkan.app"); if (process.platform === "linux") program = "cd \"".concat(absolute, "\" && ./waifu2x-ncnn-vulkan"); if (process.platform === "linux" && process.arch === "arm64") program = "cd \"".concat(absolute, "\" && ./waifu2x-ncnn-vulkan-arm"); ext = path_1.default.extname(source).replace(".", ""); command = "".concat(program, " -i \"").concat(sourcePath, "\" -o \"").concat(destPath, "\" -f ").concat(ext); if (options.scale) command += " -s ".concat(options.scale); if (options.threads) command += " -j ".concat(options.threads, ":").concat(options.threads, ":").concat(options.threads); if (options.waifu2xModel) command += " -m \"".concat(options.waifu2xModel, "\""); } else if (options.upscaler === "real-esrgan") { program = "cd \"".concat(absolute, "\" && realesrgan-ncnn-vulkan.exe"); if (process.platform === "darwin") program = "cd \"".concat(absolute, "\" && ./realesrgan-ncnn-vulkan.app"); if (process.platform === "linux") program = "cd \"".concat(absolute, "\" && ./realesrgan-ncnn-vulkan"); if (process.platform === "linux" && process.arch === "arm64") program = "cd \"".concat(absolute, "\" && ./realesrgan-ncnn-vulkan-arm"); ext = path_1.default.extname(source).replace(".", ""); command = "".concat(program, " -i \"").concat(sourcePath, "\" -o \"").concat(destPath, "\" -f ").concat(ext, " -n ").concat(options.scale === 4 ? "realesrgan-x4plus-anime" : "realesr-animevideov3"); if (options.scale) command += " -s ".concat(options.scale); if (options.threads) command += " -j ".concat(options.threads, ":").concat(options.threads, ":").concat(options.threads); } else if (options.upscaler === "real-cugan") { program = "cd \"".concat(absolute, "\" && realcugan-ncnn-vulkan.exe"); if (process.platform === "darwin") program = "cd \"".concat(absolute, "\" && ./realcugan-ncnn-vulkan.app"); if (process.platform === "linux") program = "cd \"".concat(absolute, "\" && ./realcugan-ncnn-vulkan"); if (process.platform === "linux" && process.arch === "arm64") program = "cd \"".concat(absolute, "\" && ./realcugan-ncnn-vulkan-arm"); ext = path_1.default.extname(source).replace(".", ""); command = "".concat(program, " -i \"").concat(sourcePath, "\" -o \"").concat(destPath, "\" -f ").concat(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 ".concat(options.noise); } if (options.scale) command += " -s ".concat(options.scale); if (options.threads) command += " -j ".concat(options.threads, ":").concat(options.threads, ":").concat(options.threads); } else if (options.upscaler === "anime4k") { program = "cd \"".concat(absolute, "\" && Anime4KCPP_CLI.exe"); if (process.platform === "darwin") program = "cd \"".concat(absolute, "\" && ./Anime4KCPP_CLI.app"); if (process.platform === "linux") program = "cd \"".concat(absolute, "\" && ./Anime4KCPP_CLI"); if (process.platform === "linux" && process.arch === "arm64") program = "cd \"".concat(absolute, "\" && ./ac_cli"); command = "".concat(program, " -i \"").concat(sourcePath, "\" -o \"").concat(destPath, "\" -A"); if (options.scale) command += " -z ".concat(options.scale); } else { python = process.platform === "darwin" ? "PYTORCH_ENABLE_MPS_FALLBACK=1 /usr/local/bin/python3" : "python3"; program = "cd \"".concat(absolute, "\" && ").concat(python, " upscale.py"); command = "".concat(program, " -i \"").concat(sourcePath, "\" -o \"").concat(destPath, "\" -m \"").concat(options.upscaler, "\""); if (options.pythonDownscale && Number(options.pythonDownscale > 0)) command += " -d ".concat(options.pythonDownscale); } child = child_process_1.default.exec(command); _a.addProcess(child); stopped = false; poll = function () { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_b) { switch (_b.label) { case 0: if (progress()) { stopped = true; child.stdio.forEach(function (s) { return s.destroy(); }); child.kill("SIGINT"); } return [4 /*yield*/, _a.timeout(1000)]; case 1: _b.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; _a.removeProcess(child); resolve(); }); })]; case 5: _c.sent(); if (error) return [2 /*return*/, Promise.reject(error)]; if (!(path_1.default.extname(destPath) === ".webp")) return [3 /*break*/, 7]; return [4 /*yield*/, _a.convertToWebp(destPath, destPath, options.webpPath, options.jpgWebpQuality)]; case 6: _c.sent(); _c.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 "".concat(dir, "/").concat(file); }).filter(function (f) { return fs_1.default.lstatSync(f).isFile(); }); if (!recursive) return fileMap; var dirMap = files.map(function (file) { return "".concat(dir, "/").concat(file); }).filter(function (f) { return fs_1.default.lstatSync(f).isDirectory(); }); return fileMap.concat(dirMap.flatMap(function (dirEntry) { return _a.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(_a, function (_b) { switch (_b.label) { case 0: options = __assign({}, options); if (sourceFolder.endsWith("/")) sourceFolder = sourceFolder.slice(0, -1); fileMap = _a.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; _b.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 (_b) { switch (_b.label) { case 0: if (counter >= options.limit) cancel = true; return [4 /*yield*/, _a.upscaleImage(f, destFolder, options)]; case 1: ret = _b.sent(); retArray.push(ret); stop = progress ? progress(counter++, total) : false; if (stop) cancel = true; return [2 /*return*/]; } }); }); }))]; case 2: _b.sent(); if (cancel) return [3 /*break*/, 4]; _b.label = 3; case 3: i++; return [3 /*break*/, 1]; case 4: return [2 /*return*/, retArray]; } }); }); }; Waifu2x.parseTransparentColor = function (color) { return Number("0x".concat(color.replace(/^#/, ""))); }; Waifu2x.encodeGIF = function (files, delays, dest, quality, transparentColor) { return __awaiter(void 0, void 0, void 0, function () { return __generator(_a, function (_b) { if (!quality) quality = 10; return [2 /*return*/, new Promise(function (resolve) { var dimensions = (0, 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(_a.parseTransparentColor(transparentColor)); var counter = 0; var addToGif = function (frames) { (0, 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(_a, function (_b) { 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 = "".concat(dest, "_").concat(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("".concat(newDest, "/settings.json"), "utf8")); if (JSON.stringify(settings) === JSON.stringify(options)) { return newDest; } } newDest = "".concat(dest, "_").concat(i); while (fs_1.default.existsSync(newDest) || i < 10) { if (fs_1.default.existsSync(newDest)) { var settings = JSON.parse(fs_1.default.readFileSync("".concat(newDest, "/settings.json"), "utf8")); if (JSON.stringify(settings) === JSON.stringify(options)) { return newDest; } } i++; newDest = "".concat(dest, "_").concat(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 (_b) { promiseArray = []; for (i = 0; i < frames.length; i += step) { writeStream = fs_1.default.createWriteStream("".concat(frameDest, "/frame").concat(i, ".").concat(frameExt)); frames[i].getImage().pipe(writeStream); frameArray.push("".concat(frameDest, "/frame").concat(i, ".").concat(frameExt)); delayArray.push(frames[i].frameInfo.delay); promiseArray.push(_a.awaitStream(writeStream)); } return [2 /*return*/, Promise.all(promiseArray)]; }); }); } var frameExt, frames, _b, folder, image, local, frameDest, resume, matching, constraint, step, frameArray, delayArray, upScaleDest, scaledFrames, cancel, counter_1, total_1, queue, i, finalDest; return __generator(_a, function (_c) { switch (_c.label) { case 0: options = __assign({}, options); if (!dest) dest = "./"; frameExt = options.pngFrames ? "png" : "jpg"; return [4 /*yield*/, (0, gif_frames_1.default)({ url: source, frames: "all", outputType: frameExt })]; case 1: frames = _c.sent(); _b = _a.parseFilename(source, dest, "2x"), folder = _b.folder, image = _b.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 = "".concat(folder, "/").concat(path_1.default.basename(source, path_1.default.extname(source)), "Frames"); resume = 0; if (fs_1.default.existsSync(frameDest)) { matching = _a.findMatchingSettings(frameDest, options); if (matching) { frameDest = matching; resume = fs_1.default.readdirSync("".concat(frameDest, "/upscaled")).length; } else { frameDest = _a.newDest(frameDest); fs_1.default.mkdirSync(frameDest, { recursive: true }); fs_1.default.writeFileSync("".concat(frameDest, "/settings.json"), JSON.stringify(options)); } } else { fs_1.default.mkdirSync(frameDest, { recursive: true }); fs_1.default.writeFileSync("".concat(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: _c.sent(); if (options.speed < 1) delayArray = delayArray.map(function (n) { return n / options.speed; }); upScaleDest = "".concat(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 "".concat(upScaleDest, "/").concat(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; _c.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 (_b) { switch (_b.label) { case 0: return [4 /*yield*/, _a.upscaleImage(f, "".concat(upScaleDest, "/").concat(path_1.default.basename(f)), options)]; case 1: destPath = _b.sent(); scaledFrames.push(destPath); stop = progress ? progress(counter_1++, total_1) : false; if (stop) cancel = true; return [2 /*return*/]; } }); }); }))]; case 4: _c.sent(); if (cancel) return [3 /*break*/, 6]; _c.label = 5; case 5: i++; return [3 /*break*/, 3]; case 6: return [3 /*break*/, 8]; case 7: scaledFrames = frameArray; _c.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*/, _a.encodeGIF(scaledFrames, delayArray, finalDest, options.quality, options.transparentColor)]; case 9: _c.sent(); if (options.noResume || !cancel) _a.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(_a, function (_b) { switch (_b.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 "".concat(sourceFolder, "/").concat(file); }); if (!options.limit) options.limit = fileMap.length; retArray = []; if (totalProgress) totalProgress(0, options.limit); i = 0; _b.label = 1; case 1: if (!(i < options.limit)) return [3 /*break*/, 6]; if (!fileMap[i]) return [3 /*break*/, 6]; _b.label = 2; case 2: _b.trys.push([2, 4, , 5]); return [4 /*yield*/, _a.upscaleGIF(fileMap[i], destFolder, options, progress)]; case 3: ret = _b.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 = _b.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(_a, function (_b) { switch (_b.label) { case 0: absolute = webpPath ? path_1.default.normalize(webpPath).replace(/\\/g, "/") : path_1.default.join(__dirname, "../webp"); program = "cd \"".concat(absolute, "\" && ./anim_dump.exe"); if (process.platform === "darwin") program = "cd \"".concat(absolute, "\" && ./anim_dump.app"); if (process.platform === "linux") program = "cd \"".concat(absolute, "\" && ./anim_dump"); command = "".concat(program, " -folder \"").concat(frameDest, "\" -prefix \"frame\" \"").concat(source, "\""); child = child_process_1.default.exec(command); _a.addProcess(child); return [4 /*yield*/, new Promise(function (resolve, reject) { child.on("close", function () { _a.removeProcess(child); resolve(); }); })]; case 1: _b.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(_a, function (_b) { switch (_b.label) { case 0: absolute = webpPath ? path_1.default.normalize(webpPath).replace(/\\/g, "/") : path_1.default.join(__dirname, "../webp"); program = "cd \"".concat(absolute, "\" && ./webpmux.exe"); if (process.platform === "darwin") program = "cd \"".concat(absolute, "\" && ./webpmux.app"); if (process.platform === "linux") program = "cd \"".concat(absolute, "\" && ./webpmux"); command = "".concat(program, " -info \"").concat(source, "\""); child = child_process_1.default.exec(command); data = ""; _a.addProcess(child); return [4 /*yield*/, new Promise(function (resolve, reject) { child.stdout.on("data", function (chunk) { return data += chunk; }); child.on("close", function () { _a.removeProcess(child); resolve(); }); })]; case 1: _b.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(_a, function (_b) { switch (_b.label) { case 0: if (!quality) quality = 75; frames = files.map(function (f, i) { return "-d ".concat(delays[i], " \"").concat(f, "\""); }).join(" "); absolute = webpPath ? path_1.default.normalize(webpPath).replace(/\\/g, "/") : path_1.default.join(__dirname, "../webp"); program = "cd \"".concat(absolute, "\" && ./img2webp.exe"); if (process.platform === "darwin") program = "cd \"".concat(absolute, "\" && ./img2webp.app"); if (process.platform === "linux") program = "cd \"".concat(absolute, "\" && ./img2webp"); command = "".concat(program, " -loop \"0\" ").concat(frames, " -o \"").concat(dest, "\""); child = child_process_1.default.exec(command); _a.addProcess(child); error = ""; return [4 /*yield*/, new Promise(function (resolve, reject) { child.stderr.on("data", function (chunk) { return error += chunk; }); child.on("close", function () { _a.removeProcess(child); resolve(); }); })]; case 1: _b.sent(); return [2 /*return*/, dest]; } }); }); }; Waifu2x.upscaleAnimatedWebp = function (source, dest, options, progress) { return __awaiter(void 0, void 0, void 0, function () { var _b, 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(_a, function (_c) { switch (_c.label) { case 0: options = __assign({}, options); if (!dest) dest = "./"; _b = _a.parseFilename(source, dest, "2x"), folder = _b.folder, image = _b.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 = "".concat(folder, "/").concat(path_1.default.basename(source, path_1.default.extname(source)), "Frames"); resume = 0; if (fs_1.default.existsSync(frameDest)) { matching = _a.findMatchingSettings(frameDest, options); if (matching) { frameDest = matching; resume = fs_1.default.readdirSync("".concat(frameDest, "/upscaled")).length; } else { frameDest = _a.newDest(frameDest); fs_1.default.mkdirSync(frameDest, { recursive: true }); fs_1.default.writeFileSync("".concat(frameDest, "/settings.json"), JSON.stringify(options)); } } else { fs_1.default.mkdirSync(frameDest, { recursive: true }); fs_1.default.writeFileSync("".concat(frameDest, "/settings.json"), JSON.stringify(options)); } return [4 /*yield*/, _a.dumpWebpFrames(source, frameDest, options.webpPath)]; case 1: frames = _c.sent(); return [4 /*yield*/, _a.parseWebpDelays(source, options.webpPath)]; case 2: delays = _c.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("".concat(frameDest, "/").concat(frames[i])); delayArray.push(delays[i]); } if (options.speed < 1) delayArray = delayArray.map(function (n) { return n / options.speed; }); upScaleDest = "".concat(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 "".concat(upScaleDest, "/").concat(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; _c.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 (_b) { switch (_b.label) { case 0: return [4 /*yield*/, _a.upscaleImage(f, "".c