1
0
mirror of https://github.com/upscayl/upscayl.git synced 2025-01-31 04:03:51 +01:00

Add no process toggle

This commit is contained in:
Nayam Amarshe 2023-09-19 00:00:43 +05:30
parent 58172d6359
commit 7533867de8
10 changed files with 226 additions and 96 deletions

View File

@ -5,6 +5,7 @@ import {
compression, compression,
customModelsFolderPath, customModelsFolderPath,
folderPath, folderPath,
noImageProcessing,
outputFolderPath, outputFolderPath,
overwrite, overwrite,
saveOutputFolder, saveOutputFolder,
@ -50,21 +51,23 @@ const imageUpscayl = async (event, payload) => {
const fileName = parse(fullfileName).name; const fileName = parse(fullfileName).name;
const fileExt = parse(fullfileName).ext; const fileExt = parse(fullfileName).ext;
let scale = "4"; let initialScale = "4";
if (model.includes("x2")) { if (model.includes("x2")) {
scale = "2"; initialScale = "2";
} else if (model.includes("x3")) { } else if (model.includes("x3")) {
scale = "3"; initialScale = "3";
} else { } else {
scale = "4"; initialScale = "4";
} }
const desiredScale = payload.scale;
const outFile = const outFile =
outputDir + outputDir +
slash + slash +
fileName + fileName +
"_upscayl_" + "_upscayl_" +
payload.scale + desiredScale +
"x_" + "x_" +
model + model +
"." + "." +
@ -82,6 +85,19 @@ const imageUpscayl = async (event, payload) => {
) )
); );
} else { } else {
logit("✅ Upscayl Variables: ", {
model,
gpuId,
saveImageAs,
inputDir,
outputDir,
fullfileName,
fileName,
initialScale: initialScale,
desiredScale,
outFile,
compression,
});
const upscayl = spawnUpscayl( const upscayl = spawnUpscayl(
"realesrgan", "realesrgan",
getSingleImageArguments( getSingleImageArguments(
@ -90,7 +106,7 @@ const imageUpscayl = async (event, payload) => {
outFile, outFile,
isDefaultModel ? modelsPath : customModelsFolderPath ?? modelsPath, isDefaultModel ? modelsPath : customModelsFolderPath ?? modelsPath,
model, model,
scale, initialScale,
gpuId, gpuId,
"png" "png"
), ),
@ -130,20 +146,40 @@ const imageUpscayl = async (event, payload) => {
if (!failed && !stopped) { if (!failed && !stopped) {
logit("💯 Done upscaling"); logit("💯 Done upscaling");
logit("♻ Scaling and converting now..."); logit("♻ Scaling and converting now...");
mainWindow.webContents.send(COMMAND.SCALING_AND_CONVERTING); if (noImageProcessing === false) {
// Free up memory mainWindow.webContents.send(COMMAND.SCALING_AND_CONVERTING);
upscayl.kill(); // Free up memory
try { upscayl.kill();
if (saveImageAs !== "png" && scale !== "4" && compression !== 0) { try {
await convertAndScale( await convertAndScale(
inputDir + slash + fullfileName, inputDir + slash + fullfileName,
isAlpha ? outFile + ".png" : outFile, isAlpha ? outFile + ".png" : outFile,
outFile, outFile,
payload.scale, desiredScale,
saveImageAs, saveImageAs,
onError onError
); );
mainWindow.setProgressBar(-1);
mainWindow.webContents.send(
COMMAND.UPSCAYL_DONE,
outFile.replace(
/([^/\\]+)$/i,
encodeURIComponent(outFile.match(/[^/\\]+$/i)![0])
)
);
} catch (error) {
logit(
"❌ Error processing (scaling and converting) the image. Please report this error on GitHub.",
error
);
upscayl.kill();
mainWindow.webContents.send(
COMMAND.UPSCAYL_ERROR,
"Error processing (scaling and converting) the image. Please report this error on Upscayl GitHub Issues page."
);
} }
} else {
logit("🚫 Skipping scaling and converting");
mainWindow.setProgressBar(-1); mainWindow.setProgressBar(-1);
mainWindow.webContents.send( mainWindow.webContents.send(
COMMAND.UPSCAYL_DONE, COMMAND.UPSCAYL_DONE,
@ -152,16 +188,6 @@ const imageUpscayl = async (event, payload) => {
encodeURIComponent(outFile.match(/[^/\\]+$/i)![0]) encodeURIComponent(outFile.match(/[^/\\]+$/i)![0])
) )
); );
} catch (error) {
logit(
"❌ Error processing (scaling and converting) the image. Please report this error on GitHub.",
error
);
upscayl.kill();
mainWindow.webContents.send(
COMMAND.UPSCAYL_ERROR,
"Error processing (scaling and converting) the image. Please report this error on Upscayl GitHub Issues page."
);
} }
} }
}; };

View File

@ -11,6 +11,7 @@ import {
setOverwrite, setOverwrite,
setCompression, setCompression,
setSaveOutputFolder, setSaveOutputFolder,
fetchLocalStorage,
} from "./utils/config-variables"; } from "./utils/config-variables";
import electronIsDev from "electron-is-dev"; import electronIsDev from "electron-is-dev";
import { format } from "url"; import { format } from "url";
@ -55,65 +56,7 @@ const createMainWindow = () => {
mainWindow.show(); mainWindow.show();
}); });
// GET LAST IMAGE PATH TO LOCAL STORAGE fetchLocalStorage();
mainWindow.webContents
.executeJavaScript('localStorage.getItem("lastImagePath");', true)
.then((lastImagePath: string | null) => {
if (lastImagePath && lastImagePath.length > 0) {
setImagePath(lastImagePath);
}
});
// GET LAST FOLDER PATH TO LOCAL STORAGE
mainWindow.webContents
.executeJavaScript('localStorage.getItem("lastFolderPath");', true)
.then((lastFolderPath: string | null) => {
if (lastFolderPath && lastFolderPath.length > 0) {
setFolderPath(lastFolderPath);
}
});
// GET LAST CUSTOM MODELS FOLDER PATH TO LOCAL STORAGE
mainWindow.webContents
.executeJavaScript(
'localStorage.getItem("lastCustomModelsFolderPath");',
true
)
.then((lastCustomModelsFolderPath: string | null) => {
if (lastCustomModelsFolderPath && lastCustomModelsFolderPath.length > 0) {
setCustomModelsFolderPath(lastCustomModelsFolderPath);
}
});
// GET LAST CUSTOM MODELS FOLDER PATH TO LOCAL STORAGE
mainWindow.webContents
.executeJavaScript('localStorage.getItem("lastOutputFolderPath");', true)
.then((lastOutputFolderPath: string | null) => {
if (lastOutputFolderPath && lastOutputFolderPath.length > 0) {
setOutputFolderPath(lastOutputFolderPath);
}
});
// GET LAST SAVE OUTPUT FOLDER (BOOLEAN) TO LOCAL STORAGE
mainWindow.webContents
.executeJavaScript('localStorage.getItem("rememberOutputFolder");', true)
.then((lastSaveOutputFolder: boolean | null) => {
if (lastSaveOutputFolder !== null) {
setSaveOutputFolder(lastSaveOutputFolder);
}
});
// GET IMAGE COMPRESSION (NUMBER) FROM LOCAL STORAGE
mainWindow.webContents
.executeJavaScript('localStorage.getItem("compression");', true)
.then((lastSavedCompression: string | null) => {
if (lastSavedCompression !== null) {
setCompression(parseInt(lastSavedCompression));
}
});
// GET OVERWRITE (BOOLEAN) FROM LOCAL STORAGE
mainWindow.webContents
.executeJavaScript('localStorage.getItem("overwrite");', true)
.then((lastSavedOverwrite: string | null) => {
if (lastSavedOverwrite !== null) {
setOverwrite(lastSavedOverwrite === "true");
}
});
mainWindow.webContents.send(COMMAND.OS, getPlatform()); mainWindow.webContents.send(COMMAND.OS, getPlatform());

