mirror of
https://github.com/upscayl/upscayl.git
synced 2024-12-03 03:27:25 +01:00
277 lines
8.3 KiB
TypeScript
277 lines
8.3 KiB
TypeScript
import { useAtomValue } from "jotai";
|
|
import React, { useCallback, useEffect, useMemo, useState } from "react";
|
|
import Select from "react-select";
|
|
import { Tooltip } from "react-tooltip";
|
|
import { themeChange } from "theme-change";
|
|
import { modelsListAtom } from "../../../atoms/modelsListAtom";
|
|
import useLog from "../../hooks/useLog";
|
|
import {
|
|
noImageProcessingAtom,
|
|
scaleAtom,
|
|
} from "../../../atoms/userSettingsAtom";
|
|
|
|
interface IProps {
|
|
progress: string;
|
|
selectImageHandler: () => Promise<void>;
|
|
selectFolderHandler: () => Promise<void>;
|
|
handleModelChange: (e: any) => void;
|
|
outputHandler: () => Promise<void>;
|
|
upscaylHandler: () => Promise<void>;
|
|
batchMode: boolean;
|
|
setBatchMode: React.Dispatch<React.SetStateAction<boolean>>;
|
|
imagePath: string;
|
|
outputPath: string;
|
|
doubleUpscayl: boolean;
|
|
setDoubleUpscayl: React.Dispatch<React.SetStateAction<boolean>>;
|
|
dimensions: {
|
|
width: number | null;
|
|
height: number | null;
|
|
};
|
|
setSaveImageAs: React.Dispatch<React.SetStateAction<string>>;
|
|
model: string;
|
|
setModel: React.Dispatch<React.SetStateAction<string>>;
|
|
setGpuId: React.Dispatch<React.SetStateAction<string>>;
|
|
}
|
|
|
|
function LeftPaneImageSteps({
|
|
progress,
|
|
selectImageHandler,
|
|
selectFolderHandler,
|
|
handleModelChange,
|
|
outputHandler,
|
|
upscaylHandler,
|
|
batchMode,
|
|
setBatchMode,
|
|
imagePath,
|
|
outputPath,
|
|
doubleUpscayl,
|
|
setDoubleUpscayl,
|
|
dimensions,
|
|
setSaveImageAs,
|
|
model,
|
|
setModel,
|
|
setGpuId,
|
|
}: IProps) {
|
|
const [currentModel, setCurrentModel] = useState<{
|
|
label: string;
|
|
value: string;
|
|
}>({
|
|
label: null,
|
|
value: null,
|
|
});
|
|
|
|
const modelOptions = useAtomValue(modelsListAtom);
|
|
const scale = useAtomValue(scaleAtom);
|
|
const noImageProcessing = useAtomValue(noImageProcessingAtom);
|
|
|
|
const { logit } = useLog();
|
|
|
|
useEffect(() => {
|
|
themeChange(false);
|
|
|
|
if (!localStorage.getItem("saveImageAs")) {
|
|
logit("⚙️ Setting saveImageAs to png");
|
|
localStorage.setItem("saveImageAs", "png");
|
|
} else {
|
|
const currentlySavedImageFormat = localStorage.getItem("saveImageAs");
|
|
logit(
|
|
"⚙️ Getting saveImageAs from localStorage: ",
|
|
currentlySavedImageFormat
|
|
);
|
|
setSaveImageAs(currentlySavedImageFormat);
|
|
}
|
|
|
|
if (!localStorage.getItem("model")) {
|
|
setCurrentModel(modelOptions[0]);
|
|
setModel(modelOptions[0].value);
|
|
localStorage.setItem("model", JSON.stringify(modelOptions[0]));
|
|
logit("🔀 Setting model to", modelOptions[0].value);
|
|
} else {
|
|
const currentlySavedModel = JSON.parse(
|
|
localStorage.getItem("model")
|
|
) as (typeof modelOptions)[0];
|
|
setCurrentModel(currentlySavedModel);
|
|
setModel(currentlySavedModel.value);
|
|
logit(
|
|
"⚙️ Getting model from localStorage: ",
|
|
JSON.stringify(currentlySavedModel)
|
|
);
|
|
}
|
|
|
|
if (!localStorage.getItem("gpuId")) {
|
|
localStorage.setItem("gpuId", "");
|
|
logit("⚙️ Setting gpuId to empty string");
|
|
} else {
|
|
const currentlySavedGpuId = localStorage.getItem("gpuId");
|
|
setGpuId(currentlySavedGpuId);
|
|
logit("⚙️ Getting gpuId from localStorage: ", currentlySavedGpuId);
|
|
}
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
logit("🔀 Setting model to", currentModel.value);
|
|
}, [currentModel]);
|
|
|
|
const getUpscaleResolution = useCallback(() => {
|
|
const newDimensions = {
|
|
width: dimensions.width,
|
|
height: dimensions.height,
|
|
};
|
|
|
|
let doubleScale = parseInt(scale) * parseInt(scale);
|
|
let singleScale = parseInt(scale);
|
|
|
|
if (noImageProcessing) {
|
|
let initialScale = 4;
|
|
if (model.includes("x2")) {
|
|
initialScale = 2;
|
|
} else if (model.includes("x3")) {
|
|
initialScale = 3;
|
|
} else {
|
|
initialScale = 4;
|
|
}
|
|
doubleScale = initialScale * initialScale;
|
|
singleScale = initialScale;
|
|
}
|
|
|
|
if (doubleUpscayl) {
|
|
const newWidth = dimensions.width * doubleScale;
|
|
const newHeight = dimensions.height * doubleScale;
|
|
if (newWidth < 32768 || newHeight < 32768) {
|
|
newDimensions.width = newWidth;
|
|
newDimensions.height = newHeight;
|
|
} else {
|
|
newDimensions.width = 32384;
|
|
newDimensions.height = 32384;
|
|
}
|
|
} else {
|
|
newDimensions.width = dimensions.width * singleScale;
|
|
newDimensions.height = dimensions.height * singleScale;
|
|
}
|
|
|
|
return newDimensions;
|
|
}, [dimensions.width, dimensions.height, doubleUpscayl, scale]);
|
|
|
|
return (
|
|
<div
|
|
className={`animate-step-in animate flex h-screen flex-col gap-7 overflow-y-auto p-5 overflow-x-hidden`}>
|
|
{/* BATCH OPTION */}
|
|
<div className="flex flex-row items-center gap-2">
|
|
<input
|
|
type="checkbox"
|
|
className="toggle"
|
|
defaultChecked={batchMode}
|
|
onClick={() => setBatchMode((oldValue) => !oldValue)}></input>
|
|
<p
|
|
className="mr-1 inline-block cursor-help text-sm"
|
|
data-tooltip-id="tooltip"
|
|
data-tooltip-content="This will let you Upscayl all files in a folder at once">
|
|
Batch Upscayl
|
|
</p>
|
|
</div>
|
|
|
|
{/* STEP 1 */}
|
|
<div data-tooltip-id="tooltip" data-tooltip-content={imagePath}>
|
|
<p className="step-heading">Step 1</p>
|
|
<button
|
|
className="btn-primary btn"
|
|
onClick={!batchMode ? selectImageHandler : selectFolderHandler}>
|
|
Select {batchMode ? "Folder" : "Image"}
|
|
</button>
|
|
</div>
|
|
|
|
{/* STEP 2 */}
|
|
<div className="animate-step-in">
|
|
<p className="step-heading">Step 2</p>
|
|
<p className="mb-2 text-sm">Select Model</p>
|
|
|
|
<Select
|
|
options={modelOptions}
|
|
components={{
|
|
IndicatorSeparator: () => null,
|
|
DropdownIndicator: () => null,
|
|
}}
|
|
onChange={(e) => {
|
|
handleModelChange(e);
|
|
setCurrentModel({ label: e.label, value: e.value });
|
|
}}
|
|
className="react-select-container active:w-full focus:w-full hover:w-full transition-all"
|
|
classNamePrefix="react-select"
|
|
value={currentModel}
|
|
/>
|
|
|
|
{!batchMode && (
|
|
<div className="mt-4 flex items-center gap-1">
|
|
<input
|
|
type="checkbox"
|
|
className="checkbox"
|
|
checked={doubleUpscayl}
|
|
onChange={(e) => {
|
|
if (e.target.checked) {
|
|
setDoubleUpscayl(true);
|
|
} else {
|
|
setDoubleUpscayl(false);
|
|
}
|
|
}}
|
|
/>
|
|
<p
|
|
className="cursor-pointer text-sm"
|
|
onClick={(e) => {
|
|
setDoubleUpscayl(!doubleUpscayl);
|
|
}}>
|
|
Double Upscayl
|
|
</p>
|
|
<button
|
|
className="badge-info badge cursor-help"
|
|
data-tooltip-id="tooltip"
|
|
data-tooltip-content="Enable this option to get a 16x upscayl (we just run upscayl twice). Note that this may not always work properly with all images, for example, images with really large resolutions.">
|
|
i
|
|
</button>
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
{/* STEP 3 */}
|
|
<div
|
|
className="animate-step-in"
|
|
data-tooltip-content={outputPath}
|
|
data-tooltip-id="tooltip">
|
|
<p className="step-heading">Step 3</p>
|
|
<p className="mb-2 text-sm">
|
|
Defaults to {!batchMode ? "Image's" : "Folder'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>
|
|
{dimensions.width && dimensions.height && (
|
|
<p className="mb-2 text-sm">
|
|
Upscayl from{" "}
|
|
<span className="font-bold">
|
|
{dimensions.width}x{dimensions.height}
|
|
</span>{" "}
|
|
to{" "}
|
|
<span className="font-bold">
|
|
{getUpscaleResolution().width}x{getUpscaleResolution().height}
|
|
</span>
|
|
</p>
|
|
)}
|
|
<button
|
|
className="btn-accent btn"
|
|
onClick={upscaylHandler}
|
|
disabled={progress.length > 0}>
|
|
{progress.length > 0 ? "Upscayling⏳" : "Upscayl"}
|
|
</button>
|
|
</div>
|
|
|
|
<Tooltip className="max-w-sm" id="tooltip" />
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export default LeftPaneImageSteps;
|