1
0
mirror of https://github.com/upscayl/upscayl.git synced 2025-02-17 11:18:36 +01:00

Added video pane

This commit is contained in:
Feenix 2022-11-23 23:54:30 +05:30
parent 397563bf23
commit f9a2f0a027
10 changed files with 328 additions and 133 deletions

View File

@ -12,6 +12,7 @@ const commands = {
FOLDER_UPSCAYL_PROGRESS:
"Send Folder Upscaling Progress from Main to Renderer",
OPEN_FOLDER: "Open Folder",
SELECT_VIDEO: "Select a Video",
};
export default commands;

View File

@ -6,6 +6,7 @@ import fs from "fs";
import sizeOf from "image-size";
import { autoUpdater } from "electron-updater";
import getPlatform from "./getPlatform";
import ffmpeg from "upscayl-ffmpeg";
import { execPath, modelsPath } from "./binaries";
@ -29,10 +30,10 @@ let mainWindow;
app.on("ready", async () => {
await prepareNext("./renderer");
console.log("🚀 Icon Path: ", join(__dirname, "build", "icon.png"));
console.log("🚀 Development Mode? :", isDev);
console.log("🚀 RS Executable Path: ", execPath(""));
console.log("🚀 Models: ", modelsPath);
console.log("🚀 ICON PATH: ", join(__dirname, "build", "icon.png"));
console.log("🚀 UPSCAYL EXEC PATH: ", execPath(""));
console.log("🚀 MODELS PATH: ", modelsPath);
console.log("🚀 FFMPEG PATH: ", ffmpeg.path);
mainWindow = new BrowserWindow({
icon: join(__dirname, "build", "icon.png"),

View File

@ -19,6 +19,7 @@ const child_process_1 = require("child_process");
const fs_1 = __importDefault(require("fs"));
const electron_updater_1 = require("electron-updater");
const getPlatform_1 = __importDefault(require("./getPlatform"));
const upscayl_ffmpeg_1 = __importDefault(require("upscayl-ffmpeg"));
const binaries_1 = require("./binaries");
// Packages
const electron_1 = require("electron");
@ -29,10 +30,10 @@ const commands_1 = __importDefault(require("./commands"));
let mainWindow;
electron_1.app.on("ready", () => __awaiter(void 0, void 0, void 0, function* () {
yield (0, electron_next_1.default)("./renderer");
console.log("🚀 Icon Path: ", (0, path_1.join)(__dirname, "build", "icon.png"));
console.log("🚀 Development Mode? :", electron_is_dev_1.default);
console.log("🚀 RS Executable Path: ", (0, binaries_1.execPath)(""));
console.log("🚀 Models: ", binaries_1.modelsPath);
console.log("🚀 ICON PATH: ", (0, path_1.join)(__dirname, "build", "icon.png"));
console.log("🚀 UPSCAYL EXEC PATH: ", (0, binaries_1.execPath)(""));
console.log("🚀 MODELS PATH: ", binaries_1.modelsPath);
console.log("🚀 FFMPEG PATH: ", upscayl_ffmpeg_1.default.path);
mainWindow = new electron_1.BrowserWindow({
icon: (0, path_1.join)(__dirname, "build", "icon.png"),
width: 1100,

View File

@ -1,7 +1,7 @@
{
"name": "upscayl",
"private": true,
"version": "1.5.5",
"version": "2.0.0",
"productName": "Upscayl",
"homepage": "https://github.com/TGS963/upscayl",
"contributors": [
@ -155,8 +155,9 @@
"react-image-zoom": "^1.3.1",
"react-magnifier": "^3.0.4",
"react-select": "^5.6.0",
"react-tooltip": "^4.4.3",
"tailwind-scrollbar": "^2.0.1"
"react-tooltip": "^4.5.0",
"tailwind-scrollbar": "^2.0.1",
"upscayl-ffmpeg": "^5.1.0"
},
"volta": {
"node": "16.17.0"

View File

@ -0,0 +1,20 @@
import React from "react";
const ImageOptions = () => {
return (
<div className="animate rounded-btn collapse absolute top-0 z-50 m-2 w-96 opacity-25 hover:opacity-100">
<input type="checkbox" className="peer" />
<div className="collapse-title bg-base-100 text-center text-sm font-semibold uppercase text-primary-content peer-checked:bg-base-300 peer-checked:text-base-content">
Show/Hide Image Settings
</div>
<div className="collapse-content bg-base-100 text-base-content">
<div className="p-5">
<button className="btn-primary btn">Start Again</button>
</div>
</div>
</div>
);
};
export default ImageOptions;

View File

@ -21,7 +21,7 @@ interface IProps {
setIsVideo: (arg: boolean) => void;
}
function LeftPaneSteps({
function LeftPaneImageSteps({
progress,
selectImageHandler,
selectFolderHandler,
@ -70,38 +70,17 @@ function LeftPaneSteps({
return (
<div className="animate-step-in animate flex h-screen flex-col gap-7 overflow-y-auto p-5 overflow-x-hidden">
<div className="flex items-center justify-center gap-2 font-medium">
<p>Image</p>
<input
type="radio"
name="radio-1"
className="radio"
checked={!isVideo}
onClick={() => setIsVideo(false)}
/>
<input
type="radio"
name="radio-1"
className="radio"
checked={isVideo}
onClick={() => setIsVideo(true)}
/>
<p>Video</p>
</div>
{/* BATCH OPTION */}
<div className="flex flex-row items-center gap-2">
<input
type="checkbox"
className="toggle"
onClick={handleBatchMode}
></input>
<div
className="tooltip tooltip-right relative z-50"
data-tip="This will let you upscale all files in a folder at once"
>
<p className="mr-1 inline-block cursor-help text-sm">Batch Upscale</p>
</div>
onClick={handleBatchMode}></input>
<p
className="mr-1 inline-block cursor-help text-sm"
data-tip="This will let you upscale all files in a folder at once">
Batch Upscale
</p>
</div>
{/* STEP 1 */}
@ -109,8 +88,7 @@ function LeftPaneSteps({
<p className="step-heading">Step 1</p>
<button
className="btn-primary btn"
onClick={!batchMode ? selectImageHandler : selectFolderHandler}
>
onClick={!batchMode ? selectImageHandler : selectFolderHandler}>
Select {batchMode ? "Folder" : "Image"}
</button>
</div>
@ -133,7 +111,7 @@ function LeftPaneSteps({
/>
{model !== "models-DF2K" && !batchMode && (
<div className="mt-2 flex items-center gap-1">
<div className="mt-4 flex items-center gap-1">
<input
type="checkbox"
className="checkbox"
@ -150,16 +128,14 @@ function LeftPaneSteps({
className="cursor-pointer text-sm"
onClick={(e) => {
setDoubleUpscayl(!doubleUpscayl);
}}
>
}}>
Double Upscayl
</p>
<div
className="tooltip"
data-tip="Enable this option to get an 8x upscayl. Note that this may not always work properly with all images, for example, images with really large resolutions."
>
<span className="badge-info badge cursor-help">i</span>
</div>
<button
className="badge-info badge cursor-help"
data-tip="Enable this option to get an 8x upscayl. Note that this may not always work properly with all images, for example, images with really large resolutions.">
i
</button>
</div>
)}
</div>
@ -173,30 +149,20 @@ function LeftPaneSteps({
</button>
</div>
{/* ADVANCED OPTION */}
<div className="flex flex-row items-center gap-2">
<input type="checkbox" className="checkbox" onClick={handleBatchMode} />
<p
className="mr-1 inline-block cursor-help text-sm"
data-tip="This will let you upscale all files in a folder at once"
>
Advanced Options
</p>
</div>
{/* STEP 4 */}
<div className="animate-step-in">
<p className="step-heading">Step 4</p>
<button
className="btn-accent btn"
onClick={upscaylHandler}
disabled={progress.length > 0}
>
disabled={progress.length > 0}>
{progress.length > 0 ? "Upscayling⏳" : "Upscayl"}
</button>
</div>
<ReactTooltip class="max-w-sm" />
</div>
);
}
export default LeftPaneSteps;
export default LeftPaneImageSteps;

View File

@ -0,0 +1,108 @@
import React from "react";
import Select from "react-select";
import ReactTooltip from "react-tooltip";
interface IProps {
progress: string;
selectImageHandler: () => Promise<void>;
selectFolderHandler: () => Promise<void>;
handleModelChange: (e: any) => void;
handleDrop: (e: any) => void;
outputHandler: () => Promise<void>;
upscaylHandler: () => Promise<void>;
batchMode: boolean;
setBatchMode: (arg: any) => void;
imagePath: string;
outputPath: string;
doubleUpscayl: boolean;
setDoubleUpscayl: (arg: boolean) => void;
model: string;
isVideo: boolean;
setIsVideo: (arg: boolean) => void;
}
function LeftPaneVideoSteps({
progress,
selectImageHandler,
selectFolderHandler,
handleModelChange,
handleDrop,
outputHandler,
upscaylHandler,
batchMode,
setBatchMode,
imagePath,
outputPath,
doubleUpscayl,
setDoubleUpscayl,
model,
isVideo,
setIsVideo,
}: IProps) {
const handleBatchMode = () => {
setBatchMode((oldValue) => !oldValue);
};
const customStyles = {
option: (provided, state) => ({
...provided,
borderBottom: "1px dotted pink",
color: state.isSelected ? "red" : "blue",
padding: 20,
}),
control: () => ({
// none of react-select's styles are passed to <Control />
width: 200,
}),
singleValue: (provided, state) => {
const opacity = state.isDisabled ? 0.5 : 1;
const transition = "opacity 300ms";
return { ...provided, opacity, transition };
},
};
const modelOptions = [
{ label: "General Photo", value: "realesrgan-x4plus" },
{ label: "Digital Art", value: "realesrgan-x4plus-anime" },
{ label: "Sharpen Image", value: "models-DF2K" },
];
return (
<div className="animate-step-in animate flex h-screen flex-col gap-7 overflow-y-auto p-5 overflow-x-hidden">
{/* STEP 1 */}
<div data-tip={imagePath}>
<p className="step-heading">Step 1</p>
<button
className="btn-primary btn"
onClick={!batchMode ? selectImageHandler : selectFolderHandler}>
Select Video
</button>
</div>
{/* STEP 2 */}
<div className="animate-step-in" data-tip={outputPath}>
<p className="step-heading">Step 2</p>
<p className="mb-2 text-sm">Defaults to Video's path</p>
<button className="btn-primary btn" onClick={outputHandler}>
Set Output Folder
</button>
</div>
{/* STEP 4 */}
<div className="animate-step-in">
<p className="step-heading">Step 4</p>
<button
className="btn-accent btn"
onClick={upscaylHandler}
disabled={progress.length > 0}>
{progress.length > 0 ? "Upscayling⏳" : "Upscayl"}
</button>
</div>
<ReactTooltip class="max-w-sm" />
</div>
);
}
export default LeftPaneVideoSteps;

View File

@ -8,13 +8,16 @@ import Header from "../components/Header";
import Footer from "../components/Footer";
import ProgressBar from "../components/ProgressBar";
import ResetButton from "../components/ResetButton";
import LeftPaneSteps from "../components/LeftPaneSteps";
import LeftPaneSteps from "../components/LeftPaneImageSteps";
import RightPaneInfo from "../components/RightPaneInfo";
import ImageOptions from "../components/ImageOptions";
import LeftPaneVideoSteps from "../components/LeftPaneVideoSteps";
import LeftPaneImageSteps from "../components/LeftPaneImageSteps";
const Home = () => {
const [imagePath, SetImagePath] = useState("");
const [upscaledImagePath, setUpscaledImagePath] = useState("");
const [outputPath, SetOutputPath] = useState("");
const [outputPath, setOutputPath] = useState("");
const [scaleFactor, setScaleFactor] = useState(4);
const [progress, setProgress] = useState("");
const [model, setModel] = useState("realesrgan-x4plus");
@ -25,6 +28,8 @@ const Home = () => {
const [upscaledBatchFolderPath, setUpscaledBatchFolderPath] = useState("");
const [doubleUpscayl, setDoubleUpscayl] = useState(false);
const [isVideo, setIsVideo] = useState(false);
const [videoPath, setVideoPath] = useState("");
const [upscaledVideoPath, setUpscaledVideoPath] = useState("");
const resetImagePaths = () => {
setProgress("");
@ -38,7 +43,6 @@ const Home = () => {
useEffect(() => {
setLoaded(true);
const prefersDarkScheme = window.matchMedia("(prefers-color-scheme: dark)");
setVersion(navigator?.userAgent?.match(/Upscayl\/([\d\.]+\d+)/)[1]);
@ -127,6 +131,18 @@ const Home = () => {
}
}, [imagePath]);
const selectVideoHandler = async () => {
resetImagePaths();
var path = await window.electron.invoke(commands.SELECT_VIDEO);
if (path !== "cancelled") {
setVideoPath(path);
var dirname = path.match(/(.*)[\/\\]/)[1] || "";
setOutputPath(dirname);
}
};
const selectImageHandler = async () => {
resetImagePaths();
@ -135,7 +151,7 @@ const Home = () => {
if (path !== "cancelled") {
SetImagePath(path);
var dirname = path.match(/(.*)[\/\\]/)[1] || "";
SetOutputPath(dirname);
setOutputPath(dirname);
}
};
@ -146,7 +162,7 @@ const Home = () => {
if (path !== "cancelled") {
setBatchFolderPath(path);
SetOutputPath(path + "_upscayled");
setOutputPath(path + "_upscayled");
}
};
@ -195,7 +211,7 @@ const Home = () => {
SetImagePath(filePath);
var dirname = filePath.match(/(.*)[\/\\]/)[1] || "";
console.log("🚀 => handleDrop => dirname", dirname);
SetOutputPath(dirname);
setOutputPath(dirname);
}
};
@ -215,14 +231,14 @@ const Home = () => {
} else {
SetImagePath(filePath);
var dirname = filePath.match(/(.*)[\/\\]/)[1] || "";
SetOutputPath(dirname);
setOutputPath(dirname);
}
};
const outputHandler = async () => {
var path = await window.electron.invoke(commands.SELECT_FOLDER);
if (path !== "cancelled") {
SetOutputPath(path);
setOutputPath(path);
} else {
console.log("Getting output path from input file");
}
@ -272,27 +288,64 @@ const Home = () => {
)}
{/* HEADER */}
<Header />
<div className="flex items-center justify-center gap-2 pb-4 font-medium">
<p>Image</p>
<input
type="radio"
name="radio-1"
className="radio"
checked={!isVideo}
onChange={() => setIsVideo(false)}
/>
<input
type="radio"
name="radio-1"
className="radio"
checked={isVideo}
onChange={() => setIsVideo(true)}
/>
<p>Video</p>
</div>
{/* LEFT PANE */}
<LeftPaneSteps
progress={progress}
selectImageHandler={selectImageHandler}
selectFolderHandler={selectFolderHandler}
handleModelChange={handleModelChange}
handleDrop={handleDrop}
outputHandler={outputHandler}
upscaylHandler={upscaylHandler}
batchMode={batchMode}
setBatchMode={setBatchMode}
imagePath={imagePath}
outputPath={outputPath}
doubleUpscayl={doubleUpscayl}
setDoubleUpscayl={setDoubleUpscayl}
model={model}
isVideo={isVideo}
setIsVideo={setIsVideo}
/>
{isVideo ? (
<LeftPaneVideoSteps
progress={progress}
selectImageHandler={selectImageHandler}
selectFolderHandler={selectFolderHandler}
handleModelChange={handleModelChange}
handleDrop={handleDrop}
outputHandler={outputHandler}
upscaylHandler={upscaylHandler}
batchMode={batchMode}
setBatchMode={setBatchMode}
imagePath={imagePath}
outputPath={outputPath}
doubleUpscayl={doubleUpscayl}
setDoubleUpscayl={setDoubleUpscayl}
model={model}
isVideo={isVideo}
setIsVideo={setIsVideo}
/>
) : (
<LeftPaneImageSteps
progress={progress}
selectImageHandler={selectImageHandler}
selectFolderHandler={selectFolderHandler}
handleModelChange={handleModelChange}
handleDrop={handleDrop}
outputHandler={outputHandler}
upscaylHandler={upscaylHandler}
batchMode={batchMode}
setBatchMode={setBatchMode}
imagePath={imagePath}
outputPath={outputPath}
doubleUpscayl={doubleUpscayl}
setDoubleUpscayl={setDoubleUpscayl}
model={model}
isVideo={isVideo}
setIsVideo={setIsVideo}
/>
)}
<Footer />
</div>
@ -303,8 +356,7 @@ const Home = () => {
onDragOver={(e) => handleDragOver(e)}
onDragEnter={(e) => handleDragEnter(e)}
onDragLeave={(e) => handleDragLeave(e)}
onPaste={(e) => handlePaste(e)}
>
onPaste={(e) => handlePaste(e)}>
{progress.length > 0 &&
upscaledImagePath.length === 0 &&
upscaledBatchFolderPath.length === 0 ? (
@ -349,47 +401,49 @@ const Home = () => {
</p>
<button
className="bg-gradient-blue rounded-lg p-3 font-medium text-white/90 transition-colors"
onClick={openFolderHandler}
>
onClick={openFolderHandler}>
Open Upscayled Folder
</button>
</>
)}
{!batchMode && imagePath.length > 0 && upscaledImagePath.length > 0 && (
<ReactCompareSlider
itemOne={
<>
<p className="absolute bottom-1 left-1 rounded-md bg-black p-1 text-sm font-medium text-white opacity-30">
Original
</p>
<ReactCompareSliderImage
src={"file://" + imagePath}
alt="Original"
style={{
objectFit: "contain",
}}
className="bg-[#1d1c23]"
/>
</>
}
itemTwo={
<>
<p className="absolute bottom-1 right-1 rounded-md bg-black p-1 text-sm font-medium text-white opacity-30">
Upscayled
</p>
<ReactCompareSliderImage
src={"file://" + upscaledImagePath}
alt="Upscayl"
style={{
objectFit: "contain",
}}
className="origin-bottom scale-[200%] bg-[#1d1c23]"
/>
</>
}
className="h-screen"
/>
<>
<ImageOptions />
<ReactCompareSlider
itemOne={
<>
<p className="absolute bottom-1 left-1 rounded-md bg-black p-1 text-sm font-medium text-white opacity-30">
Original
</p>
<ReactCompareSliderImage
src={"file://" + imagePath}
alt="Original"
style={{
objectFit: "contain",
}}
className="bg-[#1d1c23]"
/>
</>
}
itemTwo={
<>
<p className="absolute bottom-1 right-1 rounded-md bg-black p-1 text-sm font-medium text-white opacity-30">
Upscayled
</p>
<ReactCompareSliderImage
src={"file://" + upscaledImagePath}
alt="Upscayl"
style={{
objectFit: "contain",
}}
className="origin-bottom scale-[200%] bg-[#1d1c23]"
/>
</>
}
className="h-screen"
/>
</>
)}
</div>
</div>

View File

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" fill="#fff"
viewBox="0 0 330 330" xml:space="preserve">
<path id="XMLID_225_" d="M325.607,79.393c-5.857-5.857-15.355-5.858-21.213,0.001l-139.39,139.393L25.607,79.393
c-5.857-5.857-15.355-5.858-21.213,0.001c-5.858,5.858-5.858,15.355,0,21.213l150.004,150c2.813,2.813,6.628,4.393,10.606,4.393
s7.794-1.581,10.606-4.394l149.996-150C331.465,94.749,331.465,85.251,325.607,79.393z"/>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 826 B

View File

@ -2407,10 +2407,10 @@ react-select@^5.6.0:
react-transition-group "^4.3.0"
use-isomorphic-layout-effect "^1.1.2"
react-tooltip@^4.4.3:
version "4.4.3"
resolved "https://registry.yarnpkg.com/react-tooltip/-/react-tooltip-4.4.3.tgz#44cbb6c8bdb3281c2819d16c92e3c419ebd98582"
integrity sha512-l7/TDBwq3JtuLBtq6FvIs7wsqcHjvoHFT8AvNGpf0JhHwzh+ZhCDN25wM/+gxelj8i1ngw/ULFv53XRQ/wCMzQ==
react-tooltip@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/react-tooltip/-/react-tooltip-4.5.0.tgz#862a39fbb05522624fb6efa782b245a89a0db784"
integrity sha512-mJNurq29atce+TJc9Xe+/FHrcEs3K9J7wkjZZXwbK5Yq6uG5SZeKSFHwd0wcRPUipVwx5crmgzSW8Zu1xyvLTQ==
dependencies:
prop-types "^15.8.1"
uuid "^7.0.3"
@ -2877,6 +2877,11 @@ update-browserslist-db@^1.0.9:
escalade "^3.1.1"
picocolors "^1.0.0"
upscayl-ffmpeg@^5.1.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/upscayl-ffmpeg/-/upscayl-ffmpeg-5.1.0.tgz#6fe3355338bb8304bf52bcf9703124d2c07b97a9"
integrity sha512-l3klTtO7h6rxC8SwMHQRBmmQoxNhz+dAyWjTlNOkYN1imLL1PXIN/Tqm1wM15M1x7Ax8H9SvNyQy52hhzaY2Yg==
uri-js@^4.2.2:
version "4.4.1"
resolved "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz"