include highres and upscale in params loading
This commit is contained in:
parent
9e350f09df
commit
626ca18d7f
|
@ -60,8 +60,8 @@ export interface BaseImgParams {
|
||||||
* Parameters for txt2img requests.
|
* Parameters for txt2img requests.
|
||||||
*/
|
*/
|
||||||
export interface Txt2ImgParams extends BaseImgParams {
|
export interface Txt2ImgParams extends BaseImgParams {
|
||||||
width?: number;
|
width: number;
|
||||||
height?: number;
|
height: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -71,7 +71,7 @@ export interface Img2ImgParams extends BaseImgParams {
|
||||||
source: Blob;
|
source: Blob;
|
||||||
|
|
||||||
loopback: number;
|
loopback: number;
|
||||||
sourceFilter?: string;
|
sourceFilter: string;
|
||||||
strength: number;
|
strength: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -267,6 +267,16 @@ export interface ImageResponseWithRetry {
|
||||||
retry: RetryParams;
|
retry: RetryParams;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ImageMetadata {
|
||||||
|
highres: HighresParams;
|
||||||
|
outputs: string | Array<string>;
|
||||||
|
params: Txt2ImgParams | Img2ImgParams | InpaintParams;
|
||||||
|
upscale: UpscaleParams;
|
||||||
|
|
||||||
|
input_size: ImageSize;
|
||||||
|
size: ImageSize;
|
||||||
|
}
|
||||||
|
|
||||||
export interface ApiClient {
|
export interface ApiClient {
|
||||||
extras(): Promise<ExtrasFile>;
|
extras(): Promise<ExtrasFile>;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { InvalidArgumentError, Maybe, doesExist, mustExist } from '@apextoaster/js-utils';
|
import { doesExist, InvalidArgumentError, Maybe, mustExist } from '@apextoaster/js-utils';
|
||||||
import { Delete as DeleteIcon, Download, ImageSearch, Save as SaveIcon } from '@mui/icons-material';
|
import { Delete as DeleteIcon, Download, ImageSearch, Save as SaveIcon } from '@mui/icons-material';
|
||||||
import {
|
import {
|
||||||
Autocomplete,
|
Autocomplete,
|
||||||
|
@ -20,19 +20,20 @@ import { useContext } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useStore } from 'zustand';
|
import { useStore } from 'zustand';
|
||||||
|
|
||||||
import { BaseImgParams, HighresParams, Txt2ImgParams, UpscaleParams } from '../client/types.js';
|
import { BaseImgParams, HighresParams, ImageMetadata, Txt2ImgParams, UpscaleParams } from '../client/types.js';
|
||||||
import { StateContext } from '../state.js';
|
import { StateContext } from '../state.js';
|
||||||
|
import { DeepPartial } from '../types.js';
|
||||||
|
|
||||||
const { useState, Fragment } = React;
|
const { useState } = React;
|
||||||
|
|
||||||
export interface ProfilesProps {
|
export interface ProfilesProps {
|
||||||
highres: HighresParams;
|
highres: HighresParams;
|
||||||
params: BaseImgParams;
|
params: BaseImgParams;
|
||||||
upscale: UpscaleParams;
|
upscale: UpscaleParams;
|
||||||
|
|
||||||
setHighres(params: HighresParams): void;
|
setHighres(params: Partial<HighresParams>): void;
|
||||||
setParams(params: BaseImgParams): void;
|
setParams(params: Partial<BaseImgParams>): void;
|
||||||
setUpscale(params: UpscaleParams): void;
|
setUpscale(params: Partial<UpscaleParams>): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Profiles(props: ProfilesProps) {
|
export function Profiles(props: ProfilesProps) {
|
||||||
|
@ -50,7 +51,7 @@ export function Profiles(props: ProfilesProps) {
|
||||||
|
|
||||||
return <Stack direction='row' spacing={2}>
|
return <Stack direction='row' spacing={2}>
|
||||||
<Autocomplete
|
<Autocomplete
|
||||||
id="profile-select"
|
id='profile-select'
|
||||||
options={profiles}
|
options={profiles}
|
||||||
sx={{ width: '25em' }}
|
sx={{ width: '25em' }}
|
||||||
getOptionLabel={(option) => option.name}
|
getOptionLabel={(option) => option.name}
|
||||||
|
@ -59,7 +60,7 @@ export function Profiles(props: ProfilesProps) {
|
||||||
<ListItem
|
<ListItem
|
||||||
{...optionProps}
|
{...optionProps}
|
||||||
secondaryAction={
|
secondaryAction={
|
||||||
<IconButton edge="end" onClick={(event) => {
|
<IconButton edge='end' onClick={(event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
removeProfile(option.name);
|
removeProfile(option.name);
|
||||||
}}>
|
}}>
|
||||||
|
@ -71,7 +72,7 @@ export function Profiles(props: ProfilesProps) {
|
||||||
</ListItem>
|
</ListItem>
|
||||||
)}
|
)}
|
||||||
renderInput={(params) => (
|
renderInput={(params) => (
|
||||||
<Stack direction="row">
|
<Stack direction='row'>
|
||||||
<TextField
|
<TextField
|
||||||
{...params}
|
{...params}
|
||||||
label={t('profile.load')}
|
label={t('profile.load')}
|
||||||
|
@ -80,7 +81,7 @@ export function Profiles(props: ProfilesProps) {
|
||||||
autoComplete: 'new-password', // disable autocomplete and autofill
|
autoComplete: 'new-password', // disable autocomplete and autofill
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Button type="button" variant="contained" onClick={() => setDialogOpen(true)}>
|
<Button type='button' variant='contained' onClick={() => setDialogOpen(true)}>
|
||||||
<SaveIcon />
|
<SaveIcon />
|
||||||
</Button>
|
</Button>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
@ -100,7 +101,7 @@ export function Profiles(props: ProfilesProps) {
|
||||||
<DialogTitle>{t('profile.saveProfile')}</DialogTitle>
|
<DialogTitle>{t('profile.saveProfile')}</DialogTitle>
|
||||||
<DialogContent>
|
<DialogContent>
|
||||||
<TextField
|
<TextField
|
||||||
variant="standard"
|
variant='standard'
|
||||||
label={t('profile.name')}
|
label={t('profile.name')}
|
||||||
value={profileName}
|
value={profileName}
|
||||||
onChange={(event) => setProfileName(event.target.value)}
|
onChange={(event) => setProfileName(event.target.value)}
|
||||||
|
@ -118,8 +119,8 @@ export function Profiles(props: ProfilesProps) {
|
||||||
saveProfile({
|
saveProfile({
|
||||||
params: props.params,
|
params: props.params,
|
||||||
name: profileName,
|
name: profileName,
|
||||||
highResParams: props.highres,
|
highres: props.highres,
|
||||||
upscaleParams: props.upscale,
|
upscale: props.upscale,
|
||||||
});
|
});
|
||||||
setDialogOpen(false);
|
setDialogOpen(false);
|
||||||
setProfileName('');
|
setProfileName('');
|
||||||
|
@ -127,7 +128,7 @@ export function Profiles(props: ProfilesProps) {
|
||||||
>{t('profile.save')}</Button>
|
>{t('profile.save')}</Button>
|
||||||
</DialogActions>
|
</DialogActions>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
<Button component='label' variant="contained">
|
<Button component='label' variant='contained'>
|
||||||
<ImageSearch />
|
<ImageSearch />
|
||||||
<input
|
<input
|
||||||
hidden
|
hidden
|
||||||
|
@ -139,11 +140,16 @@ export function Profiles(props: ProfilesProps) {
|
||||||
const file = mustExist(files[0]);
|
const file = mustExist(files[0]);
|
||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||||
loadParamsFromFile(file).then((newParams) => {
|
loadParamsFromFile(file).then((newParams) => {
|
||||||
if (doesExist(newParams)) {
|
if (doesExist(newParams.params)) {
|
||||||
props.setParams({
|
props.setParams(newParams.params);
|
||||||
...props.params,
|
}
|
||||||
...newParams,
|
|
||||||
});
|
if (doesExist(newParams.highres)) {
|
||||||
|
props.setHighres(newParams.highres);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (doesExist(newParams.upscale)) {
|
||||||
|
props.setUpscale(newParams.upscale);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -154,14 +160,14 @@ export function Profiles(props: ProfilesProps) {
|
||||||
/>
|
/>
|
||||||
</Button>
|
</Button>
|
||||||
<Button component='label' variant='contained' onClick={() => {
|
<Button component='label' variant='contained' onClick={() => {
|
||||||
downloadParamsAsFile(props.params);
|
downloadParamsAsFile(props);
|
||||||
}}>
|
}}>
|
||||||
<Download />
|
<Download />
|
||||||
</Button>
|
</Button>
|
||||||
</Stack>;
|
</Stack>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function loadParamsFromFile(file: File): Promise<Partial<Txt2ImgParams>> {
|
export async function loadParamsFromFile(file: File): Promise<DeepPartial<ImageMetadata>> {
|
||||||
const parts = file.name.toLocaleLowerCase().split('.');
|
const parts = file.name.toLocaleLowerCase().split('.');
|
||||||
const ext = parts[parts.length - 1];
|
const ext = parts[parts.length - 1];
|
||||||
|
|
||||||
|
@ -182,10 +188,8 @@ export async function loadParamsFromFile(file: File): Promise<Partial<Txt2ImgPar
|
||||||
/**
|
/**
|
||||||
* from https://stackoverflow.com/a/30800715
|
* from https://stackoverflow.com/a/30800715
|
||||||
*/
|
*/
|
||||||
export function downloadParamsAsFile(params: Txt2ImgParams): void {
|
export function downloadParamsAsFile(data: DeepPartial<ImageMetadata>): void {
|
||||||
const dataStr = 'data:text/json;charset=utf-8,' + encodeURIComponent(JSON.stringify({
|
const dataStr = 'data:text/json;charset=utf-8,' + encodeURIComponent(JSON.stringify(data));
|
||||||
params,
|
|
||||||
}));
|
|
||||||
const elem = document.createElement('a');
|
const elem = document.createElement('a');
|
||||||
elem.setAttribute('href', dataStr);
|
elem.setAttribute('href', dataStr);
|
||||||
elem.setAttribute('download', 'parameters.json');
|
elem.setAttribute('download', 'parameters.json');
|
||||||
|
@ -194,7 +198,7 @@ export function downloadParamsAsFile(params: Txt2ImgParams): void {
|
||||||
elem.remove();
|
elem.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function parseImageParams(file: File): Promise<Partial<Txt2ImgParams>> {
|
export async function parseImageParams(file: File): Promise<DeepPartial<ImageMetadata>> {
|
||||||
const tags = await ExifReader.load(file);
|
const tags = await ExifReader.load(file);
|
||||||
|
|
||||||
// handle lowercase variation from my earlier mistakes
|
// handle lowercase variation from my earlier mistakes
|
||||||
|
@ -234,8 +238,8 @@ export function decodeTag(tag: Maybe<ExifReader.XmpTag | (ExifReader.NumberTag &
|
||||||
throw new InvalidArgumentError('tag value cannot be decoded');
|
throw new InvalidArgumentError('tag value cannot be decoded');
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function parseJSONParams(json: string): Promise<Partial<Txt2ImgParams>> {
|
export async function parseJSONParams(json: string): Promise<DeepPartial<ImageMetadata>> {
|
||||||
const data = JSON.parse(json);
|
const data = JSON.parse(json) as DeepPartial<ImageMetadata>;
|
||||||
const params: Partial<Txt2ImgParams> = {
|
const params: Partial<Txt2ImgParams> = {
|
||||||
...data.params,
|
...data.params,
|
||||||
};
|
};
|
||||||
|
@ -246,7 +250,11 @@ export async function parseJSONParams(json: string): Promise<Partial<Txt2ImgPara
|
||||||
params.width = size.width;
|
params.width = size.width;
|
||||||
}
|
}
|
||||||
|
|
||||||
return params;
|
return {
|
||||||
|
params,
|
||||||
|
highres: data.highres,
|
||||||
|
upscale: data.upscale,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isProbablyJSON(maybeJSON: unknown): boolean {
|
export function isProbablyJSON(maybeJSON: unknown): boolean {
|
||||||
|
@ -255,7 +263,7 @@ export function isProbablyJSON(maybeJSON: unknown): boolean {
|
||||||
|
|
||||||
export const NEGATIVE_PROMPT_TAG = 'Negative prompt:';
|
export const NEGATIVE_PROMPT_TAG = 'Negative prompt:';
|
||||||
|
|
||||||
export async function parseAutoComment(comment: string): Promise<Partial<Txt2ImgParams>> {
|
export async function parseAutoComment(comment: string): Promise<DeepPartial<ImageMetadata>> {
|
||||||
if (isProbablyJSON(comment)) {
|
if (isProbablyJSON(comment)) {
|
||||||
return parseJSONParams(comment);
|
return parseJSONParams(comment);
|
||||||
}
|
}
|
||||||
|
@ -306,5 +314,7 @@ export async function parseAutoComment(comment: string): Promise<Partial<Txt2Img
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return params;
|
return {
|
||||||
|
params,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import { ModelParams } from '../../client/types.js';
|
import { ModelParams } from '../../client/types.js';
|
||||||
import { STALE_TIME } from '../../config.js';
|
import { STALE_TIME } from '../../config.js';
|
||||||
import { ClientContext, StateContext } from '../../state.js';
|
import { ClientContext } from '../../state.js';
|
||||||
import { QueryList } from '../input/QueryList.js';
|
import { QueryList } from '../input/QueryList.js';
|
||||||
|
|
||||||
export interface ModelControlProps {
|
export interface ModelControlProps {
|
||||||
|
@ -20,7 +20,6 @@ export function ModelControl(props: ModelControlProps) {
|
||||||
const { model, setModel } = props;
|
const { model, setModel } = props;
|
||||||
|
|
||||||
const client = mustExist(useContext(ClientContext));
|
const client = mustExist(useContext(ClientContext));
|
||||||
const state = mustExist(useContext(StateContext));
|
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const restart = useMutation(['restart'], async () => client.restart());
|
const restart = useMutation(['restart'], async () => client.restart());
|
||||||
|
|
|
@ -1,20 +1,21 @@
|
||||||
import { doesExist, mustExist } from '@apextoaster/js-utils';
|
import { doesExist, mustExist } from '@apextoaster/js-utils';
|
||||||
import { Box, Button, Stack } from '@mui/material';
|
import { Box, Button, Stack } from '@mui/material';
|
||||||
|
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { useContext } from 'react';
|
import { useContext } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
|
||||||
import { useStore } from 'zustand';
|
import { useStore } from 'zustand';
|
||||||
|
|
||||||
|
import { HighresParams, Img2ImgParams, ModelParams, UpscaleParams } from '../../client/types.js';
|
||||||
import { IMAGE_FILTER, STALE_TIME } from '../../config.js';
|
import { IMAGE_FILTER, STALE_TIME } from '../../config.js';
|
||||||
import { ClientContext, ConfigContext, StateContext } from '../../state.js';
|
import { ClientContext, ConfigContext, OnnxState, StateContext, TabState } from '../../state.js';
|
||||||
|
import { HighresControl } from '../control/HighresControl.js';
|
||||||
import { ImageControl } from '../control/ImageControl.js';
|
import { ImageControl } from '../control/ImageControl.js';
|
||||||
|
import { ModelControl } from '../control/ModelControl.js';
|
||||||
import { UpscaleControl } from '../control/UpscaleControl.js';
|
import { UpscaleControl } from '../control/UpscaleControl.js';
|
||||||
import { ImageInput } from '../input/ImageInput.js';
|
import { ImageInput } from '../input/ImageInput.js';
|
||||||
import { NumericField } from '../input/NumericField.js';
|
import { NumericField } from '../input/NumericField.js';
|
||||||
import { QueryList } from '../input/QueryList.js';
|
import { QueryList } from '../input/QueryList.js';
|
||||||
import { HighresControl } from '../control/HighresControl.js';
|
|
||||||
import { ModelControl } from '../control/ModelControl.js';
|
|
||||||
import { Profiles } from '../Profiles.js';
|
import { Profiles } from '../Profiles.js';
|
||||||
|
|
||||||
export function Img2Img() {
|
export function Img2Img() {
|
||||||
|
@ -43,11 +44,11 @@ export function Img2Img() {
|
||||||
});
|
});
|
||||||
|
|
||||||
const state = mustExist(useContext(StateContext));
|
const state = mustExist(useContext(StateContext));
|
||||||
const model = useStore(state, (s) => s.img2imgModel);
|
const model = useStore(state, selectModel);
|
||||||
const source = useStore(state, (s) => s.img2img.source);
|
const source = useStore(state, (s) => s.img2img.source);
|
||||||
const img2img = useStore(state, (s) => s.img2img);
|
const img2img = useStore(state, selectParams);
|
||||||
const highres = useStore(state, (s) => s.img2imgHighres);
|
const highres = useStore(state, selectHighres);
|
||||||
const upscale = useStore(state, (s) => s.img2imgUpscale);
|
const upscale = useStore(state, selectUpscale);
|
||||||
// eslint-disable-next-line @typescript-eslint/unbound-method
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||||
const setImg2Img = useStore(state, (s) => s.setImg2Img);
|
const setImg2Img = useStore(state, (s) => s.setImg2Img);
|
||||||
// eslint-disable-next-line @typescript-eslint/unbound-method
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||||
|
@ -62,7 +63,14 @@ export function Img2Img() {
|
||||||
|
|
||||||
return <Box>
|
return <Box>
|
||||||
<Stack spacing={2}>
|
<Stack spacing={2}>
|
||||||
<Profiles params={img2img} setParams={setImg2Img} highres={highres} setHighres={setHighres} upscale={upscale} setUpscale={setUpscale} />
|
<Profiles
|
||||||
|
params={img2img}
|
||||||
|
setParams={setImg2Img}
|
||||||
|
highres={highres}
|
||||||
|
setHighres={setHighres}
|
||||||
|
upscale={upscale}
|
||||||
|
setUpscale={setUpscale}
|
||||||
|
/>
|
||||||
<ModelControl model={model} setModel={setModel} />
|
<ModelControl model={model} setModel={setModel} />
|
||||||
<ImageInput
|
<ImageInput
|
||||||
filter={IMAGE_FILTER}
|
filter={IMAGE_FILTER}
|
||||||
|
@ -143,3 +151,19 @@ export function Img2Img() {
|
||||||
</Stack>
|
</Stack>
|
||||||
</Box>;
|
</Box>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function selectModel(state: OnnxState): ModelParams {
|
||||||
|
return state.img2imgModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function selectParams(state: OnnxState): TabState<Img2ImgParams> {
|
||||||
|
return state.img2img;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function selectHighres(state: OnnxState): HighresParams {
|
||||||
|
return state.img2imgHighres;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function selectUpscale(state: OnnxState): UpscaleParams {
|
||||||
|
return state.img2imgUpscale;
|
||||||
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { useTranslation } from 'react-i18next';
|
||||||
import { useStore } from 'zustand';
|
import { useStore } from 'zustand';
|
||||||
|
|
||||||
import { IMAGE_FILTER, STALE_TIME } from '../../config.js';
|
import { IMAGE_FILTER, STALE_TIME } from '../../config.js';
|
||||||
import { ClientContext, ConfigContext, StateContext } from '../../state.js';
|
import { ClientContext, ConfigContext, OnnxState, StateContext, TabState } from '../../state.js';
|
||||||
import { HighresControl } from '../control/HighresControl.js';
|
import { HighresControl } from '../control/HighresControl.js';
|
||||||
import { ImageControl } from '../control/ImageControl.js';
|
import { ImageControl } from '../control/ImageControl.js';
|
||||||
import { ModelControl } from '../control/ModelControl.js';
|
import { ModelControl } from '../control/ModelControl.js';
|
||||||
|
@ -18,6 +18,7 @@ import { MaskCanvas } from '../input/MaskCanvas.js';
|
||||||
import { NumericField } from '../input/NumericField.js';
|
import { NumericField } from '../input/NumericField.js';
|
||||||
import { QueryList } from '../input/QueryList.js';
|
import { QueryList } from '../input/QueryList.js';
|
||||||
import { Profiles } from '../Profiles.js';
|
import { Profiles } from '../Profiles.js';
|
||||||
|
import { ModelParams, InpaintParams, HighresParams, UpscaleParams } from '../../client/types.js';
|
||||||
|
|
||||||
export function Inpaint() {
|
export function Inpaint() {
|
||||||
const { params } = mustExist(useContext(ConfigContext));
|
const { params } = mustExist(useContext(ConfigContext));
|
||||||
|
@ -35,16 +36,16 @@ export function Inpaint() {
|
||||||
const { image, retry } = await client.outpaint(model, {
|
const { image, retry } = await client.outpaint(model, {
|
||||||
...inpaint,
|
...inpaint,
|
||||||
...outpaint,
|
...outpaint,
|
||||||
mask: mustExist(mask),
|
mask: mustExist(inpaint.mask),
|
||||||
source: mustExist(source),
|
source: mustExist(inpaint.source),
|
||||||
}, upscale, highres);
|
}, upscale, highres);
|
||||||
|
|
||||||
pushHistory(image, retry);
|
pushHistory(image, retry);
|
||||||
} else {
|
} else {
|
||||||
const { image, retry } = await client.inpaint(model, {
|
const { image, retry } = await client.inpaint(model, {
|
||||||
...inpaint,
|
...inpaint,
|
||||||
mask: mustExist(mask),
|
mask: mustExist(inpaint.mask),
|
||||||
source: mustExist(source),
|
source: mustExist(inpaint.source),
|
||||||
}, upscale, highres);
|
}, upscale, highres);
|
||||||
|
|
||||||
pushHistory(image, retry);
|
pushHistory(image, retry);
|
||||||
|
@ -52,7 +53,7 @@ export function Inpaint() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function preventInpaint(): boolean {
|
function preventInpaint(): boolean {
|
||||||
return doesExist(source) === false || doesExist(mask) === false;
|
return doesExist(inpaint.source) === false || doesExist(inpaint.mask) === false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function supportsInpaint(): boolean {
|
function supportsInpaint(): boolean {
|
||||||
|
@ -60,15 +61,12 @@ export function Inpaint() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const state = mustExist(useContext(StateContext));
|
const state = mustExist(useContext(StateContext));
|
||||||
const mask = useStore(state, (s) => s.inpaint.mask);
|
const inpaint = useStore(state, selectParams);
|
||||||
const source = useStore(state, (s) => s.inpaint.source);
|
const highres = useStore(state, selectHighres);
|
||||||
const inpaint = useStore(state, (s) => s.inpaint);
|
const model = useStore(state, selectModel);
|
||||||
|
const upscale = useStore(state, selectUpscale);
|
||||||
const outpaint = useStore(state, (s) => s.outpaint);
|
const outpaint = useStore(state, (s) => s.outpaint);
|
||||||
|
|
||||||
const brush = useStore(state, (s) => s.inpaintBrush);
|
const brush = useStore(state, (s) => s.inpaintBrush);
|
||||||
const highres = useStore(state, (s) => s.inpaintHighres);
|
|
||||||
const model = useStore(state, (s) => s.inpaintModel);
|
|
||||||
const upscale = useStore(state, (s) => s.inpaintUpscale);
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/unbound-method
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||||
const setInpaint = useStore(state, (s) => s.setInpaint);
|
const setInpaint = useStore(state, (s) => s.setInpaint);
|
||||||
|
@ -100,12 +98,19 @@ export function Inpaint() {
|
||||||
|
|
||||||
return <Box>
|
return <Box>
|
||||||
<Stack spacing={2}>
|
<Stack spacing={2}>
|
||||||
<Profiles params={inpaint} setParams={setInpaint} highres={highres} setHighres={setHighres} upscale={upscale} setUpscale={setUpscale} />
|
<Profiles
|
||||||
|
params={inpaint}
|
||||||
|
setParams={setInpaint}
|
||||||
|
highres={highres}
|
||||||
|
setHighres={setHighres}
|
||||||
|
upscale={upscale}
|
||||||
|
setUpscale={setUpscale}
|
||||||
|
/>
|
||||||
<ModelControl model={model} setModel={setModel} />
|
<ModelControl model={model} setModel={setModel} />
|
||||||
{renderBanner()}
|
{renderBanner()}
|
||||||
<ImageInput
|
<ImageInput
|
||||||
filter={IMAGE_FILTER}
|
filter={IMAGE_FILTER}
|
||||||
image={source}
|
image={inpaint.source}
|
||||||
label={t('input.image.source')}
|
label={t('input.image.source')}
|
||||||
hideSelection={true}
|
hideSelection={true}
|
||||||
onChange={(file) => {
|
onChange={(file) => {
|
||||||
|
@ -116,7 +121,7 @@ export function Inpaint() {
|
||||||
/>
|
/>
|
||||||
<ImageInput
|
<ImageInput
|
||||||
filter={IMAGE_FILTER}
|
filter={IMAGE_FILTER}
|
||||||
image={mask}
|
image={inpaint.mask}
|
||||||
label={t('input.image.mask')}
|
label={t('input.image.mask')}
|
||||||
hideSelection={true}
|
hideSelection={true}
|
||||||
onChange={(file) => {
|
onChange={(file) => {
|
||||||
|
@ -127,8 +132,8 @@ export function Inpaint() {
|
||||||
/>
|
/>
|
||||||
<MaskCanvas
|
<MaskCanvas
|
||||||
brush={brush}
|
brush={brush}
|
||||||
source={source}
|
source={inpaint.source}
|
||||||
mask={mask}
|
mask={inpaint.mask}
|
||||||
onSave={(file) => {
|
onSave={(file) => {
|
||||||
setInpaint({
|
setInpaint({
|
||||||
mask: file,
|
mask: file,
|
||||||
|
@ -232,3 +237,19 @@ export function Inpaint() {
|
||||||
</Stack>
|
</Stack>
|
||||||
</Box>;
|
</Box>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function selectModel(state: OnnxState): ModelParams {
|
||||||
|
return state.inpaintModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function selectParams(state: OnnxState): TabState<InpaintParams> {
|
||||||
|
return state.inpaint;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function selectHighres(state: OnnxState): HighresParams {
|
||||||
|
return state.inpaintHighres;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function selectUpscale(state: OnnxState): UpscaleParams {
|
||||||
|
return state.inpaintUpscale;
|
||||||
|
}
|
||||||
|
|
|
@ -6,13 +6,14 @@ import { useTranslation } from 'react-i18next';
|
||||||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||||
import { useStore } from 'zustand';
|
import { useStore } from 'zustand';
|
||||||
|
|
||||||
import { ClientContext, ConfigContext, StateContext } from '../../state.js';
|
import { ClientContext, ConfigContext, OnnxState, StateContext, TabState } from '../../state.js';
|
||||||
import { HighresControl } from '../control/HighresControl.js';
|
import { HighresControl } from '../control/HighresControl.js';
|
||||||
import { ImageControl } from '../control/ImageControl.js';
|
import { ImageControl } from '../control/ImageControl.js';
|
||||||
import { UpscaleControl } from '../control/UpscaleControl.js';
|
import { UpscaleControl } from '../control/UpscaleControl.js';
|
||||||
import { NumericField } from '../input/NumericField.js';
|
import { NumericField } from '../input/NumericField.js';
|
||||||
import { ModelControl } from '../control/ModelControl.js';
|
import { ModelControl } from '../control/ModelControl.js';
|
||||||
import { Profiles } from '../Profiles.js';
|
import { Profiles } from '../Profiles.js';
|
||||||
|
import { HighresParams, ModelParams, Txt2ImgParams, UpscaleParams } from '../../client/types.js';
|
||||||
|
|
||||||
export function Txt2Img() {
|
export function Txt2Img() {
|
||||||
const { params } = mustExist(useContext(ConfigContext));
|
const { params } = mustExist(useContext(ConfigContext));
|
||||||
|
@ -30,10 +31,10 @@ export function Txt2Img() {
|
||||||
});
|
});
|
||||||
|
|
||||||
const state = mustExist(useContext(StateContext));
|
const state = mustExist(useContext(StateContext));
|
||||||
const txt2img = useStore(state, (s) => s.txt2img);
|
const txt2img = useStore(state, selectParams);
|
||||||
const model = useStore(state, (s) => s.txt2imgModel);
|
const model = useStore(state, selectModel);
|
||||||
const highres = useStore(state, (s) => s.txt2imgHighres);
|
const highres = useStore(state, selectHighres);
|
||||||
const upscale = useStore(state, (s) => s.txt2imgUpscale);
|
const upscale = useStore(state, selectUpscale);
|
||||||
// eslint-disable-next-line @typescript-eslint/unbound-method
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||||
const setParams = useStore(state, (s) => s.setTxt2Img);
|
const setParams = useStore(state, (s) => s.setTxt2Img);
|
||||||
// eslint-disable-next-line @typescript-eslint/unbound-method
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||||
|
@ -48,7 +49,14 @@ export function Txt2Img() {
|
||||||
|
|
||||||
return <Box>
|
return <Box>
|
||||||
<Stack spacing={2}>
|
<Stack spacing={2}>
|
||||||
<Profiles params={txt2img} setParams={setParams} highres={highres} setHighres={setHighres} upscale={upscale} setUpscale={setUpscale} />
|
<Profiles
|
||||||
|
params={txt2img}
|
||||||
|
setParams={setParams}
|
||||||
|
highres={highres}
|
||||||
|
setHighres={setHighres}
|
||||||
|
upscale={upscale}
|
||||||
|
setUpscale={setUpscale}
|
||||||
|
/>
|
||||||
<ModelControl model={model} setModel={setModel} />
|
<ModelControl model={model} setModel={setModel} />
|
||||||
<ImageControl selector={(s) => s.txt2img} onChange={setParams} />
|
<ImageControl selector={(s) => s.txt2img} onChange={setParams} />
|
||||||
<Stack direction='row' spacing={4}>
|
<Stack direction='row' spacing={4}>
|
||||||
|
@ -86,3 +94,19 @@ export function Txt2Img() {
|
||||||
</Stack>
|
</Stack>
|
||||||
</Box>;
|
</Box>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function selectModel(state: OnnxState): ModelParams {
|
||||||
|
return state.txt2imgModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function selectParams(state: OnnxState): TabState<Txt2ImgParams> {
|
||||||
|
return state.txt2img;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function selectHighres(state: OnnxState): HighresParams {
|
||||||
|
return state.txt2imgHighres;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function selectUpscale(state: OnnxState): UpscaleParams {
|
||||||
|
return state.txt2imgUpscale;
|
||||||
|
}
|
||||||
|
|
|
@ -43,9 +43,9 @@ interface HistoryItem {
|
||||||
|
|
||||||
interface ProfileItem {
|
interface ProfileItem {
|
||||||
name: string;
|
name: string;
|
||||||
params: Txt2ImgParams;
|
params: BaseImgParams | Txt2ImgParams;
|
||||||
highResParams?: Maybe<HighresParams>;
|
highres?: Maybe<HighresParams>;
|
||||||
upscaleParams?: Maybe<UpscaleParams>;
|
upscale?: Maybe<UpscaleParams>;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface DefaultSlice {
|
interface DefaultSlice {
|
||||||
|
|
|
@ -72,3 +72,7 @@ export interface ExtrasFile {
|
||||||
networks: Array<ExtraNetwork>;
|
networks: Array<ExtraNetwork>;
|
||||||
sources: Array<ExtraSource>;
|
sources: Array<ExtraSource>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type DeepPartial<T> = T extends object ? {
|
||||||
|
[P in keyof T]?: DeepPartial<T[P]>;
|
||||||
|
} : T;
|
||||||
|
|
Loading…
Reference in New Issue