1
0
mirror of https://github.com/upscayl/upscayl.git synced 2024-09-23 19:08:25 +02:00

Added sharp

This commit is contained in:
Feenix 2022-08-18 15:23:23 +05:30
parent 3f9e7b1be7
commit 3e9f790347
15 changed files with 9128 additions and 446 deletions

9
constants/commands.js Normal file
View File

@ -0,0 +1,9 @@
const commands = {
SELECT_FILE: "Select a File",
SELECT_FOLDER: "Select a Folder",
UPSCAYL: "Upscale the Image",
UPSCAYL_DONE: "Upscaling Done",
UPSCAYL_PROGRESS: "Send Progress from Main to Renderer",
};
module.exports = commands;

0
constants/models.js Normal file
View File

View File

@ -3,6 +3,7 @@ const { join, parse } = require("path");
const { format } = require("url");
const { spawn } = require("child_process");
const fs = require("fs");
const sizeOf = require("image-size");
const { execPath, modelsPath } = require("./binaries");
@ -13,9 +14,12 @@ const {
ipcMain,
dialog,
ipcRenderer,
shell,
} = require("electron");
const isDev = require("electron-is-dev");
const prepareNext = require("electron-next");
const commands = require("../constants/commands");
const sharp = require("sharp");
// Prepare the renderer once the app is ready
let mainWindow;
@ -25,9 +29,12 @@ app.on("ready", async () => {
mainWindow = new BrowserWindow({
width: 1100,
height: 700,
minHeight: 500,
minWidth: 500,
webPreferences: {
autoHideMenuBar: true,
nodeIntegration: true,
webSecurity: false,
preload: join(__dirname, "preload.js"),
},
});
@ -42,17 +49,19 @@ app.on("ready", async () => {
mainWindow.setMenuBarVisibility(false);
// mainWindow.maximize();
mainWindow.loadURL(url);
mainWindow.webContents.setWindowOpenHandler(({ url }) => {
shell.openExternal(url);
return { action: "deny" };
});
});
// Quit the app once all windows are closed
app.on("window-all-closed", app.quit);
// ! DONT FORGET TO RESTART THE APP WHEN YOU CHANGE CODE HERE
ipcMain.on("sendMessage", (_, message) => {
console.log(message);
});
ipcMain.handle("open", async () => {
ipcMain.handle(commands.SELECT_FILE, async () => {
const { canceled, filePaths } = await dialog.showOpenDialog({
properties: ["openFile", "multiSelections"],
});
@ -62,37 +71,40 @@ ipcMain.handle("open", async () => {
return "cancelled";
} else {
console.log(filePaths[0]);
// CREATE input AND upscaled FOLDER
// CREATE input AND upscaled FOLDER
return filePaths[0];
}
})
ipcMain.handle("output", async (event, message) => {
});
ipcMain.handle(commands.SELECT_FOLDER, async (event, message) => {
const { canceled, filePaths } = await dialog.showOpenDialog({
properties: ["openDirectory"],
});
if (canceled) {
console.log("operation cancelled");
return "cancelled";
}
else {
console.log(filePaths[0])
} else {
console.log(filePaths[0]);
return filePaths[0];
}
})
});
ipcMain.on("upscayl", async (event, paths) => {
const scale = "4";
let inputDir = paths[0].match(/(.*)[\/\\]/)[1]||'';
ipcMain.on(commands.UPSCAYL, async (event, payload) => {
console.log(payload);
const model = payload.model;
const scale = payload.scaleFactor;
let inputDir = payload.imagePath.match(/(.*)[\/\\]/)[1] || "";
/*if (!fs.existsSync(inputDir)) {
fs.mkdirSync(inputDir);
}*/
let outputDir = paths[1];
/*if (!fs.existsSync(outputDir)) {
fs.mkdirSync(outputDir);
}*/
let outputDir = payload.outputPath;
// if (!fs.existsSync(outputDir)) {
// fs.mkdirSync(outputDir);
// }
// COPY IMAGE TO upscaled FOLDER
const fullfileName = paths[0].split("/").slice(-1)[0];
const fullfileName = payload.imagePath.split("/").slice(-1)[0];
const fileName = parse(fullfileName).name;
const fileExt = parse(fullfileName).ext;
@ -101,15 +113,17 @@ ipcMain.on("upscayl", async (event, paths) => {
execPath,
[
"-i",
inputDir+'/'+fullfileName,
inputDir + "/" + fullfileName,
"-o",
outputDir+'/'+fileName+"_upscaled_"+scale+'x'+fileExt,
outputDir + "/" + fileName + "_upscayled_" + scale + "x" + fileExt,
"-s",
scale,
scale === 2 ? 4 : scale,
"-m",
modelsPath,
modelsPath, // if (!fs.existsSync(outputDir)) {
// fs.mkdirSync(outputDir);
// }
"-n",
"realesrgan-x4plus",
model,
],
{
cwd: null,
@ -120,11 +134,14 @@ ipcMain.on("upscayl", async (event, paths) => {
upscayl.stderr.on("data", (stderr) => {
console.log(stderr.toString());
stderr = stderr.toString();
mainWindow.webContents.send("output", stderr.toString());
mainWindow.webContents.send(commands.UPSCAYL_PROGRESS, stderr.toString());
});
upscayl.on("close", (code) => {
console.log("Done upscaling");
mainWindow.webContents.send("done");
mainWindow.webContents.send(
commands.UPSCAYL_DONE,
outputDir + "/" + fileName + "_upscayled_" + scale + "x" + fileExt
);
});
})
});

View File

@ -8,10 +8,4 @@ contextBridge.exposeInMainWorld("electron", {
func(event, args);
}),
invoke: (command, payload) => ipcRenderer.invoke(command, payload),
startListen: (func) => {
ipcRenderer.addListener("stdout",func)
},
stopListen: (func) => {
ipcRenderer.removeListener("stdout",func)
},
});

7236
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -67,6 +67,10 @@
"electron-is-dev": "^2.0.0",
"electron-is-packaged": "^1.0.2",
"electron-next": "^3.1.5",
"electron-root-path": "^1.0.16"
"electron-root-path": "^1.0.16",
"image-size": "^1.0.2",
"react-compare-slider": "^2.2.0",
"sharp": "^0.30.7",
"tailwind-scrollbar": "^1.3.1"
}
}

View File

@ -1,84 +1,219 @@
import { useState, useEffect, useRef } from "react";
import commands from "../../constants/commands";
import {
ReactCompareSlider,
ReactCompareSliderImage,
} from "react-compare-slider";
const Home = () => {
const [imagePath, SetImagePath] = useState();
const [outputPath, SetOutputPath] = useState();
const [imagePath, SetImagePath] = useState("");
const [upscaledImagePath, setUpscaledImagePath] = useState("");
const [outputPath, SetOutputPath] = useState("");
const [scaleFactor, setScaleFactor] = useState(4);
const [progress, setProgress] = useState("");
const [model, setModel] = useState("realesrgan-x4plus");
const [loaded, setLoaded] = useState(false);
useEffect(() => {
const handleMessage = (_event, args) => console.log(args)
window.electron.startListen(handleMessage)
// send(command, payload)
window.electron.send("sendMessage", { message: "Hello!" });
setLoaded(true);
window.electron.on("output", (_, data) => {
if (data.length > 0 && data.length < 10) console.log(data);
window.electron.on(commands.UPSCAYL_PROGRESS, (_, data) => {
if (data.length > 0 && data.length < 10) setProgress(data);
});
window.electron.on("done", (_, data) => {
console.log("DONE!");
window.electron.on(commands.UPSCAYL_DONE, (_, data) => {
setUpscaledImagePath(data);
});
return () => {
window.electron.stopListen(handleMessage)
}
}, []);
const imageHandler = async () => {
var path = await window.electron.invoke("open");
if (path != "cancelled") {
const selectImageHandler = async () => {
SetImagePath("");
setUpscaledImagePath("");
setProgress("");
var path = await window.electron.invoke(commands.SELECT_FILE);
if (path !== "cancelled") {
SetImagePath(path);
var dirname = path.match(/(.*)[\/\\]/)[1]||''
SetOutputPath(dirname)
var dirname = path.match(/(.*)[\/\\]/)[1] || "";
SetOutputPath(dirname);
}
};
const outputHandler = async () => {
var path = await window.electron.invoke("output");
if (path != "cancelled") {
SetOutputPath(path)
}
else{
console.log("Getting output path from input file")
}
};
const upscaylHandler = async () => {
window.electron.send("upscayl", [imagePath, outputPath]);
};
const outputHandler = async () => {
var path = await window.electron.invoke(commands.SELECT_FOLDER);
if (path !== "cancelled") {
SetOutputPath(path);
} else {
console.log("Getting output path from input file");
}
};
const upscaylHandler = async () => {
setProgress("0.00%");
await window.electron.send(commands.UPSCAYL, {
scaleFactor,
imagePath,
outputPath,
model,
});
};
useEffect(() => {
console.log(progress);
}, [progress]);
return (
<div className="flex h-screen w-screen flex-row bg-neutral-900">
<div className="flex h-screen w-96 flex-col bg-neutral-800 p-5">
<h1 className="text-3xl font-bold text-neutral-50">Upscayl</h1>
<div className="mt-10">
<p className="mb-2 font-medium text-neutral-100">Step 1</p>
<button className="rounded-lg bg-sky-400 p-3" onClick={imageHandler}>
Select Image
</button>
</div>
<div className="mt-10">
<p className="mb-2 font-medium text-neutral-100">Step 2</p>
<p className="mb-1 text-neutral-300">Select Scale Factor:</p>
<div className="flex flex-row gap-2">
<button className="rounded-lg bg-red-400 p-3">2x</button>
<button className="rounded-lg bg-red-400 p-3">4x</button>
<button className="rounded-lg bg-red-400 p-3">6x</button>
<div className="flex h-screen w-screen flex-row overflow-hidden bg-neutral-900">
<div className="flex h-screen w-96 flex-col bg-neutral-800">
{/* HEADER */}
<h1 className="pl-5 pt-5 text-3xl font-bold text-neutral-50">
Upscayl
</h1>
<p className="mb-2 pl-5 text-neutral-400">AI Image Upscaler</p>
{/* LEFT PANE */}
<div className="h-screen overflow-auto p-5">
{/* STEP 1 */}
<div className="mt-5">
<p className="mb-2 font-medium text-neutral-100">Step 1</p>
<button
className="rounded-lg bg-rose-400 p-3"
onClick={selectImageHandler}
>
Select Image
</button>
</div>
{/* STEP 2 */}
<div className="mt-10">
<p className="font-medium text-neutral-100">Step 2</p>
<p className="mb-2 text-sm text-neutral-400">Select Scale Factor</p>
<div className="animate flex flex-row gap-2">
<button
className={`h-12 w-12 rounded-lg ${
scaleFactor === 2 ? "bg-yellow-400" : "bg-neutral-400"
}`}
onClick={() => setScaleFactor(2)}
>
2x
</button>
<button
className={`h-12 w-12 rounded-lg ${
scaleFactor === 3 ? "bg-yellow-400" : "bg-neutral-400"
}`}
onClick={() => setScaleFactor(3)}
>
3x
</button>
<button
className={`h-12 w-12 rounded-lg ${
scaleFactor === 4 ? "bg-yellow-400" : "bg-neutral-400"
}`}
onClick={() => setScaleFactor(6)}
>
4x
</button>
</div>
</div>
{/* STEP 3 */}
<div className="mt-10">
<p className="font-medium text-neutral-100">Step 3</p>
<p className="mb-2 text-sm text-neutral-400">
Defaults to Image's path
</p>
<button
className="rounded-lg bg-teal-400 p-3"
onClick={outputHandler}
>
Set Output Folder
</button>
</div>
{/* STEP 4 */}
<div className="mt-10">
<p className="mb-2 font-medium text-neutral-100">Step 4</p>
<button
className="rounded-lg bg-sky-400 p-3"
onClick={upscaylHandler}
>
Upscayl
</button>
</div>
</div>
<div className="mt-10">
<p className="mb-2 font-medium text-neutral-100">Step 3</p>
<button className="rounded-lg bg-violet-400 p-3" onClick={outputHandler}>
Set Output Folder
</button>
</div>
<div className="mt-10">
<p className="mb-2 font-medium text-neutral-100">Step 4</p>
<button className="rounded-lg bg-green-400 p-3" onClick={upscaylHandler}>Upscayl</button>
<div className="p-2 text-center text-sm text-neutral-500">
<p>
Copyright © 2022 -{" "}
<a
className="font-bold"
href="https://github.com/TGS963/upscayl"
target="_blank"
>
Upscayl
</a>
</p>
<p>
Made by{" "}
<a
href="https://github.com/TGS963"
className="font-bold"
target="_blank"
>
TGS963
</a>{" "}
and{" "}
<a
href="https://github.com/NayamAmarshe"
className="font-bold"
target="_blank"
>
Nayam Amarshe
</a>
</p>
</div>
</div>
<div className="flex h-screen w-full flex-col items-center justify-center p-5">
<p className="text-lg font-medium text-neutral-400">
Select an Image to Upscale
</p>
{/* RIGHT PANE */}
<div className="relative flex h-screen w-full flex-col items-center justify-center">
{progress.length > 0 && (
<div className="absolute flex h-full w-full flex-col items-center justify-center bg-black/50 backdrop-blur-lg">
<div className="flex flex-col items-center gap-2">
<img src="/loading.svg" className="w-10" alt="Loading" />
<p className="font-bold text-neutral-50">{progress}</p>
</div>
</div>
)}
{imagePath.length === 0 ? (
<p className="p-5 text-lg font-medium text-neutral-400">
Select an Image to Upscale
</p>
) : upscaledImagePath.length === 0 ? (
<img
className="h-full w-full object-contain"
src={
"file://" + `${upscaledImagePath ? upscaledImagePath : imagePath}`
}
alt=""
/>
) : (
<ReactCompareSlider
itemOne={
<ReactCompareSliderImage
src={"file://" + imagePath}
alt="Original"
/>
}
itemTwo={
<ReactCompareSliderImage
src={"file://" + upscaledImagePath}
alt="Upscayl"
/>
}
className="h-full"
/>
)}
</div>
</div>
);

View File

@ -0,0 +1,55 @@
<!-- By Sam Herbert (@sherb), for everyone. More @ http://goo.gl/7AJzbL -->
<svg width="58" height="58" viewBox="0 0 58 58" xmlns="http://www.w3.org/2000/svg">
<g fill="none" fill-rule="evenodd">
<g transform="translate(2 1)" stroke="#FFF" stroke-width="1.5">
<circle cx="42.601" cy="11.462" r="5" fill-opacity="1" fill="#fff">
<animate attributeName="fill-opacity"
begin="0s" dur="1.3s"
values="1;0;0;0;0;0;0;0" calcMode="linear"
repeatCount="indefinite" />
</circle>
<circle cx="49.063" cy="27.063" r="5" fill-opacity="0" fill="#fff">
<animate attributeName="fill-opacity"
begin="0s" dur="1.3s"
values="0;1;0;0;0;0;0;0" calcMode="linear"
repeatCount="indefinite" />
</circle>
<circle cx="42.601" cy="42.663" r="5" fill-opacity="0" fill="#fff">
<animate attributeName="fill-opacity"
begin="0s" dur="1.3s"
values="0;0;1;0;0;0;0;0" calcMode="linear"
repeatCount="indefinite" />
</circle>
<circle cx="27" cy="49.125" r="5" fill-opacity="0" fill="#fff">
<animate attributeName="fill-opacity"
begin="0s" dur="1.3s"
values="0;0;0;1;0;0;0;0" calcMode="linear"
repeatCount="indefinite" />
</circle>
<circle cx="11.399" cy="42.663" r="5" fill-opacity="0" fill="#fff">
<animate attributeName="fill-opacity"
begin="0s" dur="1.3s"
values="0;0;0;0;1;0;0;0" calcMode="linear"
repeatCount="indefinite" />
</circle>
<circle cx="4.938" cy="27.063" r="5" fill-opacity="0" fill="#fff">
<animate attributeName="fill-opacity"
begin="0s" dur="1.3s"
values="0;0;0;0;0;1;0;0" calcMode="linear"
repeatCount="indefinite" />
</circle>
<circle cx="11.399" cy="11.462" r="5" fill-opacity="0" fill="#fff">
<animate attributeName="fill-opacity"
begin="0s" dur="1.3s"
values="0;0;0;0;0;0;1;0" calcMode="linear"
repeatCount="indefinite" />
</circle>
<circle cx="27" cy="5" r="5" fill-opacity="0" fill="#fff">
<animate attributeName="fill-opacity"
begin="0s" dur="1.3s"
values="0;0;0;0;0;0;0;1" calcMode="linear"
repeatCount="indefinite" />
</circle>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@ -3,6 +3,21 @@
@tailwind utilities;
@layer base {
::-webkit-scrollbar {
@apply w-3;
}
::-webkit-scrollbar-track {
@apply rounded-full bg-neutral-700;
}
::-webkit-scrollbar-thumb {
@apply rounded-full bg-neutral-500;
}
::-webkit-scrollbar-thumb:hover {
@apply rounded-full bg-neutral-400;
}
}
@ -10,5 +25,4 @@
.animate {
@apply transition-all duration-300 ease-in-out;
}
}

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -7,5 +7,5 @@ module.exports = {
extend: {},
},
darkMode: "class",
plugins: [],
plugins: [require("tailwind-scrollbar")],
};

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 934 KiB

919
yarn.lock

File diff suppressed because it is too large Load Diff