View File

@ -1,4 +1,6 @@
import { ChildProcessWithoutNullStreams } from "child_process"; import { ChildProcessWithoutNullStreams } from "child_process";
import { getMainWindow } from "../main-window";
import logit from "./logit";
export let imagePath: string | undefined = ""; export let imagePath: string | undefined = "";
export let folderPath: string | undefined = undefined; export let folderPath: string | undefined = undefined;
@ -12,38 +14,47 @@ export let childProcesses: {
process: ChildProcessWithoutNullStreams; process: ChildProcessWithoutNullStreams;
kill: () => boolean; kill: () => boolean;
}[] = []; }[] = [];
export let noImageProcessing: boolean = false;
export function setImagePath(value: string | undefined): void { export function setImagePath(value: string | undefined): void {
imagePath = value; imagePath = value;
logit("🖼️ Updating Image Path: ", imagePath);
} }
export function setFolderPath(value: string | undefined): void { export function setFolderPath(value: string | undefined): void {
folderPath = value; folderPath = value;
logit("📁 Updating Folder Path: ", folderPath);
} }
export function setCustomModelsFolderPath(value: string | undefined): void { export function setCustomModelsFolderPath(value: string | undefined): void {
customModelsFolderPath = value; customModelsFolderPath = value;
logit("📁 Updating Custom Models Folder Path: ", customModelsFolderPath);
} }
// SETTERS // SETTERS
export function setOutputFolderPath(value: string | undefined): void { export function setOutputFolderPath(value: string | undefined): void {
outputFolderPath = value; outputFolderPath = value;
logit("📁 Updating Output Folder Path: ", outputFolderPath);
} }
export function setSaveOutputFolder(value: boolean): void { export function setSaveOutputFolder(value: boolean): void {
saveOutputFolder = value; saveOutputFolder = value;
logit("💾 Updating Save Output Folder: ", saveOutputFolder);
} }
export function setCompression(value: number): void { export function setCompression(value: number): void {
compression = value; compression = value;
logit("📐 Updating Compression: ", compression);
} }
export function setOverwrite(value: boolean): void { export function setOverwrite(value: boolean): void {
overwrite = value; overwrite = value;
logit("📝 Updating Overwrite: ", overwrite);
} }
export function setStopped(value: boolean): void { export function setStopped(value: boolean): void {
stopped = value; stopped = value;
logit("🛑 Updating Stopped: ", stopped);
} }
export function setChildProcesses(value: { export function setChildProcesses(value: {
@ -51,4 +62,84 @@ export function setChildProcesses(value: {
kill: () => boolean; kill: () => boolean;
}): void { }): void {
childProcesses.push(value); childProcesses.push(value);
logit("👶 Updating Child Processes: ", childProcesses);
}
export function setNoImageProcessing(value: boolean): void {
noImageProcessing = value;
logit("🖼️ Updating No Image Processing: ", noImageProcessing);
}
// LOCAL STORAGE
export function fetchLocalStorage(): void {
const mainWindow = getMainWindow();
if (!mainWindow) return;
// GET LAST IMAGE PATH TO LOCAL STORAGE
mainWindow.webContents
.executeJavaScript('localStorage.getItem("lastImagePath");', true)
.then((lastImagePath: string | null) => {
if (lastImagePath && lastImagePath.length > 0) {
setImagePath(lastImagePath);
}
});
// GET LAST FOLDER PATH TO LOCAL STORAGE
mainWindow.webContents
.executeJavaScript('localStorage.getItem("lastFolderPath");', true)
.then((lastFolderPath: string | null) => {
if (lastFolderPath && lastFolderPath.length > 0) {
setFolderPath(lastFolderPath);
}
});
// GET LAST CUSTOM MODELS FOLDER PATH TO LOCAL STORAGE
mainWindow.webContents
.executeJavaScript(
'localStorage.getItem("lastCustomModelsFolderPath");',
true
)
.then((lastCustomModelsFolderPath: string | null) => {
if (lastCustomModelsFolderPath && lastCustomModelsFolderPath.length > 0) {
setCustomModelsFolderPath(lastCustomModelsFolderPath);
}
});
// GET LAST CUSTOM MODELS FOLDER PATH TO LOCAL STORAGE
mainWindow.webContents
.executeJavaScript('localStorage.getItem("lastOutputFolderPath");', true)
.then((lastOutputFolderPath: string | null) => {
if (lastOutputFolderPath && lastOutputFolderPath.length > 0) {
setOutputFolderPath(lastOutputFolderPath);
}
});
// GET LAST SAVE OUTPUT FOLDER (BOOLEAN) TO LOCAL STORAGE
mainWindow.webContents
.executeJavaScript('localStorage.getItem("rememberOutputFolder");', true)
.then((lastSaveOutputFolder: boolean | null) => {
if (lastSaveOutputFolder !== null) {
setSaveOutputFolder(lastSaveOutputFolder);
}
});
// GET IMAGE COMPRESSION (NUMBER) FROM LOCAL STORAGE
mainWindow.webContents
.executeJavaScript('localStorage.getItem("compression");', true)
.then((lastSavedCompression: string | null) => {
if (lastSavedCompression !== null) {
setCompression(parseInt(lastSavedCompression));
}
});
// GET OVERWRITE (BOOLEAN) FROM LOCAL STORAGE
mainWindow.webContents
.executeJavaScript('localStorage.getItem("overwrite");', true)
.then((lastSavedOverwrite: string | null) => {
if (lastSavedOverwrite !== null) {
setOverwrite(lastSavedOverwrite === "true");
}
});
// GET PROCESS IMAGE (BOOLEAN) FROM LOCAL STORAGE
mainWindow.webContents
.executeJavaScript('localStorage.getItem("noImageProcessing");', true)
.then((lastSaved: string | null) => {
if (lastSaved !== null) {
setNoImageProcessing(lastSaved === "true");
}
});
} }

View File

@ -18,20 +18,33 @@ const convertAndScale = async (
if (!mainWindow || !originalImage) { if (!mainWindow || !originalImage) {
throw new Error("Could not grab the original image!"); throw new Error("Could not grab the original image!");
} }
// Resize the image to the scale // Resize the image to the scale
const newImage = sharp(upscaledImagePath, { const newImage = sharp(upscaledImagePath, {
limitInputPixels: false, limitInputPixels: false,
}).resize( }).resize(
originalImage.width && originalImage.width * parseInt(scale), originalImage.width && originalImage.width * parseInt(scale),
originalImage.height && originalImage.height * parseInt(scale) originalImage.height && originalImage.height * parseInt(scale),
{
fit: "outside",
}
); );
// Convert compression percentage (0-100) to compressionLevel (0-9) // Convert compression percentage (0-100) to compressionLevel (0-9)
const compressionLevel = Math.round((compression / 100) * 9); const compressionLevel = Math.round((compression / 100) * 9);
logit("Compression: ", compression);
logit("📐 Processing Image: ", {
originalWidth: originalImage.width,
originalHeight: originalImage.height,
scale,
saveImageAs,
compressionPercentage: compression,
compressionLevel,
});
const buffer = await newImage.toBuffer(); const buffer = await newImage.toBuffer();
try { try {
logit("");
await sharp(buffer, { await sharp(buffer, {
limitInputPixels: false, limitInputPixels: false,
}) })

View File

View File

@ -19,3 +19,8 @@ export const dontShowCloudModalAtom = atomWithStorage<boolean>(
"dontShowCloudModal", "dontShowCloudModal",
false false
); );
export const noImageProcessingAtom = atomWithStorage<boolean>(
"noImageProcessing",
false
);

View File

@ -6,7 +6,11 @@ type LogAreaProps = {
logData: string[]; logData: string[];
}; };
export function LogArea({ copyOnClickHandler, isCopied, logData }) { export function LogArea({
copyOnClickHandler,
isCopied,
logData,
}: LogAreaProps) {
return ( return (
<div className="relative flex flex-col gap-2"> <div className="relative flex flex-col gap-2">
<button <button

View File

@ -1,11 +1,11 @@
import React, { useEffect } from "react"; import React, { useEffect } from "react";
type ToggleOverwriteProps = { type OverwriteToggleProps = {
overwrite: boolean; overwrite: boolean;
setOverwrite: (arg: any) => void; setOverwrite: (arg: any) => void;
}; };
const ToggleOverwrite = ({ overwrite, setOverwrite }: ToggleOverwriteProps) => { const OverwriteToggle = ({ overwrite, setOverwrite }: OverwriteToggleProps) => {
useEffect(() => { useEffect(() => {
if (!localStorage.getItem("overwrite")) { if (!localStorage.getItem("overwrite")) {
localStorage.setItem("overwrite", JSON.stringify(overwrite)); localStorage.setItem("overwrite", JSON.stringify(overwrite));
@ -44,4 +44,4 @@ const ToggleOverwrite = ({ overwrite, setOverwrite }: ToggleOverwriteProps) => {
); );
}; };
export default ToggleOverwrite; export default OverwriteToggle;

View File

@ -0,0 +1,31 @@
type ProcessImageToggleProps = {
noImageProcessing: boolean;
setNoImageProcessing: (arg: any) => void;
};
const ProcessImageToggle = ({
noImageProcessing,
setNoImageProcessing,
}: ProcessImageToggleProps) => {
return (
<div className="flex flex-col gap-2">
<p className="text-sm font-medium">DON'T POST-PROCESS IMAGE</p>
<p className="text-xs text-base-content/80">
If enabled, the image will not be converted or scaled or post-processed.
This will output the original AI upscaling result as-is (Restart
Required)
</p>
<input
type="checkbox"
className="toggle"
checked={noImageProcessing}
onClick={() => {
setNoImageProcessing(!noImageProcessing);
alert("Please restart Upscayl for the changes to take effect.");
}}
/>
</div>
);
};
export default ProcessImageToggle;

View File

@ -9,13 +9,18 @@ import { DonateButton } from "./DonateButton";
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { themeChange } from "theme-change"; import { themeChange } from "theme-change";
import { useAtom, useAtomValue } from "jotai"; import { useAtom, useAtomValue } from "jotai";
import { customModelsPathAtom, scaleAtom } from "../../atoms/userSettingsAtom"; import {
customModelsPathAtom,
noImageProcessingAtom,
scaleAtom,
} from "../../atoms/userSettingsAtom";
import { modelsListAtom } from "../../atoms/modelsListAtom"; import { modelsListAtom } from "../../atoms/modelsListAtom";
import useLog from "../hooks/useLog"; import useLog from "../hooks/useLog";
import { CompressionInput } from "./CompressionInput"; import { CompressionInput } from "./CompressionInput";
import ToggleOverwrite from "./ToggleOverwrite"; import OverwriteToggle from "./OverwriteToggle";
import { UpscaylCloudModal } from "../UpscaylCloudModal"; import { UpscaylCloudModal } from "../UpscaylCloudModal";
import { ResetSettings } from "./ResetSettings"; import { ResetSettings } from "./ResetSettings";
import ProcessImageToggle from "./ProcessImageToggle";
interface IProps { interface IProps {
batchMode: boolean; batchMode: boolean;
@ -66,6 +71,9 @@ function SettingsTab({
const [customModelsPath, setCustomModelsPath] = useAtom(customModelsPathAtom); const [customModelsPath, setCustomModelsPath] = useAtom(customModelsPathAtom);
const modelOptions = useAtomValue(modelsListAtom); const modelOptions = useAtomValue(modelsListAtom);
const [scale, setScale] = useAtom(scaleAtom); const [scale, setScale] = useAtom(scaleAtom);
const [noImageProcessing, setNoImageProcessing] = useAtom(
noImageProcessingAtom
);
const { logit } = useLog(); const { logit } = useLog();
@ -191,20 +199,29 @@ function SettingsTab({
setExportType={setExportType} setExportType={setExportType}
/> />
{/* IMAGE SCALE */} <ProcessImageToggle
<ImageScaleSelect scale={scale} setScale={setScale} /> noImageProcessing={noImageProcessing}
setNoImageProcessing={setNoImageProcessing}
<CompressionInput
compression={compression}
handleCompressionChange={handleCompressionChange}
/> />
{!noImageProcessing && (
<>
{/* IMAGE SCALE */}
<ImageScaleSelect scale={scale} setScale={setScale} />
<CompressionInput
compression={compression}
handleCompressionChange={handleCompressionChange}
/>
</>
)}
<SaveOutputFolderToggle <SaveOutputFolderToggle
rememberOutputFolder={rememberOutputFolder} rememberOutputFolder={rememberOutputFolder}
setRememberOutputFolder={setRememberOutputFolder} setRememberOutputFolder={setRememberOutputFolder}
/> />
<ToggleOverwrite overwrite={overwrite} setOverwrite={setOverwrite} /> <OverwriteToggle overwrite={overwrite} setOverwrite={setOverwrite} />
{/* GPU ID INPUT */} {/* GPU ID INPUT */}
<GpuIdInput gpuId={gpuId} handleGpuIdChange={handleGpuIdChange} /> <GpuIdInput gpuId={gpuId} handleGpuIdChange={handleGpuIdChange} />