diff --git a/lama_cleaner/app/src/adapters/inpainting.ts b/lama_cleaner/app/src/adapters/inpainting.ts index 7f48a21..fcd1cc7 100644 --- a/lama_cleaner/app/src/adapters/inpainting.ts +++ b/lama_cleaner/app/src/adapters/inpainting.ts @@ -9,7 +9,8 @@ export default async function inpaint( settings: Settings, croperRect: Rect, prompt?: string, - sizeLimit?: string + sizeLimit?: string, + seed?: number ) { // 1080, 2000, Original const fd = new FormData() @@ -42,7 +43,8 @@ export default async function inpaint( fd.append('sdSteps', settings.sdSteps.toString()) fd.append('sdGuidanceScale', settings.sdGuidanceScale.toString()) fd.append('sdSampler', settings.sdSampler.toString()) - fd.append('sdSeed', settings.sdSeedFixed ? settings.sdSeed.toString() : '-1') + // fd.append('sdSeed', settings.sdSeedFixed ? settings.sdSeed.toString() : '-1') + fd.append('sdSeed', seed ? seed.toString() : '-1') if (sizeLimit === undefined) { fd.append('sizeLimit', '1080') @@ -57,8 +59,8 @@ export default async function inpaint( }) if (res.ok) { const blob = await res.blob() - const seed = res.headers.get('x-seed') - return { blob: URL.createObjectURL(blob), seed } + const newSeed = res.headers.get('x-seed') + return { blob: URL.createObjectURL(blob), seed: newSeed } } } catch { throw new Error('Something went wrong on server side.') diff --git a/lama_cleaner/app/src/components/Editor/Editor.tsx b/lama_cleaner/app/src/components/Editor/Editor.tsx index b84c35b..aabca4d 100644 --- a/lama_cleaner/app/src/components/Editor/Editor.tsx +++ b/lama_cleaner/app/src/components/Editor/Editor.tsx @@ -41,7 +41,7 @@ import { } from '../../store/Atoms' import useHotKey from '../../hooks/useHotkey' import Croper from '../Croper/Croper' -import emitter, { EVENT_PROMPT } from '../../event' +import emitter, { EVENT_PROMPT, EVENT_RERUN } from '../../event' const TOOLBAR_SIZE = 200 const BRUSH_COLOR = '#ffcc00bb' @@ -102,6 +102,7 @@ export default function Editor(props: EditorProps) { return document.createElement('canvas') }) const [lineGroups, setLineGroups] = useState([]) + const [lastLineGroup, setLastLineGroup] = useState([]) const [curLineGroup, setCurLineGroup] = useState([]) const [{ x, y }, setCoords] = useState({ x: -1, y: -1 }) const [showBrush, setShowBrush] = useState(false) @@ -182,32 +183,65 @@ export default function Editor(props: EditorProps) { ) const runInpainting = useCallback( - async (prompt?: string) => { + async (prompt?: string, useLastLineGroup?: boolean) => { + // useLastLineGroup 的影响 + // 1. 使用上一次的 mask + // 2. 结果替换当前 render console.log('runInpainting') - if (!hadDrawSomething()) { - return - } - console.log(prompt) - const newLineGroups = [...lineGroups, curLineGroup] + let maskLineGroup = [] + if (useLastLineGroup === true) { + if (lastLineGroup.length === 0) { + return + } + maskLineGroup = lastLineGroup + } else { + if (!hadDrawSomething()) { + return + } + + setLastLineGroup(curLineGroup) + maskLineGroup = curLineGroup + } + + const newLineGroups = [...lineGroups, maskLineGroup] + setCurLineGroup([]) setIsDraging(false) setIsInpainting(true) if (settings.graduallyInpainting) { - drawLinesOnMask([curLineGroup]) + drawLinesOnMask([maskLineGroup]) } else { drawLinesOnMask(newLineGroups) } let targetFile = file - if (settings.graduallyInpainting === true && renders.length > 0) { - console.info('gradually inpainting on last result') - const lastRender = renders[renders.length - 1] - targetFile = await srcToFile( - lastRender.currentSrc, - file.name, - file.type - ) + if (settings.graduallyInpainting === true) { + if (useLastLineGroup === true) { + // renders.length == 1 还是用原来的 + if (renders.length > 1) { + const lastRender = renders[renders.length - 2] + targetFile = await srcToFile( + lastRender.currentSrc, + file.name, + file.type + ) + } + } else if (renders.length > 0) { + console.info('gradually inpainting on last result') + + const lastRender = renders[renders.length - 1] + targetFile = await srcToFile( + lastRender.currentSrc, + file.name, + file.type + ) + } + } + + let sdSeed = settings.sdSeedFixed ? settings.sdSeed : -1 + if (useLastLineGroup === true) { + sdSeed = -1 } try { @@ -217,7 +251,8 @@ export default function Editor(props: EditorProps) { settings, croperRect, prompt, - sizeLimit.toString() + sizeLimit.toString(), + sdSeed ) if (!res) { throw new Error('empty response') @@ -228,8 +263,16 @@ export default function Editor(props: EditorProps) { } const newRender = new Image() await loadImage(newRender, blob) - const newRenders = [...renders, newRender] - setRenders(newRenders) + + if (useLastLineGroup === true) { + const prevRenders = renders.slice(0, -1) + const newRenders = [...prevRenders, newRender] + setRenders(newRenders) + } else { + const newRenders = [...renders, newRender] + setRenders(newRenders) + } + draw(newRender, []) // Only append new LineGroup after inpainting success setLineGroups(newLineGroups) @@ -280,6 +323,26 @@ export default function Editor(props: EditorProps) { } }, [hadDrawSomething, runInpainting, prompt]) + useEffect(() => { + emitter.on(EVENT_RERUN, () => { + if (hadDrawSomething()) { + runInpainting(promptVal) + } else if (lastLineGroup.length !== 0) { + runInpainting(promptVal, true) + } else { + setToastState({ + open: true, + desc: 'Please draw mask on picture', + state: 'error', + duration: 1500, + }) + } + }) + return () => { + emitter.off(EVENT_RERUN) + } + }, [lastLineGroup, hadDrawSomething, runInpainting, prompt]) + const hadRunInpainting = () => { return renders.length !== 0 } @@ -547,6 +610,7 @@ export default function Editor(props: EditorProps) { if (curLineGroup.length === 0) { return } + setLastLineGroup([]) const lastLine = curLineGroup.pop()! const newRedoCurLines = [...redoCurLines, lastLine] @@ -563,8 +627,8 @@ export default function Editor(props: EditorProps) { } // save line Group - const lastLineGroup = lineGroups.pop()! - setRedoLineGroups([...redoLineGroups, lastLineGroup]) + const latestLineGroup = lineGroups.pop()! + setRedoLineGroups([...redoLineGroups, latestLineGroup]) // If render is undo, clear strokes setRedoCurLines([]) diff --git a/lama_cleaner/app/src/components/SidePanel/SidePanel.tsx b/lama_cleaner/app/src/components/SidePanel/SidePanel.tsx index 44337bb..15aca9b 100644 --- a/lama_cleaner/app/src/components/SidePanel/SidePanel.tsx +++ b/lama_cleaner/app/src/components/SidePanel/SidePanel.tsx @@ -8,7 +8,7 @@ import SettingBlock from '../Settings/SettingBlock' import Selector from '../shared/Selector' import { Switch, SwitchThumb } from '../shared/Switch' import Button from '../shared/Button' -import emitter, { EVENT_PROMPT } from '../../event' +import emitter, { EVENT_RERUN } from '../../event' const INPUT_WIDTH = 30 @@ -18,7 +18,7 @@ const SidePanel = () => { const [setting, setSettingState] = useRecoilState(settingState) const onReRunBtnClick = () => { - emitter.emit(EVENT_PROMPT) + emitter.emit(EVENT_RERUN) } return ( diff --git a/lama_cleaner/app/src/event.ts b/lama_cleaner/app/src/event.ts index e4344fb..1a38e51 100644 --- a/lama_cleaner/app/src/event.ts +++ b/lama_cleaner/app/src/event.ts @@ -1,6 +1,7 @@ import mitt from 'mitt' export const EVENT_PROMPT = 'prompt' +export const EVENT_RERUN = 'rerun_last_mask' const emitter = mitt()