Skip to content

Commit

Permalink
feat(gui): add outpainting dimension controls to inpaint tab
Browse files Browse the repository at this point in the history
  • Loading branch information
ssube committed Jan 14, 2023
1 parent d9bbb9b commit 9e2921d
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 13 deletions.
36 changes: 23 additions & 13 deletions gui/src/api/client.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { doesExist, NotImplementedError } from '@apextoaster/js-utils';
import { doesExist } from '@apextoaster/js-utils';

import { ConfigParams } from '../config.js';

Expand Down Expand Up @@ -43,13 +43,11 @@ export type Txt2ImgResponse = Required<Txt2ImgParams>;
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 {
Expand All @@ -72,9 +70,7 @@ export interface ApiClient {

img2img(params: Img2ImgParams): Promise<ApiResponse>;
txt2img(params: Txt2ImgParams): Promise<ApiResponse>;

inpaint(params: InpaintParams): Promise<ApiResponse>;
outpaint(params: OutpaintParams): Promise<ApiResponse>;

ready(params: ApiResponse): Promise<ApiReady>;
}
Expand Down Expand Up @@ -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');
Expand All @@ -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<ApiReady> {
const path = makeApiUrl(root, 'ready');
path.searchParams.append('output', params.output.key);
Expand All @@ -240,7 +250,7 @@ export function makeClient(root: string, f = fetch): ApiClient {
}

export async function parseApiResponse(root: string, res: Response): Promise<ApiResponse> {
type LimitedResponse = Omit<ApiResponse, 'output'> & {output: string};
type LimitedResponse = Omit<ApiResponse, 'output'> & { output: string };

if (res.status === STATUS_SUCCESS) {
const data = await res.json() as LimitedResponse;
Expand Down
2 changes: 2 additions & 0 deletions gui/src/components/Inpaint.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -88,6 +89,7 @@ export function Inpaint(props: InpaintProps) {
setInpaint(newParams);
}}
/>
<OutpaintControl config={config} />
<Button onClick={() => upload.mutate()}>Generate</Button>
</Stack>
</Box>;
Expand Down
73 changes: 73 additions & 0 deletions gui/src/components/OutpaintControl.tsx
Original file line number Diff line number Diff line change
@@ -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 <Stack direction='row' spacing={4}>
<NumericField
label='Left'
min={0}
max={config.width.max}
step={config.width.step}
value={params.left}
onChange={(left) => {
setInpaint({
left,
});
}}
/>
<NumericField
label='Right'
min={0}
max={config.width.max}
step={config.width.step}
value={params.right}
onChange={(right) => {
setInpaint({
right,
});
}}
/>
<NumericField
label='Top'
min={0}
max={config.height.max}
step={config.height.step}
value={params.top}
onChange={(top) => {
setInpaint({
top,
});
}}
/>
<NumericField
label='Bottom'
min={0}
max={config.height.max}
step={config.height.step}
value={params.bottom}
onChange={(bottom) => {
setInpaint({
bottom,
});
}}
/>
</Stack>;
}
8 changes: 8 additions & 0 deletions gui/src/state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) => ({
Expand All @@ -129,6 +133,10 @@ export function createStateSlices(base: ConfigParams) {
...defaults,
mask: null,
source: null,
left: 0,
right: 0,
top: 0,
bottom: 0,
},
});
},
Expand Down

0 comments on commit 9e2921d

Please sign in to comment.