lots of updates

This commit is contained in:
Qing
2023-01-05 22:07:39 +08:00
parent 2e8e52f7a5
commit a22536becc
21 changed files with 394 additions and 74 deletions

View File

@@ -18,7 +18,10 @@ import {
} from 'react-zoom-pan-pinch'
import { useRecoilState, useRecoilValue } from 'recoil'
import { useWindowSize, useKey, useKeyPressEvent } from 'react-use'
import inpaint, { postInteractiveSeg } from '../../adapters/inpainting'
import inpaint, {
downloadToOutput,
postInteractiveSeg,
} from '../../adapters/inpainting'
import Button from '../shared/Button'
import Slider from './Slider'
import SizeSelector from './SizeSelector'
@@ -34,7 +37,10 @@ import {
} from '../../utils'
import {
croperState,
enableFileManagerState,
fileState,
imageHeightState,
imageWidthState,
interactiveSegClicksState,
isInpaintingState,
isInteractiveSegRunningState,
@@ -173,6 +179,10 @@ export default function Editor() {
const [redoRenders, setRedoRenders] = useState<HTMLImageElement[]>([])
const [redoCurLines, setRedoCurLines] = useState<Line[]>([])
const [redoLineGroups, setRedoLineGroups] = useState<LineGroup[]>([])
const enableFileManager = useRecoilValue(enableFileManagerState)
const [imageWidth, setImageWidth] = useRecoilState(imageWidthState)
const [imageHeight, setImageHeight] = useRecoilState(imageHeightState)
const draw = useCallback(
(render: HTMLImageElement, lineGroup: LineGroup) => {
@@ -524,6 +534,9 @@ export default function Editor() {
const rW = windowSize.width / original.naturalWidth
const rH = (windowSize.height - TOOLBAR_SIZE) / original.naturalHeight
setImageWidth(original.naturalWidth)
setImageHeight(original.naturalHeight)
let s = 1.0
if (rW < 1 || rH < 1) {
s = Math.min(rW, rH)
@@ -1054,6 +1067,27 @@ export default function Editor() {
if (file === undefined) {
return
}
if (enableFileManager && renders.length > 0) {
try {
downloadToOutput(renders[renders.length - 1], file.name, file.type)
setToastState({
open: true,
desc: `Save image success`,
state: 'success',
duration: 2000,
})
} catch (e: any) {
setToastState({
open: true,
desc: e.message ? e.message : e.toString(),
state: 'error',
duration: 2000,
})
}
return
}
// TODO: download to output directory
const name = file.name.replace(/(\.[\w\d_-]+)$/i, '_cleanup$1')
const curRender = renders[renders.length - 1]
downloadImage(curRender.currentSrc, name)

View File

@@ -6,14 +6,23 @@ type SliderProps = {
min?: number
max?: number
onChange: (value: number) => void
onClick: () => void
onClick?: () => void
width?: number
}
export default function Slider(props: SliderProps) {
const { value, onChange, onClick, label, min, max } = props
const { value, onChange, onClick, label, min, max, width } = props
const styles: any = {}
if (width !== undefined) {
styles.width = width
}
const step = ((max || 100) - (min || 0)) / 100
const onMouseUp = (e: React.MouseEvent<HTMLDivElement>) => {
e.currentTarget?.blur()
}
return (
<div className="editor-brush-slider">
<span>{label}</span>
@@ -29,6 +38,8 @@ export default function Slider(props: SliderProps) {
onChange(parseInt(ev.currentTarget.value, 10))
}}
onClick={onClick}
style={styles}
onMouseUp={onMouseUp}
/>
</div>
)

View File

@@ -5,7 +5,7 @@ import React, {
useState,
useCallback,
} from 'react'
import { useRecoilState, useRecoilValue } from 'recoil'
import { useRecoilState } from 'recoil'
import PhotoAlbum, { RenderPhoto } from 'react-photo-album'
import * as ScrollArea from '@radix-ui/react-scroll-area'
import Modal from '../shared/Modal'
@@ -127,7 +127,7 @@ export default function FileManager(props: Props) {
ref={onRefChange}
>
<PhotoAlbum
layout="columns"
layout="masonry"
photos={photos}
renderPhoto={renderPhoto}
spacing={8}

View File

@@ -21,7 +21,7 @@ function SettingBlock(props: SettingBlockProps) {
<div className={`setting-block ${className}`}>
<div className={contentClass}>
<div className="setting-block-content-title">
<div style={{ display: 'flex', alignItems: 'center', gap: '12px' }}>
<div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
{desc ? (
<Tooltip content={<div style={{ maxWidth: 400 }}>{desc}</div>}>
<span>{title}</span>

View File

@@ -1,8 +1,5 @@
import React, { FormEvent } from 'react'
import React from 'react'
import { useRecoilState, useRecoilValue } from 'recoil'
import { FolderOpenIcon } from '@heroicons/react/24/outline'
import * as Tabs from '@radix-ui/react-tabs'
import {
isPaintByExampleState,
isSDState,
@@ -14,10 +11,6 @@ import HDSettingBlock from './HDSettingBlock'
import ModelSettingBlock from './ModelSettingBlock'
import DownloadMaskSettingBlock from './DownloadMaskSettingBlock'
import useHotKey from '../../hooks/useHotkey'
import SettingBlock from './SettingBlock'
import { Switch, SwitchThumb } from '../shared/Switch'
import Button from '../shared/Button'
import TextInput from '../shared/Input'
declare module 'react' {
interface InputHTMLAttributes<T> extends HTMLAttributes<T> {

View File

@@ -0,0 +1,58 @@
import React from 'react'
import { useRecoilState, useRecoilValue } from 'recoil'
import { appState, croperState, settingState } from '../../store/Atoms'
import Slider from '../Editor/Slider'
import SettingBlock from '../Settings/SettingBlock'
const ImageResizeScale = () => {
const [setting, setSettingState] = useRecoilState(settingState)
const app = useRecoilValue(appState)
const croper = useRecoilValue(croperState)
const handleSliderChange = (value: number) => {
setSettingState(old => {
return { ...old, sdScale: value }
})
}
const scaledWidth = () => {
let width = app.imageWidth
if (setting.showCroper) {
width = croper.width
}
return Math.round((width * setting.sdScale) / 100)
}
const scaledHeight = () => {
let height = app.imageHeight
if (setting.showCroper) {
height = croper.height
}
return Math.round((height * setting.sdScale) / 100)
}
return (
<SettingBlock
className="sub-setting-block"
title="Resize"
titleSuffix={
<div
style={{ width: 86 }}
>{`(${scaledWidth()}x${scaledHeight()})`}</div>
}
desc="Resize the image before inpainting, the area outside the mask will not lose quality."
input={
<Slider
label=""
width={70}
min={50}
max={100}
value={setting.sdScale}
onChange={handleSliderChange}
/>
}
/>
)
}
export default ImageResizeScale

View File

@@ -14,6 +14,7 @@ import { Switch, SwitchThumb } from '../shared/Switch'
import Button from '../shared/Button'
import emitter, { EVENT_PAINT_BY_EXAMPLE } from '../../event'
import { useImage } from '../../utils'
import ImageResizeScale from './ImageResizeScale'
const INPUT_WIDTH = 30
@@ -68,22 +69,6 @@ const PESidePanel = () => {
</PopoverPrimitive.Trigger>
<PopoverPrimitive.Portal>
<PopoverPrimitive.Content className="side-panel-content">
<SettingBlock
title="Croper"
input={
<Switch
checked={setting.showCroper}
onCheckedChange={value => {
setSettingState(old => {
return { ...old, showCroper: value }
})
}}
>
<SwitchThumb />
</Switch>
}
/>
<NumberInputSetting
title="Steps"
width={INPUT_WIDTH}
@@ -97,6 +82,8 @@ const PESidePanel = () => {
}}
/>
<ImageResizeScale />
<NumberInputSetting
title="Guidance Scale"
width={INPUT_WIDTH}

View File

@@ -1,4 +1,4 @@
import React, { FormEvent, useState } from 'react'
import React, { FormEvent } from 'react'
import { useRecoilState, useRecoilValue } from 'recoil'
import * as PopoverPrimitive from '@radix-ui/react-popover'
import { useToggle } from 'react-use'
@@ -15,6 +15,7 @@ import Selector from '../shared/Selector'
import { Switch, SwitchThumb } from '../shared/Switch'
import TextAreaInput from '../shared/Textarea'
import emitter, { EVENT_PROMPT } from '../../event'
import ImageResizeScale from './ImageResizeScale'
const INPUT_WIDTH = 30
@@ -71,6 +72,9 @@ const SidePanel = () => {
</Switch>
}
/>
<ImageResizeScale />
{/*
<NumberInputSetting
title="Num Samples"
@@ -98,21 +102,6 @@ const SidePanel = () => {
}}
/>
{/* <NumberInputSetting
title="Strength"
width={INPUT_WIDTH}
allowFloat
value={`${setting.sdStrength}`}
desc="TODO"
onValue={value => {
const val = value.length === 0 ? 0 : parseFloat(value)
console.log(val)
setSettingState(old => {
return { ...old, sdStrength: val }
})
}}
/> */}
<NumberInputSetting
title="Guidance Scale"
width={INPUT_WIDTH}