From 9e2921d3de6bf782d0c25efd15122d09de199341 Mon Sep 17 00:00:00 2001 From: Sean Sube Date: Sat, 14 Jan 2023 17:00:53 -0600 Subject: [PATCH] feat(gui): add outpainting dimension controls to inpaint tab --- gui/src/api/client.ts | 36 ++++++++----- gui/src/components/Inpaint.tsx | 2 + gui/src/components/OutpaintControl.tsx | 73 ++++++++++++++++++++++++++ gui/src/state.ts | 8 +++ 4 files changed, 106 insertions(+), 13 deletions(-) create mode 100644 gui/src/components/OutpaintControl.tsx diff --git a/gui/src/api/client.ts b/gui/src/api/client.ts index 4584baa2..b14be99d 100644 --- a/gui/src/api/client.ts +++ b/gui/src/api/client.ts @@ -1,4 +1,4 @@ -import { doesExist, NotImplementedError } from '@apextoaster/js-utils'; +import { doesExist } from '@apextoaster/js-utils'; import { ConfigParams } from '../config.js'; @@ -43,13 +43,11 @@ export type Txt2ImgResponse = Required; export interface InpaintParams extends BaseImgParams { mask: Blob; source: Blob; -} -export interface OutpaintParams extends Img2ImgParams { - up: boolean; - down: boolean; - left: boolean; - right: boolean; + left?: number; + right?: number; + top?: number; + bottom?: number; } export interface ApiResponse { @@ -72,9 +70,7 @@ export interface ApiClient { img2img(params: Img2ImgParams): Promise; txt2img(params: Txt2ImgParams): Promise; - inpaint(params: InpaintParams): Promise; - outpaint(params: OutpaintParams): Promise; ready(params: ApiResponse): Promise; } @@ -214,6 +210,23 @@ export function makeClient(root: string, f = fetch): ApiClient { const url = makeImageURL(root, 'inpaint', params); + if (doesExist(params.left)) { + url.searchParams.append('left', params.left.toFixed(0)); + } + + + if (doesExist(params.right)) { + url.searchParams.append('right', params.right.toFixed(0)); + } + + if (doesExist(params.top)) { + url.searchParams.append('top', params.top.toFixed(0)); + } + + if (doesExist(params.bottom)) { + url.searchParams.append('bottom', params.bottom.toFixed(0)); + } + const body = new FormData(); body.append('mask', params.mask, 'mask'); body.append('source', params.source, 'source'); @@ -226,9 +239,6 @@ export function makeClient(root: string, f = fetch): ApiClient { // eslint-disable-next-line no-return-await return await pending; }, - async outpaint() { - throw new NotImplementedError(); - }, async ready(params: ApiResponse): Promise { const path = makeApiUrl(root, 'ready'); path.searchParams.append('output', params.output.key); @@ -240,7 +250,7 @@ export function makeClient(root: string, f = fetch): ApiClient { } export async function parseApiResponse(root: string, res: Response): Promise { - type LimitedResponse = Omit & {output: string}; + type LimitedResponse = Omit & { output: string }; if (res.status === STATUS_SUCCESS) { const data = await res.json() as LimitedResponse; diff --git a/gui/src/components/Inpaint.tsx b/gui/src/components/Inpaint.tsx index f84d4f55..f441937d 100644 --- a/gui/src/components/Inpaint.tsx +++ b/gui/src/components/Inpaint.tsx @@ -9,6 +9,7 @@ import { ClientContext, StateContext } from '../state.js'; import { ImageControl } from './ImageControl.js'; import { ImageInput } from './ImageInput.js'; import { MaskCanvas } from './MaskCanvas.js'; +import { OutpaintControl } from './OutpaintControl.js'; const { useContext } = React; @@ -88,6 +89,7 @@ export function Inpaint(props: InpaintProps) { setInpaint(newParams); }} /> + ; diff --git a/gui/src/components/OutpaintControl.tsx b/gui/src/components/OutpaintControl.tsx new file mode 100644 index 00000000..d620936c --- /dev/null +++ b/gui/src/components/OutpaintControl.tsx @@ -0,0 +1,73 @@ +import { mustExist } from '@apextoaster/js-utils'; +import { Stack } from '@mui/material'; +import * as React from 'react'; +import { useContext } from 'react'; +import { useStore } from 'zustand'; + +import { ConfigParams } from '../config.js'; +import { StateContext } from '../state.js'; +import { NumericField } from './NumericField.js'; + +export interface OutpaintControlProps { + config: ConfigParams; +} + +export function OutpaintControl(props: OutpaintControlProps) { + const { config } = props; + + const state = mustExist(useContext(StateContext)); + const params = useStore(state, (s) => s.inpaint); + // eslint-disable-next-line @typescript-eslint/unbound-method + const setInpaint = useStore(state, (s) => s.setInpaint); + + return + { + setInpaint({ + left, + }); + }} + /> + { + setInpaint({ + right, + }); + }} + /> + { + setInpaint({ + top, + }); + }} + /> + { + setInpaint({ + bottom, + }); + }} + /> + ; +} diff --git a/gui/src/state.ts b/gui/src/state.ts index 22e2bed6..89887090 100644 --- a/gui/src/state.ts +++ b/gui/src/state.ts @@ -114,6 +114,10 @@ export function createStateSlices(base: ConfigParams) { ...defaults, mask: null, source: null, + left: 0, + right: 0, + top: 0, + bottom: 0, }, setInpaint(params) { set((prev) => ({ @@ -129,6 +133,10 @@ export function createStateSlices(base: ConfigParams) { ...defaults, mask: null, source: null, + left: 0, + right: 0, + top: 0, + bottom: 0, }, }); },