update
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { ModelInfo, Rect } from "@/lib/types"
|
||||
import { Settings } from "@/lib/states"
|
||||
import { dataURItoBlob, srcToFile } from "@/lib/utils"
|
||||
import { srcToFile } from "@/lib/utils"
|
||||
import axios from "axios"
|
||||
|
||||
export const API_ENDPOINT = import.meta.env.VITE_BACKEND
|
||||
@@ -15,6 +15,7 @@ export default async function inpaint(
|
||||
imageFile: File,
|
||||
settings: Settings,
|
||||
croperRect: Rect,
|
||||
extenderState: Rect,
|
||||
mask: File | Blob,
|
||||
paintByExampleImage: File | null = null
|
||||
) {
|
||||
@@ -32,11 +33,18 @@ export default async function inpaint(
|
||||
|
||||
fd.append("prompt", settings.prompt)
|
||||
fd.append("negativePrompt", settings.negativePrompt)
|
||||
|
||||
fd.append("useCroper", settings.showCropper ? "true" : "false")
|
||||
fd.append("croperX", croperRect.x.toString())
|
||||
fd.append("croperY", croperRect.y.toString())
|
||||
fd.append("croperHeight", croperRect.height.toString())
|
||||
fd.append("croperWidth", croperRect.width.toString())
|
||||
fd.append("useCroper", settings.showCropper ? "true" : "false")
|
||||
|
||||
fd.append("useExtender", settings.showExtender ? "true" : "false")
|
||||
fd.append("extenderX", extenderState.x.toString())
|
||||
fd.append("extenderY", extenderState.y.toString())
|
||||
fd.append("extenderHeight", extenderState.height.toString())
|
||||
fd.append("extenderWidth", extenderState.width.toString())
|
||||
|
||||
fd.append("sdMaskBlur", settings.sdMaskBlur.toString())
|
||||
fd.append("sdStrength", settings.sdStrength.toString())
|
||||
@@ -82,7 +90,7 @@ export default async function inpaint(
|
||||
})
|
||||
if (res.ok) {
|
||||
const blob = await res.blob()
|
||||
const newSeed = res.headers.get("x-seed")
|
||||
const newSeed = res.headers.get("X-seed")
|
||||
return { blob: URL.createObjectURL(blob), seed: newSeed }
|
||||
}
|
||||
const errMsg = await res.text()
|
||||
|
||||
@@ -8,6 +8,15 @@ export const MODEL_TYPE_DIFFUSERS_SDXL_INPAINT = "diffusers_sdxl_inpaint"
|
||||
export const MODEL_TYPE_OTHER = "diffusers_other"
|
||||
export const BRUSH_COLOR = "#ffcc00bb"
|
||||
|
||||
export const EXTENDER_X = "extender_x"
|
||||
export const EXTENDER_Y = "extender_y"
|
||||
export const EXTENDER_ALL = "extender_all"
|
||||
export const EXTENDER_BUILTIN_X_LEFT = "extender_builtin_x_left"
|
||||
export const EXTENDER_BUILTIN_X_RIGHT = "extender_builtin_x_right"
|
||||
export const EXTENDER_BUILTIN_Y_TOP = "extender_builtin_y_top"
|
||||
export const EXTENDER_BUILTIN_Y_BOTTOM = "extender_builtin_y_bottom"
|
||||
export const EXTENDER_BUILTIN_ALL = "extender_builtin_all"
|
||||
|
||||
export const PAINT_BY_EXAMPLE = "Fantasy-Studio/Paint-by-Example"
|
||||
export const INSTRUCT_PIX2PIX = "timbrooks/instruct-pix2pix"
|
||||
export const KANDINSKY_2_2 = "kandinsky-community/kandinsky-2-2-decoder-inpaint"
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
import mitt from "mitt"
|
||||
|
||||
export const EVENT_PROMPT = "prompt"
|
||||
|
||||
export const EVENT_CUSTOM_MASK = "custom_mask"
|
||||
export interface CustomMaskEventData {
|
||||
mask: File
|
||||
}
|
||||
|
||||
export const EVENT_PAINT_BY_EXAMPLE = "paint_by_example"
|
||||
export interface PaintByExampleEventData {
|
||||
image: File
|
||||
}
|
||||
|
||||
export const RERUN_LAST_MASK = "rerun_last_mask"
|
||||
|
||||
export const DREAM_BUTTON_MOUSE_ENTER = "dream_button_mouse_enter"
|
||||
export const DREAM_BUTTON_MOUSE_LEAVE = "dream_btoon_mouse_leave"
|
||||
|
||||
const emitter = mitt()
|
||||
|
||||
export default emitter
|
||||
@@ -21,6 +21,14 @@ import {
|
||||
BRUSH_COLOR,
|
||||
DEFAULT_BRUSH_SIZE,
|
||||
DEFAULT_NEGATIVE_PROMPT,
|
||||
EXTENDER_ALL,
|
||||
EXTENDER_BUILTIN_ALL,
|
||||
EXTENDER_BUILTIN_X_LEFT,
|
||||
EXTENDER_BUILTIN_X_RIGHT,
|
||||
EXTENDER_BUILTIN_Y_BOTTOM,
|
||||
EXTENDER_BUILTIN_Y_TOP,
|
||||
EXTENDER_X,
|
||||
EXTENDER_Y,
|
||||
MODEL_TYPE_INPAINT,
|
||||
PAINT_BY_EXAMPLE,
|
||||
} from "./const"
|
||||
@@ -56,7 +64,8 @@ export type Settings = {
|
||||
enableManualInpainting: boolean
|
||||
enableUploadMask: boolean
|
||||
showCropper: boolean
|
||||
showExpender: boolean
|
||||
showExtender: boolean
|
||||
extenderDirection: string
|
||||
|
||||
// For LDM
|
||||
ldmSteps: number
|
||||
@@ -168,6 +177,9 @@ type AppAction = {
|
||||
setExtenderY: (newValue: number) => void
|
||||
setExtenderWidth: (newValue: number) => void
|
||||
setExtenderHeight: (newValue: number) => void
|
||||
updateExtenderDirection: (newValue: string) => void
|
||||
resetExtender: (width: number, height: number) => void
|
||||
updateExtenderByBuiltIn: (direction: string, scale: number) => void
|
||||
|
||||
setServerConfig: (newValue: ServerConfig) => void
|
||||
setSeed: (newValue: number) => void
|
||||
@@ -281,7 +293,8 @@ const defaultValues: AppState = {
|
||||
},
|
||||
enableControlnet: false,
|
||||
showCropper: false,
|
||||
showExpender: false,
|
||||
showExtender: false,
|
||||
extenderDirection: EXTENDER_ALL,
|
||||
enableDownloadMask: false,
|
||||
enableManualInpainting: false,
|
||||
enableUploadMask: false,
|
||||
@@ -362,7 +375,7 @@ export const useStore = createWithEqualityFn<AppState & AppAction>()(
|
||||
}
|
||||
return targetFile
|
||||
},
|
||||
|
||||
// todo: 传入 custom mask,单独逻辑
|
||||
runInpainting: async () => {
|
||||
const {
|
||||
isInpainting,
|
||||
@@ -372,6 +385,7 @@ export const useStore = createWithEqualityFn<AppState & AppAction>()(
|
||||
imageHeight,
|
||||
settings,
|
||||
cropperState,
|
||||
extenderState,
|
||||
} = get()
|
||||
if (isInpainting) {
|
||||
return
|
||||
@@ -398,7 +412,11 @@ export const useStore = createWithEqualityFn<AppState & AppAction>()(
|
||||
// 2. 结果替换当前 render
|
||||
let maskLineGroup: LineGroup = []
|
||||
if (useLastLineGroup === true) {
|
||||
if (lastLineGroup.length === 0 && maskImage === null) {
|
||||
if (
|
||||
lastLineGroup.length === 0 &&
|
||||
maskImage === null &&
|
||||
!settings.showExtender
|
||||
) {
|
||||
toast({
|
||||
variant: "destructive",
|
||||
description: "Please draw mask on picture",
|
||||
@@ -407,7 +425,11 @@ export const useStore = createWithEqualityFn<AppState & AppAction>()(
|
||||
}
|
||||
maskLineGroup = lastLineGroup
|
||||
} else {
|
||||
if (curLineGroup.length === 0 && maskImage === null) {
|
||||
if (
|
||||
curLineGroup.length === 0 &&
|
||||
maskImage === null &&
|
||||
!settings.showExtender
|
||||
) {
|
||||
toast({
|
||||
variant: "destructive",
|
||||
description: "Please draw mask on picture",
|
||||
@@ -455,6 +477,7 @@ export const useStore = createWithEqualityFn<AppState & AppAction>()(
|
||||
targetFile,
|
||||
settings,
|
||||
cropperState,
|
||||
extenderState,
|
||||
dataURItoBlob(maskCanvas.toDataURL()),
|
||||
paintByExampleFile
|
||||
)
|
||||
@@ -465,7 +488,7 @@ export const useStore = createWithEqualityFn<AppState & AppAction>()(
|
||||
|
||||
const { blob, seed } = res
|
||||
if (seed) {
|
||||
set((state) => (state.settings.seed = parseInt(seed, 10)))
|
||||
get().setSeed(parseInt(seed, 10))
|
||||
}
|
||||
const newRender = new Image()
|
||||
await loadImage(newRender, blob)
|
||||
@@ -794,7 +817,7 @@ export const useStore = createWithEqualityFn<AppState & AppAction>()(
|
||||
state.isPluginRunning = newValue
|
||||
}),
|
||||
|
||||
setFile: (file: File) =>
|
||||
setFile: (file: File) => {
|
||||
set((state) => {
|
||||
state.file = file
|
||||
state.interactiveSegState = castDraft(
|
||||
@@ -802,7 +825,8 @@ export const useStore = createWithEqualityFn<AppState & AppAction>()(
|
||||
)
|
||||
state.editorState = castDraft(defaultValues.editorState)
|
||||
state.cropperState = defaultValues.cropperState
|
||||
}),
|
||||
})
|
||||
},
|
||||
|
||||
setCustomFile: (file: File) =>
|
||||
set((state) => {
|
||||
@@ -822,6 +846,7 @@ export const useStore = createWithEqualityFn<AppState & AppAction>()(
|
||||
state.editorState.brushSizeScale =
|
||||
Math.max(Math.min(width, height), 512) / 512
|
||||
})
|
||||
get().resetExtender(width, height)
|
||||
},
|
||||
|
||||
setCropperX: (newValue: number) =>
|
||||
@@ -864,6 +889,68 @@ export const useStore = createWithEqualityFn<AppState & AppAction>()(
|
||||
state.extenderState.height = newValue
|
||||
}),
|
||||
|
||||
updateExtenderDirection: (newValue: string) => {
|
||||
console.log(
|
||||
`updateExtenderDirection: ${JSON.stringify(get().extenderState)}`
|
||||
)
|
||||
set((state) => {
|
||||
state.settings.extenderDirection = newValue
|
||||
state.extenderState.x = 0
|
||||
state.extenderState.y = 0
|
||||
state.extenderState.width = state.imageWidth
|
||||
state.extenderState.height = state.imageHeight
|
||||
})
|
||||
},
|
||||
|
||||
updateExtenderByBuiltIn: (direction: string, scale: number) => {
|
||||
const newExtenderState = { ...defaultValues.extenderState }
|
||||
let { x, y, width, height } = newExtenderState
|
||||
const { imageWidth, imageHeight } = get()
|
||||
width = imageWidth
|
||||
height = imageHeight
|
||||
|
||||
switch (direction) {
|
||||
case EXTENDER_BUILTIN_X_LEFT:
|
||||
x = -Math.ceil(imageWidth * (scale - 1))
|
||||
width = Math.ceil(imageWidth * scale)
|
||||
break
|
||||
case EXTENDER_BUILTIN_X_RIGHT:
|
||||
width = Math.ceil(imageWidth * scale)
|
||||
break
|
||||
case EXTENDER_BUILTIN_Y_TOP:
|
||||
y = -Math.ceil(imageHeight * (scale - 1))
|
||||
height = Math.ceil(imageHeight * scale)
|
||||
break
|
||||
case EXTENDER_BUILTIN_Y_BOTTOM:
|
||||
height = Math.ceil(imageHeight * scale)
|
||||
break
|
||||
case EXTENDER_BUILTIN_ALL:
|
||||
x = -Math.ceil((imageWidth * (scale - 1)) / 2)
|
||||
y = -Math.ceil((imageHeight * (scale - 1)) / 2)
|
||||
width = Math.ceil(imageWidth * scale)
|
||||
height = Math.ceil(imageHeight * scale)
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
set((state) => {
|
||||
state.extenderState.x = x
|
||||
state.extenderState.y = y
|
||||
state.extenderState.width = width
|
||||
state.extenderState.height = height
|
||||
})
|
||||
},
|
||||
|
||||
resetExtender: (width: number, height: number) => {
|
||||
set((state) => {
|
||||
state.extenderState.x = 0
|
||||
state.extenderState.y = 0
|
||||
state.extenderState.width = width
|
||||
state.extenderState.height = height
|
||||
})
|
||||
},
|
||||
|
||||
setSeed: (newValue: number) =>
|
||||
set((state) => {
|
||||
state.settings.seed = newValue
|
||||
@@ -871,7 +958,7 @@ export const useStore = createWithEqualityFn<AppState & AppAction>()(
|
||||
})),
|
||||
{
|
||||
name: "ZUSTAND_STATE", // name of the item in the storage (must be unique)
|
||||
version: 1,
|
||||
version: 0,
|
||||
partialize: (state) =>
|
||||
Object.fromEntries(
|
||||
Object.entries(state).filter(([key]) =>
|
||||
|
||||
@@ -67,7 +67,7 @@ export enum SDSampler {
|
||||
kEulerA = "k_euler_a",
|
||||
dpmPlusPlus = "dpm++",
|
||||
uni_pc = "uni_pc",
|
||||
lcm = "lcm",
|
||||
// lcm = "lcm",
|
||||
}
|
||||
|
||||
export interface FreeuConfig {
|
||||
|
||||
@@ -71,6 +71,26 @@ export function canvasToImage(
|
||||
})
|
||||
}
|
||||
|
||||
export function fileToImage(file: File): Promise<HTMLImageElement> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const reader = new FileReader()
|
||||
reader.onload = () => {
|
||||
const image = new Image()
|
||||
image.onload = () => {
|
||||
resolve(image)
|
||||
}
|
||||
image.onerror = () => {
|
||||
reject("无法加载图像。")
|
||||
}
|
||||
image.src = reader.result as string
|
||||
}
|
||||
reader.onerror = () => {
|
||||
reject("无法读取文件。")
|
||||
}
|
||||
reader.readAsDataURL(file)
|
||||
})
|
||||
}
|
||||
|
||||
export function srcToFile(src: string, fileName: string, mimeType: string) {
|
||||
return fetch(src)
|
||||
.then(function (res) {
|
||||
|
||||
Reference in New Issue
Block a user