mirror of
https://github.com/upscayl/upscayl.git
synced 2025-02-17 11:18:36 +01:00
New save options, updated step order, CSS updates
This commit is contained in:
parent
6cc5991a41
commit
88209ac2f0
@ -1,6 +1,8 @@
|
|||||||
const commands = {
|
const commands = {
|
||||||
SELECT_FILE: "Select a File",
|
SELECT_FILE: "Select a File",
|
||||||
SELECT_FOLDER: "Select a Folder",
|
SELECT_OUTPUT: "Save as",
|
||||||
|
SET_FILE: "Set file",
|
||||||
|
REPLACE_ORIGINAL: "Replace original",
|
||||||
UPSCAYL: "Upscale the Image",
|
UPSCAYL: "Upscale the Image",
|
||||||
UPSCAYL_DONE: "Upscaling Done",
|
UPSCAYL_DONE: "Upscaling Done",
|
||||||
UPSCAYL_PROGRESS: "Send Progress from Main to Renderer",
|
UPSCAYL_PROGRESS: "Send Progress from Main to Renderer",
|
||||||
|
@ -4,6 +4,7 @@ const { format } = require("url");
|
|||||||
const { spawn } = require("child_process");
|
const { spawn } = require("child_process");
|
||||||
const fs = require("fs");
|
const fs = require("fs");
|
||||||
const sizeOf = require("image-size");
|
const sizeOf = require("image-size");
|
||||||
|
const path = require('path');
|
||||||
const { autoUpdater } = require("electron-updater");
|
const { autoUpdater } = require("electron-updater");
|
||||||
const { getPlatform } = require("./getPlatform");
|
const { getPlatform } = require("./getPlatform");
|
||||||
|
|
||||||
@ -21,6 +22,7 @@ const {
|
|||||||
const isDev = require("electron-is-dev");
|
const isDev = require("electron-is-dev");
|
||||||
const prepareNext = require("electron-next");
|
const prepareNext = require("electron-next");
|
||||||
const commands = require("./commands");
|
const commands = require("./commands");
|
||||||
|
const tmpPath = path.join(app.getPath("userData"), "\\tmp\\");
|
||||||
|
|
||||||
// Prepare the renderer once the app is ready
|
// Prepare the renderer once the app is ready
|
||||||
let mainWindow;
|
let mainWindow;
|
||||||
@ -79,21 +81,49 @@ ipcMain.handle(commands.SELECT_FILE, async () => {
|
|||||||
return "cancelled";
|
return "cancelled";
|
||||||
} else {
|
} else {
|
||||||
console.log(filePaths[0]);
|
console.log(filePaths[0]);
|
||||||
// CREATE input AND upscaled FOLDER
|
// CREATE original copy
|
||||||
|
if(!fs.existsSync(tmpPath)) {
|
||||||
|
fs.mkdirSync(tmpPath);
|
||||||
|
}
|
||||||
|
fs.copyFileSync(filePaths[0], path.join(tmpPath, "original" + parse(filePaths[0]).ext));
|
||||||
return filePaths[0];
|
return filePaths[0];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.handle(commands.SELECT_FOLDER, async (event, message) => {
|
ipcMain.handle(commands.SET_FILE, async (event, payload) => {
|
||||||
const { canceled, filePaths } = await dialog.showOpenDialog({
|
const original = payload.original;
|
||||||
properties: ["openDirectory"],
|
const fileExt = parse(original).ext;
|
||||||
|
// CREATE original copy
|
||||||
|
if(!fs.existsSync(tmpPath)) {
|
||||||
|
fs.mkdirSync(tmpPath);
|
||||||
|
}
|
||||||
|
fs.copyFileSync(original, path.join(tmpPath, "original" + fileExt));
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
ipcMain.handle(commands.SELECT_OUTPUT, async (event, payload) => {
|
||||||
|
const original = payload.original;
|
||||||
|
const fileExt = parse(original).ext;
|
||||||
|
const { canceled, filePath } = await dialog.showSaveDialog({
|
||||||
|
filters: [{name: fileExt, extensions: [fileExt.substring(1)]}]
|
||||||
});
|
});
|
||||||
if (canceled) {
|
if (canceled) {
|
||||||
console.log("operation cancelled");
|
console.log("operation cancelled");
|
||||||
return "cancelled";
|
return "cancelled";
|
||||||
} else {
|
} else {
|
||||||
console.log(filePaths[0]);
|
console.log(filePath);
|
||||||
return filePaths[0];
|
if(fs.existsSync(tmpPath + "/scaled" + fileExt)) {
|
||||||
|
fs.copyFileSync(tmpPath + "/scaled" + fileExt, filePath);
|
||||||
|
}
|
||||||
|
return filePath;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ipcMain.handle(commands.REPLACE_ORIGINAL, async (event, payload) => {
|
||||||
|
const original = payload.original;
|
||||||
|
const fileExt = parse(original).ext;
|
||||||
|
if(fs.existsSync(tmpPath + "/scaled" + fileExt)) {
|
||||||
|
fs.copyFileSync(tmpPath + "/scaled" + fileExt, original);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -102,10 +132,10 @@ ipcMain.on(commands.UPSCAYL, async (event, payload) => {
|
|||||||
const scale = payload.scaleFactor;
|
const scale = payload.scaleFactor;
|
||||||
|
|
||||||
let inputDir = payload.imagePath.match(/(.*)[\/\\]/)[1] || "";
|
let inputDir = payload.imagePath.match(/(.*)[\/\\]/)[1] || "";
|
||||||
let outputDir = payload.outputPath;
|
let outputDir = tmpPath
|
||||||
console.log("🚀 => ipcMain.on => outputDir", outputDir);
|
console.log("🚀 => ipcMain.on => outputDir", outputDir);
|
||||||
|
|
||||||
// COPY IMAGE TO upscaled FOLDER
|
// COPY IMAGE TO TMP FOLDER
|
||||||
const platform = getPlatform();
|
const platform = getPlatform();
|
||||||
const fullfileName =
|
const fullfileName =
|
||||||
platform === "win"
|
platform === "win"
|
||||||
@ -121,9 +151,9 @@ ipcMain.on(commands.UPSCAYL, async (event, payload) => {
|
|||||||
execPath,
|
execPath,
|
||||||
[
|
[
|
||||||
"-i",
|
"-i",
|
||||||
inputDir + "/" + fullfileName,
|
tmpPath + "/original" + fileExt,
|
||||||
"-o",
|
"-o",
|
||||||
outputDir + "/" + fileName + "_upscayled_" + scale + "x" + fileExt,
|
tmpPath + "/scaled" + fileExt,
|
||||||
"-s",
|
"-s",
|
||||||
scale === 2 ? 4 : scale,
|
scale === 2 ? 4 : scale,
|
||||||
"-m",
|
"-m",
|
||||||
@ -151,7 +181,7 @@ ipcMain.on(commands.UPSCAYL, async (event, payload) => {
|
|||||||
console.log("Done upscaling");
|
console.log("Done upscaling");
|
||||||
mainWindow.webContents.send(
|
mainWindow.webContents.send(
|
||||||
commands.UPSCAYL_DONE,
|
commands.UPSCAYL_DONE,
|
||||||
outputDir + "/" + fileName + "_upscayled_" + scale + "x" + fileExt
|
outputDir + "/scaled" + fileExt
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -14,6 +14,7 @@ const Home = () => {
|
|||||||
const [outputPath, SetOutputPath] = useState("");
|
const [outputPath, SetOutputPath] = useState("");
|
||||||
const [scaleFactor, setScaleFactor] = useState(4);
|
const [scaleFactor, setScaleFactor] = useState(4);
|
||||||
const [progress, setProgress] = useState("");
|
const [progress, setProgress] = useState("");
|
||||||
|
const [curStep, setStep] = useState(1);
|
||||||
const [model, setModel] = useState("realesrgan-x4plus");
|
const [model, setModel] = useState("realesrgan-x4plus");
|
||||||
const [loaded, setLoaded] = useState(false);
|
const [loaded, setLoaded] = useState(false);
|
||||||
const [version, setVersion] = useState("");
|
const [version, setVersion] = useState("");
|
||||||
@ -22,8 +23,13 @@ const Home = () => {
|
|||||||
setProgress("");
|
setProgress("");
|
||||||
SetImagePath("");
|
SetImagePath("");
|
||||||
setUpscaledImagePath("");
|
setUpscaledImagePath("");
|
||||||
|
setStep(1);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const stepStyle = (thisStep) => {
|
||||||
|
return { display: (thisStep > curStep ? "none" : "block") };
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setVersion(navigator.userAgent.match(/Upscayl\/([\d\.]+\d+)/)[1]);
|
setVersion(navigator.userAgent.match(/Upscayl\/([\d\.]+\d+)/)[1]);
|
||||||
}, []);
|
}, []);
|
||||||
@ -48,6 +54,7 @@ const Home = () => {
|
|||||||
window.electron.on(commands.UPSCAYL_DONE, (_, data) => {
|
window.electron.on(commands.UPSCAYL_DONE, (_, data) => {
|
||||||
setProgress("");
|
setProgress("");
|
||||||
setUpscaledImagePath(data);
|
setUpscaledImagePath(data);
|
||||||
|
setStep(4);
|
||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
@ -59,6 +66,7 @@ const Home = () => {
|
|||||||
SetImagePath(path);
|
SetImagePath(path);
|
||||||
var dirname = path.match(/(.*)[\/\\]/)[1] || "";
|
var dirname = path.match(/(.*)[\/\\]/)[1] || "";
|
||||||
SetOutputPath(dirname);
|
SetOutputPath(dirname);
|
||||||
|
setStep(3);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -101,6 +109,8 @@ const Home = () => {
|
|||||||
SetImagePath(filePath);
|
SetImagePath(filePath);
|
||||||
var dirname = filePath.match(/(.*)[\/\\]/)[1] || "";
|
var dirname = filePath.match(/(.*)[\/\\]/)[1] || "";
|
||||||
SetOutputPath(dirname);
|
SetOutputPath(dirname);
|
||||||
|
setStep(3);
|
||||||
|
window.electron.invoke(commands.SET_FILE, {original: filePath});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -121,11 +131,21 @@ const Home = () => {
|
|||||||
SetImagePath(filePath);
|
SetImagePath(filePath);
|
||||||
var dirname = filePath.match(/(.*)[\/\\]/)[1] || "";
|
var dirname = filePath.match(/(.*)[\/\\]/)[1] || "";
|
||||||
SetOutputPath(dirname);
|
SetOutputPath(dirname);
|
||||||
|
setStep(3);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const outputHandler = async () => {
|
const outputHandler = async () => {
|
||||||
var path = await window.electron.invoke(commands.SELECT_FOLDER);
|
var path = await window.electron.invoke(commands.SELECT_OUTPUT, { original: imagePath });
|
||||||
|
if (path !== "cancelled") {
|
||||||
|
SetOutputPath(path);
|
||||||
|
} else {
|
||||||
|
console.log("Getting output path from input file");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const replaceHandler = async () => {
|
||||||
|
var path = await window.electron.invoke(commands.REPLACE_ORIGINAL, { original: imagePath });
|
||||||
if (path !== "cancelled") {
|
if (path !== "cancelled") {
|
||||||
SetOutputPath(path);
|
SetOutputPath(path);
|
||||||
} else {
|
} else {
|
||||||
@ -169,17 +189,17 @@ const Home = () => {
|
|||||||
{/* LEFT PANE */}
|
{/* LEFT PANE */}
|
||||||
<div className="h-screen overflow-auto p-5">
|
<div className="h-screen overflow-auto p-5">
|
||||||
{/* STEP 1 */}
|
{/* STEP 1 */}
|
||||||
<div className="mt-5">
|
<div className="mt-0">
|
||||||
<p className="mb-2 font-medium text-neutral-100">Step 1</p>
|
<p className="mb-2 font-medium text-neutral-100">Step 1</p>
|
||||||
<button
|
<button
|
||||||
className="rounded-lg bg-rose-400 p-3"
|
className="rounded-lg bg-rose-400 hover:bg-rose-300 transition-colors p-3 w-full font-semibold"
|
||||||
onClick={selectImageHandler}
|
onClick={selectImageHandler}
|
||||||
>
|
>
|
||||||
Select Image
|
Select Image
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
{/* STEP 2 */}
|
{/* STEP 2 */}
|
||||||
<div className="mt-10">
|
<div className="mt-5 animate-step-in" style={stepStyle(3)}>
|
||||||
<p className="font-medium text-neutral-100">Step 2</p>
|
<p className="font-medium text-neutral-100">Step 2</p>
|
||||||
<p className="mb-2 text-sm text-neutral-400">
|
<p className="mb-2 text-sm text-neutral-400">
|
||||||
Select Upscaling Type
|
Select Upscaling Type
|
||||||
@ -187,14 +207,26 @@ const Home = () => {
|
|||||||
<select
|
<select
|
||||||
name="select-model"
|
name="select-model"
|
||||||
onDrop={(e) => handleDrop(e)}
|
onDrop={(e) => handleDrop(e)}
|
||||||
className="rounded-lg bg-slate-300 p-3"
|
className="rounded-lg bg-slate-300 hover:bg-slate-200 p-3 w-full"
|
||||||
onChange={handleModelChange}
|
onChange={handleModelChange}
|
||||||
>
|
>
|
||||||
<option value="realesrgan-x4plus">General Photo</option>
|
<option value="realesrgan-x4plus">Photos & Realistic Art</option>
|
||||||
<option value="realesrgan-x4plus-anime">Digital Art</option>
|
<option value="realesrgan-x4plus-anime">2D & Simple Art</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* STEP 3 */}
|
||||||
|
<div className="mt-5 animate-step-in" style={stepStyle(3)}>
|
||||||
|
<p className="mb-2 font-medium text-neutral-100">Step 3</p>
|
||||||
|
<button
|
||||||
|
className="rounded-lg bg-sky-400 hover:bg-sky-300 transition-colors p-3 w-full font-semibold"
|
||||||
|
onClick={upscaylHandler}
|
||||||
|
disabled={progress.length > 0}
|
||||||
|
>
|
||||||
|
{progress.length > 0 ? "Upscayling⏳" : "Upscayl"}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* STEP 3
|
{/* STEP 3
|
||||||
<div className="mt-10">
|
<div className="mt-10">
|
||||||
<p className="font-medium text-neutral-100">Step 3</p>
|
<p className="font-medium text-neutral-100">Step 3</p>
|
||||||
@ -227,29 +259,23 @@ const Home = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div> */}
|
</div> */}
|
||||||
|
|
||||||
{/* STEP 3 */}
|
{/* STEP 4 */}
|
||||||
<div className="mt-10">
|
<div className="mt-5 animate-step-in" style={stepStyle(4)}>
|
||||||
<p className="font-medium text-neutral-100">Step 3</p>
|
<p className="font-medium text-neutral-100">Step 4</p>
|
||||||
<p className="mb-2 text-sm text-neutral-400">
|
<p className="mb-2 text-sm text-neutral-400">
|
||||||
Defaults to Image's path
|
Save file
|
||||||
</p>
|
</p>
|
||||||
<button
|
<button
|
||||||
className="rounded-lg bg-teal-400 p-3"
|
className="rounded-lg bg-teal-400 hover:bg-teal-300 transition-colors p-3 w-full font-semibold"
|
||||||
|
onClick={replaceHandler}
|
||||||
|
>
|
||||||
|
Replace Original
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className="rounded-lg bg-teal-400 hover:bg-teal-300 transition-colors p-3 mt-1 w-full font-semibold"
|
||||||
onClick={outputHandler}
|
onClick={outputHandler}
|
||||||
>
|
>
|
||||||
Set Output Folder
|
Save As
|
||||||
</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}
|
|
||||||
disabled={progress.length > 0}
|
|
||||||
>
|
|
||||||
{progress.length > 0 ? "Upscayling⏳" : "Upscayl"}
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -295,8 +321,8 @@ const Home = () => {
|
|||||||
onDragLeave={(e) => handleDragLeave(e)}
|
onDragLeave={(e) => handleDragLeave(e)}
|
||||||
onPaste={(e) => handlePaste(e)}
|
onPaste={(e) => handlePaste(e)}
|
||||||
>
|
>
|
||||||
{progress.length > 0 && upscaledImagePath.length === 0 && (
|
{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="absolute flex h-full w-full flex-col items-center justify-center bg-black/50 backdrop-blur-lg z-10">
|
||||||
<div className="flex flex-col items-center gap-2">
|
<div className="flex flex-col items-center gap-2">
|
||||||
<Image src={Animated} />
|
<Image src={Animated} />
|
||||||
<p className="font-bold text-neutral-50">{progress}</p>
|
<p className="font-bold text-neutral-50">{progress}</p>
|
||||||
@ -309,7 +335,7 @@ const Home = () => {
|
|||||||
<p className="p-5 text-lg font-medium text-neutral-400">
|
<p className="p-5 text-lg font-medium text-neutral-400">
|
||||||
Select an Image to Upscale
|
Select an Image to Upscale
|
||||||
</p>
|
</p>
|
||||||
<p className="text-neutral-600">Upscale v{version}</p>
|
<p className="text-neutral-600">Upscayl v{version}</p>
|
||||||
</>
|
</>
|
||||||
) : upscaledImagePath.length === 0 ? (
|
) : upscaledImagePath.length === 0 ? (
|
||||||
<img
|
<img
|
||||||
@ -324,7 +350,7 @@ const Home = () => {
|
|||||||
<ReactCompareSlider
|
<ReactCompareSlider
|
||||||
itemOne={
|
itemOne={
|
||||||
<ReactCompareSliderImage
|
<ReactCompareSliderImage
|
||||||
src={"file://" + imagePath}
|
src={"file://" + imagePath + "?" + Date.now()}
|
||||||
alt="Original"
|
alt="Original"
|
||||||
style={{
|
style={{
|
||||||
objectFit: "contain",
|
objectFit: "contain",
|
||||||
@ -333,7 +359,7 @@ const Home = () => {
|
|||||||
}
|
}
|
||||||
itemTwo={
|
itemTwo={
|
||||||
<ReactCompareSliderImage
|
<ReactCompareSliderImage
|
||||||
src={"file://" + upscaledImagePath}
|
src={"file://" + upscaledImagePath + "?" + Date.now()}
|
||||||
alt="Upscayl"
|
alt="Upscayl"
|
||||||
style={{
|
style={{
|
||||||
objectFit: "contain",
|
objectFit: "contain",
|
||||||
|
@ -26,3 +26,13 @@
|
|||||||
@apply transition-all duration-300 ease-in-out;
|
@apply transition-all duration-300 ease-in-out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.animate-step-in {
|
||||||
|
animation: animate-step-in 0.35s cubic-bezier(0.07, 0.43, 0.02, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes animate-step-in {
|
||||||
|
0% { opacity: 0; transform: translateY(-10px); }
|
||||||
|
80% { opacity: 1; }
|
||||||
|
100% { opacity: 1; transform: translateY(0px); }
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user