waifu2x
Version:
2x upscaling of images with waifu2x
886 lines • 82.8 kB
JavaScript
"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