mirror of
https://github.com/upscayl/upscayl.git
synced 2025-01-18 17:14:08 +01:00
Add back custom width
This commit is contained in:
parent
ded51941fe
commit
ecbb48acdc
6
common/types/types.d.ts
vendored
6
common/types/types.d.ts
vendored
@ -8,6 +8,8 @@ export type ImageUpscaylPayload = {
|
||||
overwrite: boolean;
|
||||
compression: string;
|
||||
noImageProcessing: boolean;
|
||||
customWidth: string;
|
||||
useCustomWidth: boolean;
|
||||
};
|
||||
|
||||
export type DoubleUpscaylPayload = {
|
||||
@ -19,6 +21,8 @@ export type DoubleUpscaylPayload = {
|
||||
saveImageAs: string;
|
||||
compression: string;
|
||||
noImageProcessing: boolean;
|
||||
customWidth: string;
|
||||
useCustomWidth: boolean;
|
||||
};
|
||||
|
||||
export type BatchUpscaylPayload = {
|
||||
@ -30,4 +34,6 @@ export type BatchUpscaylPayload = {
|
||||
scale: string;
|
||||
compression: string;
|
||||
noImageProcessing: boolean;
|
||||
customWidth: string;
|
||||
useCustomWidth: boolean;
|
||||
};
|
||||
|
@ -3,14 +3,12 @@ import { getMainWindow } from "../main-window";
|
||||
import {
|
||||
childProcesses,
|
||||
savedCustomModelsPath,
|
||||
customWidth,
|
||||
noImageProcessing,
|
||||
rememberOutputFolder,
|
||||
setCompression,
|
||||
setNoImageProcessing,
|
||||
setStopped,
|
||||
stopped,
|
||||
useCustomWidth,
|
||||
} from "../utils/config-variables";
|
||||
import logit from "../utils/logit";
|
||||
import { spawnUpscayl } from "../utils/spawn-upscayl";
|
||||
@ -20,8 +18,6 @@ import { modelsPath } from "../utils/get-resource-paths";
|
||||
import COMMAND from "../../common/commands";
|
||||
import { BatchUpscaylPayload } from "../../common/types/types";
|
||||
import { ImageFormat } from "../utils/types";
|
||||
import getModelScale from "../../common/check-model-scale";
|
||||
import removeFileExtension from "../utils/remove-file-extension";
|
||||
import showNotification from "../utils/show-notification";
|
||||
import { DEFAULT_MODELS } from "../../common/models-list";
|
||||
|
||||
@ -47,8 +43,11 @@ const batchUpscayl = async (event, payload: BatchUpscaylPayload) => {
|
||||
const isDefaultModel = DEFAULT_MODELS.includes(model);
|
||||
|
||||
const scale = payload.scale;
|
||||
const customWidth = payload.customWidth;
|
||||
const useCustomWidth = payload.useCustomWidth;
|
||||
|
||||
const outputFolderName = `upscayl_${saveImageAs}_${model}_${scale ? scale : ""}${useCustomWidth ? "px" : "x"}`;
|
||||
|
||||
const outputFolderName = `upscayl_${saveImageAs}_${model}_${scale}${useCustomWidth ? "px" : "x"}`;
|
||||
outputFolderPath += slash + outputFolderName;
|
||||
if (!fs.existsSync(outputFolderPath)) {
|
||||
fs.mkdirSync(outputFolderPath, { recursive: true });
|
||||
@ -78,6 +77,7 @@ const batchUpscayl = async (event, payload: BatchUpscaylPayload) => {
|
||||
gpuId,
|
||||
saveImageAs,
|
||||
scale,
|
||||
customWidth,
|
||||
}),
|
||||
logit,
|
||||
);
|
||||
|
@ -3,8 +3,6 @@ import { getMainWindow } from "../main-window";
|
||||
import {
|
||||
childProcesses,
|
||||
savedCustomModelsPath,
|
||||
customWidth,
|
||||
savedBatchUpscaylFolderPath,
|
||||
noImageProcessing,
|
||||
savedOutputPath,
|
||||
rememberOutputFolder,
|
||||
@ -12,7 +10,6 @@ import {
|
||||
setNoImageProcessing,
|
||||
setStopped,
|
||||
stopped,
|
||||
useCustomWidth,
|
||||
} from "../utils/config-variables";
|
||||
import slash from "../utils/slash";
|
||||
import { spawnUpscayl } from "../utils/spawn-upscayl";
|
||||
@ -25,9 +22,7 @@ import logit from "../utils/logit";
|
||||
import COMMAND from "../../common/commands";
|
||||
import { DoubleUpscaylPayload } from "../../common/types/types";
|
||||
import { ImageFormat } from "../utils/types";
|
||||
import getModelScale from "../../common/check-model-scale";
|
||||
import showNotification from "../utils/show-notification";
|
||||
import { unlinkSync } from "fs";
|
||||
import { DEFAULT_MODELS } from "../../common/models-list";
|
||||
|
||||
const doubleUpscayl = async (event, payload: DoubleUpscaylPayload) => {
|
||||
@ -56,13 +51,15 @@ const doubleUpscayl = async (event, payload: DoubleUpscaylPayload) => {
|
||||
const fileName = parse(fullfileName).name;
|
||||
|
||||
const scale = parseInt(payload.scale) * parseInt(payload.scale);
|
||||
const customWidth = payload.customWidth;
|
||||
const useCustomWidth = payload.useCustomWidth;
|
||||
|
||||
const outFile =
|
||||
outputDir +
|
||||
slash +
|
||||
fileName +
|
||||
"_upscayl_" +
|
||||
scale +
|
||||
(scale ? scale : "") +
|
||||
(useCustomWidth ? "px_" : "x_") +
|
||||
model +
|
||||
"." +
|
||||
@ -186,6 +183,7 @@ const doubleUpscayl = async (event, payload: DoubleUpscaylPayload) => {
|
||||
gpuId,
|
||||
saveImageAs,
|
||||
scale: scale.toString(),
|
||||
customWidth,
|
||||
}),
|
||||
logit,
|
||||
);
|
||||
|
@ -4,7 +4,6 @@ import COMMAND from "../../common/commands";
|
||||
import {
|
||||
savedCompression,
|
||||
savedCustomModelsPath,
|
||||
customWidth,
|
||||
savedBatchUpscaylFolderPath,
|
||||
noImageProcessing,
|
||||
savedOutputPath,
|
||||
@ -14,7 +13,6 @@ import {
|
||||
setNoImageProcessing,
|
||||
setStopped,
|
||||
stopped,
|
||||
useCustomWidth,
|
||||
} from "../utils/config-variables";
|
||||
import { getSingleImageArguments } from "../utils/get-arguments";
|
||||
import logit from "../utils/logit";
|
||||
@ -60,6 +58,9 @@ const imageUpscayl = async (event, payload: ImageUpscaylPayload) => {
|
||||
const fullfileName = payload.imagePath.replace(/^.*[\\\/]/, "") as string;
|
||||
const fileName = parse(fullfileName).name;
|
||||
const fileExt = parse(fullfileName).ext;
|
||||
const useCustomWidth = payload.useCustomWidth;
|
||||
const customWidth = payload.customWidth;
|
||||
|
||||
const desiredScale = useCustomWidth
|
||||
? customWidth || payload.scale
|
||||
: payload.scale;
|
||||
@ -115,6 +116,7 @@ const imageUpscayl = async (event, payload: ImageUpscaylPayload) => {
|
||||
scale: desiredScale,
|
||||
gpuId,
|
||||
saveImageAs,
|
||||
customWidth,
|
||||
}),
|
||||
logit,
|
||||
);
|
||||
|
@ -64,17 +64,17 @@ export function setTurnOffNotifications(value: boolean): void {
|
||||
logit("🔕 Updating Turn Off Notifications: ", turnOffNotifications);
|
||||
}
|
||||
|
||||
export let customWidth: string | null = null;
|
||||
export function setCustomWidth(value: string | null): void {
|
||||
customWidth = value;
|
||||
logit("📏 Updating Custom Width: ", customWidth);
|
||||
}
|
||||
// export let customWidth: string | null = null;
|
||||
// export function setCustomWidth(value: string | null): void {
|
||||
// customWidth = value;
|
||||
// logit("📏 Updating Custom Width: ", customWidth);
|
||||
// }
|
||||
|
||||
export let useCustomWidth: boolean = false;
|
||||
export function setUseCustomWidth(value: boolean): void {
|
||||
useCustomWidth = value;
|
||||
logit("📏 Updating Use Custom Width: ", useCustomWidth);
|
||||
}
|
||||
// export let useCustomWidth: boolean = false;
|
||||
// export function setUseCustomWidth(value: boolean): void {
|
||||
// useCustomWidth = value;
|
||||
// logit("📏 Updating Use Custom Width: ", useCustomWidth);
|
||||
// }
|
||||
|
||||
// SETTERS
|
||||
|
||||
@ -174,21 +174,21 @@ export function fetchLocalStorage(): void {
|
||||
}
|
||||
});
|
||||
|
||||
// GET CUSTOM WIDTH (STRING) FROM LOCAL STORAGE
|
||||
mainWindow.webContents
|
||||
.executeJavaScript('localStorage.getItem("customWidth");', true)
|
||||
.then((lastSaved: string | null) => {
|
||||
if (lastSaved !== null) {
|
||||
setCustomWidth(lastSaved);
|
||||
}
|
||||
});
|
||||
// // GET CUSTOM WIDTH (STRING) FROM LOCAL STORAGE
|
||||
// mainWindow.webContents
|
||||
// .executeJavaScript('localStorage.getItem("customWidth");', true)
|
||||
// .then((lastSaved: string | null) => {
|
||||
// if (lastSaved !== null) {
|
||||
// setCustomWidth(lastSaved);
|
||||
// }
|
||||
// });
|
||||
|
||||
// GET USE CUSTOM WIDTH (BOOLEAN) FROM LOCAL STORAGE
|
||||
mainWindow.webContents
|
||||
.executeJavaScript('localStorage.getItem("useCustomWidth");', true)
|
||||
.then((lastSaved: string | null) => {
|
||||
if (lastSaved !== null) {
|
||||
setUseCustomWidth(lastSaved === "true");
|
||||
}
|
||||
});
|
||||
// // GET USE CUSTOM WIDTH (BOOLEAN) FROM LOCAL STORAGE
|
||||
// mainWindow.webContents
|
||||
// .executeJavaScript('localStorage.getItem("useCustomWidth");', true)
|
||||
// .then((lastSaved: string | null) => {
|
||||
// if (lastSaved !== null) {
|
||||
// setUseCustomWidth(lastSaved === "true");
|
||||
// }
|
||||
// });
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ export const getSingleImageArguments = ({
|
||||
scale,
|
||||
gpuId,
|
||||
saveImageAs,
|
||||
customWidth,
|
||||
}: {
|
||||
inputDir: string;
|
||||
fullfileName: string;
|
||||
@ -20,6 +21,7 @@ export const getSingleImageArguments = ({
|
||||
scale: any;
|
||||
gpuId: string;
|
||||
saveImageAs: ImageFormat;
|
||||
customWidth: string;
|
||||
}) => {
|
||||
return [
|
||||
"-i",
|
||||
@ -36,6 +38,7 @@ export const getSingleImageArguments = ({
|
||||
gpuId ? gpuId : "",
|
||||
"-f",
|
||||
saveImageAs,
|
||||
customWidth ? `-w ${customWidth}` : "",
|
||||
];
|
||||
};
|
||||
|
||||
@ -84,6 +87,7 @@ export const getDoubleUpscaleSecondPassArguments = ({
|
||||
gpuId,
|
||||
saveImageAs,
|
||||
scale,
|
||||
customWidth,
|
||||
}: {
|
||||
isAlpha: boolean;
|
||||
outFile: string;
|
||||
@ -92,6 +96,7 @@ export const getDoubleUpscaleSecondPassArguments = ({
|
||||
gpuId: string;
|
||||
saveImageAs: ImageFormat;
|
||||
scale: string;
|
||||
customWidth: string;
|
||||
}) => {
|
||||
return [
|
||||
"-i",
|
||||
@ -108,6 +113,7 @@ export const getDoubleUpscaleSecondPassArguments = ({
|
||||
gpuId ? gpuId : "",
|
||||
isAlpha ? "" : "-f",
|
||||
isAlpha ? "" : saveImageAs,
|
||||
customWidth ? `-w ${customWidth}` : "",
|
||||
];
|
||||
};
|
||||
|
||||
@ -119,6 +125,7 @@ export const getBatchArguments = ({
|
||||
gpuId,
|
||||
saveImageAs,
|
||||
scale,
|
||||
customWidth,
|
||||
}: {
|
||||
inputDir: string;
|
||||
outputDir: string;
|
||||
@ -127,6 +134,7 @@ export const getBatchArguments = ({
|
||||
gpuId: string;
|
||||
saveImageAs: ImageFormat;
|
||||
scale: string;
|
||||
customWidth: string;
|
||||
}) => {
|
||||
return [
|
||||
"-i",
|
||||
@ -143,5 +151,6 @@ export const getBatchArguments = ({
|
||||
gpuId ? gpuId : "",
|
||||
"-f",
|
||||
saveImageAs,
|
||||
customWidth ? `-w ${customWidth}` : "",
|
||||
];
|
||||
};
|
||||
|
@ -7,19 +7,21 @@ type TabsProps = {
|
||||
|
||||
const Tabs = ({ selectedTab, setSelectedTab }: TabsProps) => {
|
||||
return (
|
||||
<div className="tabs tabs-boxed mx-auto mb-2">
|
||||
<div className="tabs-boxed tabs mx-auto mb-2">
|
||||
<a
|
||||
className={`tab ${selectedTab === 0 && "tab-active"}`}
|
||||
onClick={() => {
|
||||
setSelectedTab(0);
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
Upscayl
|
||||
</a>
|
||||
<a
|
||||
className={`tab ${selectedTab === 1 && "tab-active"}`}
|
||||
onClick={() => {
|
||||
setSelectedTab(1);
|
||||
}}>
|
||||
}}
|
||||
>
|
||||
Settings
|
||||
</a>
|
||||
</div>
|
||||
|
53
renderer/components/settings-tab/CustomResolutionInput.tsx
Normal file
53
renderer/components/settings-tab/CustomResolutionInput.tsx
Normal file
@ -0,0 +1,53 @@
|
||||
import { customWidthAtom, useCustomWidthAtom } from "@/atoms/userSettingsAtom";
|
||||
import { useAtom } from "jotai";
|
||||
import React, { useState } from "react";
|
||||
import { Input } from "../ui/input";
|
||||
|
||||
export function CustomResolutionInput() {
|
||||
const [useCustomWidth, setUseCustomWidth] = useAtom(useCustomWidthAtom);
|
||||
const [customWidth, setCustomWidth] = useAtom(customWidthAtom);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="flex flex-col gap-1">
|
||||
<p className="text-sm font-medium">CUSTOM OUTPUT WIDTH</p>
|
||||
<p className="text-xs text-base-content/80">
|
||||
<b>REQUIRES RESTART</b>
|
||||
<br />
|
||||
Use a custom width for the output images. The height will be adjusted
|
||||
automatically. Enabling this will override the scale setting.
|
||||
</p>
|
||||
</div>
|
||||
<div className="mt-2 flex items-center gap-2">
|
||||
<input
|
||||
type="checkbox"
|
||||
className="toggle"
|
||||
checked={useCustomWidth}
|
||||
onClick={(e) => {
|
||||
if (!e.currentTarget.checked) {
|
||||
localStorage.removeItem("customWidth");
|
||||
}
|
||||
setUseCustomWidth(!useCustomWidth);
|
||||
}}
|
||||
/>
|
||||
<input
|
||||
type="number"
|
||||
value={customWidth}
|
||||
disabled={!useCustomWidth}
|
||||
onChange={(e) => {
|
||||
if (e.currentTarget.value === "") {
|
||||
setUseCustomWidth(false);
|
||||
setCustomWidth(null);
|
||||
localStorage.removeItem("customWidth");
|
||||
return;
|
||||
}
|
||||
setCustomWidth(parseInt(e.currentTarget.value));
|
||||
}}
|
||||
step="1"
|
||||
min="1"
|
||||
className="input input-primary h-7 w-32 [appearance:textfield] [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
@ -1,13 +1,20 @@
|
||||
import { useCustomWidthAtom } from "@/atoms/userSettingsAtom";
|
||||
import { useAtom } from "jotai";
|
||||
|
||||
type ImageScaleSelectProps = {
|
||||
scale: "4" | "2" | "3";
|
||||
setScale: (arg: "4" | "2" | "3") => void;
|
||||
};
|
||||
|
||||
export function ImageScaleSelect({ scale, setScale }: ImageScaleSelectProps) {
|
||||
const [useCustomWidth, setUseCustomWidth] = useAtom(useCustomWidthAtom);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className={`${useCustomWidth && "opacity-50"}`}>
|
||||
<div className="flex flex-row gap-1">
|
||||
<p className="text-sm font-medium">IMAGE SCALE ({scale}X)</p>
|
||||
<p className="text-sm font-medium">
|
||||
IMAGE SCALE ({scale}X) {useCustomWidth && "DISABLED"}
|
||||
</p>
|
||||
</div>
|
||||
<p className="text-xs text-base-content/80">
|
||||
Anything above 4X (except 16X Double Upscayl) only resizes the image and
|
||||
@ -23,14 +30,8 @@ export function ImageScaleSelect({ scale, setScale }: ImageScaleSelectProps) {
|
||||
}}
|
||||
step="1"
|
||||
className="range range-primary mt-2"
|
||||
disabled={useCustomWidth}
|
||||
/>
|
||||
{/* <div className="flex w-full justify-between px-2 text-xs font-semibold text-base-content">
|
||||
<span>1</span>
|
||||
<span>4</span>
|
||||
<span>8</span>
|
||||
<span>12</span>
|
||||
<span>16</span>
|
||||
</div> */}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ import { ResetSettings } from "./ResetSettings";
|
||||
import { featureFlags } from "@common/feature-flags";
|
||||
import TurnOffNotificationsToggle from "./TurnOffNotificationsToggle";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { CustomResolutionInput } from "./CustomResolutionInput";
|
||||
|
||||
interface IProps {
|
||||
batchMode: boolean;
|
||||
@ -225,6 +226,8 @@ function SettingsTab({
|
||||
{/* IMAGE SCALE */}
|
||||
<ImageScaleSelect scale={scale} setScale={setScale} />
|
||||
|
||||
<CustomResolutionInput />
|
||||
|
||||
<CompressionInput
|
||||
compression={compression}
|
||||
handleCompressionChange={handleCompressionChange}
|
||||
@ -250,7 +253,7 @@ function SettingsTab({
|
||||
{featureFlags.SHOW_UPSCAYL_CLOUD_INFO && (
|
||||
<>
|
||||
<button
|
||||
className="rounded-btn mx-5 mb-5 animate-pulse bg-success p-1 text-sm text-slate-50 shadow-lg shadow-success/40"
|
||||
className="mx-5 mb-5 animate-pulse rounded-btn bg-success p-1 text-sm text-slate-50 shadow-lg shadow-success/40"
|
||||
onClick={() => {
|
||||
setShow(true);
|
||||
}}
|
||||
|
25
renderer/components/ui/input.tsx
Normal file
25
renderer/components/ui/input.tsx
Normal file
@ -0,0 +1,25 @@
|
||||
import * as React from "react"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
export interface InputProps
|
||||
extends React.InputHTMLAttributes<HTMLInputElement> {}
|
||||
|
||||
const Input = React.forwardRef<HTMLInputElement, InputProps>(
|
||||
({ className, type, ...props }, ref) => {
|
||||
return (
|
||||
<input
|
||||
type={type}
|
||||
className={cn(
|
||||
"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
|
||||
className
|
||||
)}
|
||||
ref={ref}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
)
|
||||
Input.displayName = "Input"
|
||||
|
||||
export { Input }
|
@ -26,6 +26,8 @@ import {
|
||||
viewTypeAtom,
|
||||
rememberOutputFolderAtom,
|
||||
showSidebarAtom,
|
||||
customWidthAtom,
|
||||
useCustomWidthAtom,
|
||||
} from "../atoms/userSettingsAtom";
|
||||
import useLog from "../components/hooks/useLog";
|
||||
import { UpscaylCloudModal } from "../components/UpscaylCloudModal";
|
||||
@ -87,6 +89,8 @@ const Home = () => {
|
||||
const lensSize = useAtomValue(lensSizeAtom);
|
||||
const rememberOutputFolder = useAtomValue(rememberOutputFolderAtom);
|
||||
const [showSidebar, setShowSidebar] = useAtom(showSidebarAtom);
|
||||
const customWidth = useAtomValue(customWidthAtom);
|
||||
const useCustomWidth = useAtomValue(useCustomWidthAtom);
|
||||
|
||||
const { logit } = useLog();
|
||||
|
||||
@ -459,6 +463,8 @@ const Home = () => {
|
||||
scale,
|
||||
noImageProcessing,
|
||||
compression: compression.toString(),
|
||||
useCustomWidth,
|
||||
customWidth: customWidth.toString(),
|
||||
});
|
||||
logit("🏁 DOUBLE_UPSCAYL");
|
||||
} else if (batchMode) {
|
||||
@ -473,6 +479,8 @@ const Home = () => {
|
||||
scale,
|
||||
noImageProcessing,
|
||||
compression: compression.toString(),
|
||||
customWidth: customWidth.toString(),
|
||||
useCustomWidth,
|
||||
});
|
||||
logit("🏁 FOLDER_UPSCAYL");
|
||||
} else {
|
||||
@ -487,6 +495,8 @@ const Home = () => {
|
||||
overwrite,
|
||||
noImageProcessing,
|
||||
compression: compression.toString(),
|
||||
customWidth: customWidth.toString(),
|
||||
useCustomWidth,
|
||||
});
|
||||
logit("🏁 UPSCAYL");
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user