add gradually inpainting mode

This commit is contained in:
Qing 2022-06-13 16:50:51 +08:00
parent d43d0694c2
commit 335685d581
15 changed files with 246 additions and 6 deletions

View File

@ -9,6 +9,7 @@
"@radix-ui/react-select": "0.1.2-rc.27", "@radix-ui/react-select": "0.1.2-rc.27",
"@radix-ui/react-switch": "^0.1.5", "@radix-ui/react-switch": "^0.1.5",
"@radix-ui/react-toast": "^0.1.1", "@radix-ui/react-toast": "^0.1.1",
"@radix-ui/react-tooltip": "^0.1.7",
"@testing-library/jest-dom": "^5.14.1", "@testing-library/jest-dom": "^5.14.1",
"@testing-library/react": "^12.1.2", "@testing-library/react": "^12.1.2",
"@testing-library/user-event": "^13.5.0", "@testing-library/user-event": "^13.5.0",

View File

@ -35,7 +35,6 @@ export default async function inpaint(
method: 'POST', method: 'POST',
body: fd, body: fd,
}).then(async r => { }).then(async r => {
console.log(r)
if (r.ok) { if (r.ok) {
return r.blob() return r.blob()
} }

View File

@ -26,6 +26,7 @@ import {
isMidClick, isMidClick,
isRightClick, isRightClick,
loadImage, loadImage,
srcToFile,
useImage, useImage,
} from '../../utils' } from '../../utils'
import { settingState, toastState } from '../../store/Atoms' import { settingState, toastState } from '../../store/Atoms'
@ -150,9 +151,16 @@ export default function Editor(props: EditorProps) {
setIsInpaintingLoading(true) setIsInpaintingLoading(true)
drawAllLinesOnMask(newLineGroups) drawAllLinesOnMask(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)
}
try { try {
const res = await inpaint( const res = await inpaint(
file, targetFile,
maskCanvas.toDataURL(), maskCanvas.toDataURL(),
settings, settings,
sizeLimit.toString() sizeLimit.toString()

View File

@ -0,0 +1,32 @@
import React from 'react'
import { useRecoilState } from 'recoil'
import { settingState } from '../../store/Atoms'
import { Switch, SwitchThumb } from '../shared/Switch'
import SettingBlock from './SettingBlock'
const GraduallyInpaintingSettingBlock: React.FC = () => {
const [setting, setSettingState] = useRecoilState(settingState)
const onCheckChange = (checked: boolean) => {
setSettingState(old => {
return { ...old, graduallyInpainting: checked }
})
}
return (
<SettingBlock
title="Gradually Inpainting"
desc="If checked, perform inpainting on the last result, otherwise, always run the model on the initial image."
input={
<Switch
checked={setting.graduallyInpainting}
onCheckedChange={onCheckChange}
>
<SwitchThumb />
</Switch>
}
/>
)
}
export default GraduallyInpaintingSettingBlock

View File

@ -25,8 +25,10 @@
.setting-block-content-title { .setting-block-content-title {
display: flex; display: flex;
flex-direction: column; flex-direction: row;
justify-content: space-between; justify-content: center;
align-items: center;
gap: 8px;
} }
.setting-block-desc { .setting-block-desc {

View File

@ -1,4 +1,5 @@
import React, { ReactNode } from 'react' import React, { ReactNode } from 'react'
import Tooltip from '../shared/Tooltip'
interface SettingBlockProps { interface SettingBlockProps {
title: string title: string
@ -15,7 +16,24 @@ function SettingBlock(props: SettingBlockProps) {
<div className="setting-block-content"> <div className="setting-block-content">
<div className="setting-block-content-title"> <div className="setting-block-content-title">
<span>{title}</span> <span>{title}</span>
{desc && <span className="setting-block-desc">{desc}</span>} {desc && (
<Tooltip content={<div style={{ width: 400 }}>{desc}</div>}>
<svg
width="18"
height="18"
viewBox="0 0 15 15"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M0.877075 7.49972C0.877075 3.84204 3.84222 0.876892 7.49991 0.876892C11.1576 0.876892 14.1227 3.84204 14.1227 7.49972C14.1227 11.1574 11.1576 14.1226 7.49991 14.1226C3.84222 14.1226 0.877075 11.1574 0.877075 7.49972ZM7.49991 1.82689C4.36689 1.82689 1.82708 4.36671 1.82708 7.49972C1.82708 10.6327 4.36689 13.1726 7.49991 13.1726C10.6329 13.1726 13.1727 10.6327 13.1727 7.49972C13.1727 4.36671 10.6329 1.82689 7.49991 1.82689ZM8.24993 10.5C8.24993 10.9142 7.91414 11.25 7.49993 11.25C7.08571 11.25 6.74993 10.9142 6.74993 10.5C6.74993 10.0858 7.08571 9.75 7.49993 9.75C7.91414 9.75 8.24993 10.0858 8.24993 10.5ZM6.05003 6.25C6.05003 5.57211 6.63511 4.925 7.50003 4.925C8.36496 4.925 8.95003 5.57211 8.95003 6.25C8.95003 6.74118 8.68002 6.99212 8.21447 7.27494C8.16251 7.30651 8.10258 7.34131 8.03847 7.37854L8.03841 7.37858C7.85521 7.48497 7.63788 7.61119 7.47449 7.73849C7.23214 7.92732 6.95003 8.23198 6.95003 8.7C6.95004 9.00376 7.19628 9.25 7.50004 9.25C7.8024 9.25 8.04778 9.00601 8.05002 8.70417L8.05056 8.7033C8.05924 8.6896 8.08493 8.65735 8.15058 8.6062C8.25207 8.52712 8.36508 8.46163 8.51567 8.37436L8.51571 8.37433C8.59422 8.32883 8.68296 8.27741 8.78559 8.21506C9.32004 7.89038 10.05 7.35382 10.05 6.25C10.05 4.92789 8.93511 3.825 7.50003 3.825C6.06496 3.825 4.95003 4.92789 4.95003 6.25C4.95003 6.55376 5.19628 6.8 5.50003 6.8C5.80379 6.8 6.05003 6.55376 6.05003 6.25Z"
fill="currentColor"
fillRule="evenodd"
clipRule="evenodd"
/>
</svg>
</Tooltip>
)}
</div> </div>
{input} {input}
</div> </div>

View File

@ -6,6 +6,7 @@ import Modal from '../shared/Modal'
import ManualRunInpaintingSettingBlock from './ManualRunInpaintingSettingBlock' import ManualRunInpaintingSettingBlock from './ManualRunInpaintingSettingBlock'
import HDSettingBlock from './HDSettingBlock' import HDSettingBlock from './HDSettingBlock'
import ModelSettingBlock from './ModelSettingBlock' import ModelSettingBlock from './ModelSettingBlock'
import GraduallyInpaintingSettingBlock from './GraduallyInpaintingSettingBlock'
interface SettingModalProps { interface SettingModalProps {
onClose: () => void onClose: () => void
@ -29,6 +30,7 @@ export default function SettingModal(props: SettingModalProps) {
show={setting.show} show={setting.show}
> >
<ManualRunInpaintingSettingBlock /> <ManualRunInpaintingSettingBlock />
<GraduallyInpaintingSettingBlock />
<ModelSettingBlock /> <ModelSettingBlock />
<HDSettingBlock /> <HDSettingBlock />
</Modal> </Modal>

View File

@ -31,3 +31,40 @@ $tooltip-margin: 1.5rem;
margin-top: $tooltip-margin; margin-top: $tooltip-margin;
} }
} }
// radix-ui
.tooltip-trigger {
all: unset;
display: flex;
justify-content: center;
align-items: center;
}
.tooltip-content {
color: var(--tooltip-text-color);
background-color: var(--tooltip-bg);
padding: 10px 15px;
border-radius: 4px;
box-shadow: hsl(206 22% 7% / 35%) 0px 10px 38px -10px,
hsl(206 22% 7% / 20%) 0px 10px 20px -15px;
@media (prefers-reduced-motion: no-preference) {
animation-duration: 400ms;
animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1);
animation-fill-mode: forwards;
will-change: transform, opacity;
&[data-state='delayed-open'] {
&[data-side='top'] {
animation-name: slideDownAndFade;
}
&[data-side='bottom'] {
animation-name: slideUpAndFade;
}
}
}
}
.tooltip-arrow {
fill: var(--tooltip-bg);
}

View File

@ -0,0 +1,29 @@
import React, { ReactNode } from 'react'
import * as TooltipPrimitive from '@radix-ui/react-tooltip'
import { TooltipProps } from '@radix-ui/react-tooltip'
interface MyTooltipProps extends TooltipProps {
content: string | ReactNode
children: ReactNode
}
const Tooltip = (props: MyTooltipProps) => {
const { content, children } = props
return (
<TooltipPrimitive.Root>
<TooltipPrimitive.Provider>
<TooltipPrimitive.Trigger className="tooltip-trigger">
{children}
</TooltipPrimitive.Trigger>
<TooltipPrimitive.Content className="tooltip-content">
{content}
<TooltipPrimitive.Arrow className="tooltip-arrow" />
</TooltipPrimitive.Content>
</TooltipPrimitive.Provider>
</TooltipPrimitive.Root>
)
}
export default Tooltip

View File

@ -32,6 +32,7 @@ export const shortcutsState = atom<boolean>({
export interface Settings { export interface Settings {
show: boolean show: boolean
graduallyInpainting: boolean
runInpaintingManually: boolean runInpaintingManually: boolean
model: AIModel model: AIModel
@ -48,6 +49,7 @@ export interface Settings {
export const settingStateDefault = { export const settingStateDefault = {
show: false, show: false,
graduallyInpainting: false,
runInpaintingManually: false, runInpaintingManually: false,
model: AIModel.LAMA, model: AIModel.LAMA,
ldmSteps: 50, ldmSteps: 50,

View File

@ -55,3 +55,25 @@
transform: rotate(360deg); transform: rotate(360deg);
} }
} }
@keyframes slideUpAndFade {
0% {
opacity: 0;
transform: translateY(2px);
}
100% {
opacity: 1;
transform: translateY(0);
}
}
@keyframes slideDownAndFade {
0% {
opacity: 0;
transform: translateY(-2px);
}
100% {
opacity: 1;
transform: translateY(0);
}
}

View File

@ -10,7 +10,7 @@
--border-color: rgb(100, 100, 120); --border-color: rgb(100, 100, 120);
--border-color-light: rgba(100, 100, 120, 0.5); --border-color-light: rgba(100, 100, 120, 0.5);
--tooltip-bg: rgb(230, 230, 234); --tooltip-bg: rgb(230, 230, 234);
--tooltip-text-color: rgb(0, 0,0); --tooltip-text-color: rgb(0, 0, 0);
--error-color: rgb(239, 68, 68); --error-color: rgb(239, 68, 68);
--success-color: rgb(16, 185, 129); --success-color: rgb(16, 185, 129);
@ -44,4 +44,7 @@
--switch-root-background-color: rgb(223, 225, 228); --switch-root-background-color: rgb(223, 225, 228);
--switch-thumb-color: var(--page-bg); --switch-thumb-color: var(--page-bg);
--switch-thumb-checked-color: var(--page-bg); --switch-thumb-checked-color: var(--page-bg);
// tooltip
--tooltip-bg: var(--page-bg);
} }

View File

@ -42,4 +42,7 @@
--switch-root-background-color: rgb(60, 63, 68); --switch-root-background-color: rgb(60, 63, 68);
--switch-thumb-color: rgb(31, 32, 35); --switch-thumb-color: rgb(31, 32, 35);
--switch-thumb-checked-color: white; --switch-thumb-checked-color: white;
// tooltip
--tooltip-bg: hsl(197 6.8% 13.6%);
} }

View File

@ -192,3 +192,13 @@ export function isMidClick(ev: SyntheticEvent) {
const mouseEvent = ev.nativeEvent as MouseEvent const mouseEvent = ev.nativeEvent as MouseEvent
return mouseEvent.button === 1 return mouseEvent.button === 1
} }
export function srcToFile(src: string, fileName: string, mimeType: string) {
return fetch(src)
.then(function (res) {
return res.arrayBuffer()
})
.then(function (buf) {
return new File([buf], fileName, { type: mimeType })
})
}

View File

@ -1551,6 +1551,14 @@
dependencies: dependencies:
"@babel/runtime" "^7.13.10" "@babel/runtime" "^7.13.10"
"@radix-ui/popper@0.1.0":
version "0.1.0"
resolved "https://registry.npmmirror.com/@radix-ui/popper/-/popper-0.1.0.tgz#c387a38f31b7799e1ea0d2bb1ca0c91c2931b063"
integrity sha512-uzYeElL3w7SeNMuQpXiFlBhTT+JyaNMCwDfjKkrzugEcYrf5n52PHqncNdQPUtR42hJh8V9FsqyEDbDxkeNjJQ==
dependencies:
"@babel/runtime" "^7.13.10"
csstype "^3.0.4"
"@radix-ui/primitive@0.1.0": "@radix-ui/primitive@0.1.0":
version "0.1.0" version "0.1.0"
resolved "https://registry.npmmirror.com/@radix-ui/primitive/-/primitive-0.1.0.tgz#6206b97d379994f0d1929809db035733b337e543" resolved "https://registry.npmmirror.com/@radix-ui/primitive/-/primitive-0.1.0.tgz#6206b97d379994f0d1929809db035733b337e543"
@ -1558,6 +1566,14 @@
dependencies: dependencies:
"@babel/runtime" "^7.13.10" "@babel/runtime" "^7.13.10"
"@radix-ui/react-arrow@0.1.4":
version "0.1.4"
resolved "https://registry.npmmirror.com/@radix-ui/react-arrow/-/react-arrow-0.1.4.tgz#a871448a418cd3507d83840fdd47558cb961672b"
integrity sha512-BB6XzAb7Ml7+wwpFdYVtZpK1BlMgqyafSQNGzhIpSZ4uXvXOHPlR5GP8M449JkeQzgQjv9Mp1AsJxFC0KuOtuA==
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/react-primitive" "0.1.4"
"@radix-ui/react-collection@0.1.5-rc.18": "@radix-ui/react-collection@0.1.5-rc.18":
version "0.1.5-rc.18" version "0.1.5-rc.18"
resolved "https://registry.npmmirror.com/@radix-ui/react-collection/-/react-collection-0.1.5-rc.18.tgz#4dc03a8f464643748c0dad781b472f149d671d5c" resolved "https://registry.npmmirror.com/@radix-ui/react-collection/-/react-collection-0.1.5-rc.18.tgz#4dc03a8f464643748c0dad781b472f149d671d5c"
@ -1706,6 +1722,21 @@
"@radix-ui/react-id" "0.1.6-rc.18" "@radix-ui/react-id" "0.1.6-rc.18"
"@radix-ui/react-primitive" "0.1.5-rc.18" "@radix-ui/react-primitive" "0.1.5-rc.18"
"@radix-ui/react-popper@0.1.4":
version "0.1.4"
resolved "https://registry.npmmirror.com/@radix-ui/react-popper/-/react-popper-0.1.4.tgz#dfc055dcd7dfae6a2eff7a70d333141d15a5d029"
integrity sha512-18gDYof97t8UQa7zwklG1Dr8jIdj3u+rVOQLzPi9f5i1YQak/pVGkaqw8aY+iDUknKKuZniTk/7jbAJUYlKyOw==
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/popper" "0.1.0"
"@radix-ui/react-arrow" "0.1.4"
"@radix-ui/react-compose-refs" "0.1.0"
"@radix-ui/react-context" "0.1.1"
"@radix-ui/react-primitive" "0.1.4"
"@radix-ui/react-use-rect" "0.1.1"
"@radix-ui/react-use-size" "0.1.1"
"@radix-ui/rect" "0.1.1"
"@radix-ui/react-portal@0.1.4": "@radix-ui/react-portal@0.1.4":
version "0.1.4" version "0.1.4"
resolved "https://registry.npmmirror.com/@radix-ui/react-portal/-/react-portal-0.1.4.tgz#17bdce3d7f1a9a0b35cb5e935ab8bc562441a7d2" resolved "https://registry.npmmirror.com/@radix-ui/react-portal/-/react-portal-0.1.4.tgz#17bdce3d7f1a9a0b35cb5e935ab8bc562441a7d2"
@ -1833,6 +1864,27 @@
"@radix-ui/react-use-layout-effect" "0.1.0" "@radix-ui/react-use-layout-effect" "0.1.0"
"@radix-ui/react-visually-hidden" "0.1.4" "@radix-ui/react-visually-hidden" "0.1.4"
"@radix-ui/react-tooltip@^0.1.7":
version "0.1.7"
resolved "https://registry.npmmirror.com/@radix-ui/react-tooltip/-/react-tooltip-0.1.7.tgz#6f8c00d6e489565d14abf209ce0fb8853c8c8ee3"
integrity sha512-eiBUsVOHenZ0JR16tl970bB0DafJBz6mFgSGfIGIVpflFj0LIsIDiLMsYyvYdx1KwwsIUDTEZtxcPm/sWjPzqA==
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/primitive" "0.1.0"
"@radix-ui/react-compose-refs" "0.1.0"
"@radix-ui/react-context" "0.1.1"
"@radix-ui/react-id" "0.1.5"
"@radix-ui/react-popper" "0.1.4"
"@radix-ui/react-portal" "0.1.4"
"@radix-ui/react-presence" "0.1.2"
"@radix-ui/react-primitive" "0.1.4"
"@radix-ui/react-slot" "0.1.2"
"@radix-ui/react-use-controllable-state" "0.1.0"
"@radix-ui/react-use-escape-keydown" "0.1.0"
"@radix-ui/react-use-previous" "0.1.1"
"@radix-ui/react-use-rect" "0.1.1"
"@radix-ui/react-visually-hidden" "0.1.4"
"@radix-ui/react-use-body-pointer-events@0.1.1": "@radix-ui/react-use-body-pointer-events@0.1.1":
version "0.1.1" version "0.1.1"
resolved "https://registry.npmmirror.com/@radix-ui/react-use-body-pointer-events/-/react-use-body-pointer-events-0.1.1.tgz#63e7fd81ca7ffd30841deb584cd2b7f460df2597" resolved "https://registry.npmmirror.com/@radix-ui/react-use-body-pointer-events/-/react-use-body-pointer-events-0.1.1.tgz#63e7fd81ca7ffd30841deb584cd2b7f460df2597"
@ -1923,6 +1975,14 @@
dependencies: dependencies:
"@babel/runtime" "^7.13.10" "@babel/runtime" "^7.13.10"
"@radix-ui/react-use-rect@0.1.1":
version "0.1.1"
resolved "https://registry.npmmirror.com/@radix-ui/react-use-rect/-/react-use-rect-0.1.1.tgz#6c15384beee59c086e75b89a7e66f3d2e583a856"
integrity sha512-kHNNXAsP3/PeszEmM/nxBBS9Jbo93sO+xuMTcRfwzXsmxT5gDXQzAiKbZQ0EecCPtJIzqvr7dlaQi/aP1PKYqQ==
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/rect" "0.1.1"
"@radix-ui/react-use-size@0.1.1": "@radix-ui/react-use-size@0.1.1":
version "0.1.1" version "0.1.1"
resolved "https://registry.npmmirror.com/@radix-ui/react-use-size/-/react-use-size-0.1.1.tgz#f6b75272a5d41c3089ca78c8a2e48e5f204ef90f" resolved "https://registry.npmmirror.com/@radix-ui/react-use-size/-/react-use-size-0.1.1.tgz#f6b75272a5d41c3089ca78c8a2e48e5f204ef90f"
@ -1946,6 +2006,13 @@
"@babel/runtime" "^7.13.10" "@babel/runtime" "^7.13.10"
"@radix-ui/react-primitive" "0.1.5-rc.18" "@radix-ui/react-primitive" "0.1.5-rc.18"
"@radix-ui/rect@0.1.1":
version "0.1.1"
resolved "https://registry.npmmirror.com/@radix-ui/rect/-/rect-0.1.1.tgz#95b5ba51f469bea6b1b841e2d427e17e37d38419"
integrity sha512-g3hnE/UcOg7REdewduRPAK88EPuLZtaq7sA9ouu8S+YEtnyFRI16jgv6GZYe3VMoQLL1T171ebmEPtDjyxWLzw==
dependencies:
"@babel/runtime" "^7.13.10"
"@rollup/plugin-node-resolve@^7.1.1": "@rollup/plugin-node-resolve@^7.1.1":
version "7.1.3" version "7.1.3"
resolved "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-7.1.3.tgz" resolved "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-7.1.3.tgz"
@ -4496,6 +4563,11 @@ csstype@^3.0.2, csstype@^3.0.6:
resolved "https://registry.npmjs.org/csstype/-/csstype-3.0.9.tgz" resolved "https://registry.npmjs.org/csstype/-/csstype-3.0.9.tgz"
integrity sha512-rpw6JPxK6Rfg1zLOYCSwle2GFOOsnjmDYDaBwEcwoOg4qlsIVCN789VkBZDJAGi4T07gI4YSutR43t9Zz4Lzuw== integrity sha512-rpw6JPxK6Rfg1zLOYCSwle2GFOOsnjmDYDaBwEcwoOg4qlsIVCN789VkBZDJAGi4T07gI4YSutR43t9Zz4Lzuw==
csstype@^3.0.4:
version "3.1.0"
resolved "https://registry.npmmirror.com/csstype/-/csstype-3.1.0.tgz#4ddcac3718d787cf9df0d1b7d15033925c8f29f2"
integrity sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==
cyclist@^1.0.1: cyclist@^1.0.1:
version "1.0.1" version "1.0.1"
resolved "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz" resolved "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz"