diff --git a/invokeai/frontend/web/public/locales/en.json b/invokeai/frontend/web/public/locales/en.json index 63380a19fa..fbae5b4a30 100644 --- a/invokeai/frontend/web/public/locales/en.json +++ b/invokeai/frontend/web/public/locales/en.json @@ -503,6 +503,9 @@ "hiresStrength": "High Res Strength", "imageFit": "Fit Initial Image To Output Size", "codeformerFidelity": "Fidelity", + "maskAdjustmentsHeader": "Mask Adjustments", + "maskBlur": "Mask Blur", + "maskBlurMethod": "Mask Blur Method", "seamSize": "Seam Size", "seamBlur": "Seam Blur", "seamStrength": "Seam Strength", diff --git a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasInpaintGraph.ts b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasInpaintGraph.ts index 892cdc2d7c..817e8d5176 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasInpaintGraph.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasInpaintGraph.ts @@ -13,12 +13,15 @@ import { addVAEToGraph } from './addVAEToGraph'; import { addWatermarkerToGraph } from './addWatermarkerToGraph'; import { CLIP_SKIP, + COLOR_CORRECT, INPAINT, + INPAINT_FINAL_IMAGE, INPAINT_GRAPH, INPAINT_IMAGE, ITERATE, LATENTS_TO_IMAGE, MAIN_MODEL_LOADER, + MASK_BLUR, NEGATIVE_CONDITIONING, NOISE, POSITIVE_CONDITIONING, @@ -50,10 +53,8 @@ export const buildCanvasInpaintGraph = ( vaePrecision, shouldUseNoiseSettings, shouldUseCpuNoise, - seamSize, - seamBlur, - seamSteps, - seamStrength, + maskBlur, + maskBlurMethod, tileSize, infillMethod, clipSkip, @@ -90,7 +91,6 @@ export const buildCanvasInpaintGraph = ( scheduler: scheduler, denoising_start: 1 - strength, denoising_end: 1, - mask: canvasMaskImage, }, [INPAINT_IMAGE]: { type: 'i2l', @@ -137,7 +137,27 @@ export const buildCanvasInpaintGraph = ( is_intermediate: true, skipped_layers: clipSkip, }, - + [COLOR_CORRECT]: { + type: 'color_correct', + id: COLOR_CORRECT, + is_intermediate: true, + reference: canvasInitImage, + mask: canvasMaskImage, + }, + [MASK_BLUR]: { + type: 'img_blur', + id: MASK_BLUR, + is_intermediate: true, + image: canvasMaskImage, + radius: maskBlur, + blur_type: maskBlurMethod, + }, + [INPAINT_FINAL_IMAGE]: { + type: 'img_paste', + id: INPAINT_FINAL_IMAGE, + is_intermediate: true, + base_image: canvasInitImage, + }, [RANGE_OF_SIZE]: { type: 'range_of_size', id: RANGE_OF_SIZE, @@ -234,6 +254,16 @@ export const buildCanvasInpaintGraph = ( field: 'latents', }, }, + { + source: { + node_id: MASK_BLUR, + field: 'image', + }, + destination: { + node_id: INPAINT, + field: 'mask', + }, + }, { source: { node_id: RANGE_OF_SIZE, @@ -264,6 +294,36 @@ export const buildCanvasInpaintGraph = ( field: 'latents', }, }, + { + source: { + node_id: LATENTS_TO_IMAGE, + field: 'image', + }, + destination: { + node_id: COLOR_CORRECT, + field: 'image', + }, + }, + { + source: { + node_id: MASK_BLUR, + field: 'image', + }, + destination: { + node_id: INPAINT_FINAL_IMAGE, + field: 'mask', + }, + }, + { + source: { + node_id: COLOR_CORRECT, + field: 'image', + }, + destination: { + node_id: INPAINT_FINAL_IMAGE, + field: 'image', + }, + }, ], }; diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/MaskAdjustment/ParamMaskAdjustmentCollapse.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/MaskAdjustment/ParamMaskAdjustmentCollapse.tsx new file mode 100644 index 0000000000..9ca6503d3d --- /dev/null +++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/MaskAdjustment/ParamMaskAdjustmentCollapse.tsx @@ -0,0 +1,21 @@ +import { Flex } from '@chakra-ui/react'; +import IAICollapse from 'common/components/IAICollapse'; +import { memo } from 'react'; +import { useTranslation } from 'react-i18next'; +import ParamMaskBlur from './ParamMaskBlur'; +import ParamMaskBlurMethod from './ParamMaskBlurMethod'; + +const ParamMaskAdjustmentCollapse = () => { + const { t } = useTranslation(); + + return ( + + + + + + + ); +}; + +export default memo(ParamMaskAdjustmentCollapse); diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/SeamCorrection/ParamSeamBlur.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/MaskAdjustment/ParamMaskBlur.tsx similarity index 62% rename from invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/SeamCorrection/ParamSeamBlur.tsx rename to invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/MaskAdjustment/ParamMaskBlur.tsx index 5c20ba7a13..82b82228e2 100644 --- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/SeamCorrection/ParamSeamBlur.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/MaskAdjustment/ParamMaskBlur.tsx @@ -1,31 +1,31 @@ import type { RootState } from 'app/store/store'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAISlider from 'common/components/IAISlider'; -import { setSeamBlur } from 'features/parameters/store/generationSlice'; +import { setMaskBlur } from 'features/parameters/store/generationSlice'; import { useTranslation } from 'react-i18next'; -export default function ParamSeamBlur() { +export default function ParamMaskBlur() { const dispatch = useAppDispatch(); - const seamBlur = useAppSelector( - (state: RootState) => state.generation.seamBlur + const maskBlur = useAppSelector( + (state: RootState) => state.generation.maskBlur ); const { t } = useTranslation(); return ( { - dispatch(setSeamBlur(v)); + dispatch(setMaskBlur(v)); }} withInput withSliderMarks withReset handleReset={() => { - dispatch(setSeamBlur(16)); + dispatch(setMaskBlur(16)); }} /> ); diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/MaskAdjustment/ParamMaskBlurMethod.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/MaskAdjustment/ParamMaskBlurMethod.tsx new file mode 100644 index 0000000000..b45dc8b884 --- /dev/null +++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/MaskAdjustment/ParamMaskBlurMethod.tsx @@ -0,0 +1,36 @@ +import { SelectItem } from '@mantine/core'; +import { RootState } from 'app/store/store'; + +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; +import IAIMantineSelect from 'common/components/IAIMantineSelect'; +import { setMaskBlurMethod } from 'features/parameters/store/generationSlice'; +import { useTranslation } from 'react-i18next'; + +export type MaskBlurMethods = 'box' | 'gaussian'; + +const maskBlurMethods: SelectItem[] = [ + { label: 'Box Blur', value: 'box' }, + { label: 'Gaussian Blur', value: 'gaussian' }, +]; + +export default function ParamMaskBlurMethod() { + const maskBlurMethod = useAppSelector( + (state: RootState) => state.generation.maskBlurMethod + ); + const dispatch = useAppDispatch(); + const { t } = useTranslation(); + + const handleMaskBlurMethodChange = (v: string | null) => { + if (!v) return; + dispatch(setMaskBlurMethod(v as MaskBlurMethods)); + }; + + return ( + + ); +} diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/SeamCorrection/ParamSeamCorrectionCollapse.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/SeamCorrection/ParamSeamCorrectionCollapse.tsx deleted file mode 100644 index 88d839fa15..0000000000 --- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/SeamCorrection/ParamSeamCorrectionCollapse.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import IAICollapse from 'common/components/IAICollapse'; -import { memo } from 'react'; -import { useTranslation } from 'react-i18next'; -import ParamSeamBlur from './ParamSeamBlur'; -import ParamSeamSize from './ParamSeamSize'; -import ParamSeamSteps from './ParamSeamSteps'; -import ParamSeamStrength from './ParamSeamStrength'; - -const ParamSeamCorrectionCollapse = () => { - const { t } = useTranslation(); - - return ( - - - - - - - ); -}; - -export default memo(ParamSeamCorrectionCollapse); diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/SeamCorrection/ParamSeamSize.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/SeamCorrection/ParamSeamSize.tsx deleted file mode 100644 index 8e56cded7b..0000000000 --- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/SeamCorrection/ParamSeamSize.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import type { RootState } from 'app/store/store'; -import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; -import IAISlider from 'common/components/IAISlider'; -import { setSeamSize } from 'features/parameters/store/generationSlice'; -import { useTranslation } from 'react-i18next'; - -export default function ParamSeamSize() { - const dispatch = useAppDispatch(); - const { t } = useTranslation(); - - const seamSize = useAppSelector( - (state: RootState) => state.generation.seamSize - ); - - return ( - { - dispatch(setSeamSize(v)); - }} - withInput - withSliderMarks - withReset - handleReset={() => dispatch(setSeamSize(96))} - /> - ); -} diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/SeamCorrection/ParamSeamSteps.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/SeamCorrection/ParamSeamSteps.tsx deleted file mode 100644 index 8ca5226621..0000000000 --- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/SeamCorrection/ParamSeamSteps.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import type { RootState } from 'app/store/store'; -import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; -import IAISlider from 'common/components/IAISlider'; -import { setSeamSteps } from 'features/parameters/store/generationSlice'; -import { useTranslation } from 'react-i18next'; - -export default function ParamSeamSteps() { - const { t } = useTranslation(); - const seamSteps = useAppSelector( - (state: RootState) => state.generation.seamSteps - ); - const dispatch = useAppDispatch(); - - return ( - { - dispatch(setSeamSteps(v)); - }} - withInput - withSliderMarks - withReset - handleReset={() => { - dispatch(setSeamSteps(30)); - }} - /> - ); -} diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/SeamCorrection/ParamSeamStrength.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/SeamCorrection/ParamSeamStrength.tsx deleted file mode 100644 index de74156cd3..0000000000 --- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/SeamCorrection/ParamSeamStrength.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import { RootState } from 'app/store/store'; -import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; -import IAISlider from 'common/components/IAISlider'; -import { setSeamStrength } from 'features/parameters/store/generationSlice'; -import { useTranslation } from 'react-i18next'; - -export default function ParamSeamStrength() { - const dispatch = useAppDispatch(); - const { t } = useTranslation(); - const seamStrength = useAppSelector( - (state: RootState) => state.generation.seamStrength - ); - - return ( - { - dispatch(setSeamStrength(v)); - }} - withInput - withSliderMarks - withReset - handleReset={() => { - dispatch(setSeamStrength(0.7)); - }} - /> - ); -} diff --git a/invokeai/frontend/web/src/features/parameters/store/generationSlice.ts b/invokeai/frontend/web/src/features/parameters/store/generationSlice.ts index 12f2c3eabf..33a76da4e6 100644 --- a/invokeai/frontend/web/src/features/parameters/store/generationSlice.ts +++ b/invokeai/frontend/web/src/features/parameters/store/generationSlice.ts @@ -4,6 +4,7 @@ import { roundToMultiple } from 'common/util/roundDownToMultiple'; import { configChanged } from 'features/system/store/configSlice'; import { clamp } from 'lodash-es'; import { ImageDTO } from 'services/api/types'; +import { MaskBlurMethods } from '../components/Parameters/Canvas/MaskAdjustment/ParamMaskBlurMethod'; import { clipSkipMap } from '../types/constants'; import { CfgScaleParam, @@ -33,10 +34,8 @@ export interface GenerationState { positivePrompt: PositivePromptParam; negativePrompt: NegativePromptParam; scheduler: SchedulerParam; - seamBlur: number; - seamSize: number; - seamSteps: number; - seamStrength: number; + maskBlur: number; + maskBlurMethod: MaskBlurMethods; seed: SeedParam; seedWeights: string; shouldFitToWidthHeight: boolean; @@ -72,10 +71,8 @@ export const initialGenerationState: GenerationState = { positivePrompt: '', negativePrompt: '', scheduler: 'euler', - seamBlur: 16, - seamSize: 96, - seamSteps: 30, - seamStrength: 0.7, + maskBlur: 16, + maskBlurMethod: 'box', seed: 0, seedWeights: '', shouldFitToWidthHeight: true, @@ -196,17 +193,11 @@ export const generationSlice = createSlice({ clearInitialImage: (state) => { state.initialImage = undefined; }, - setSeamSize: (state, action: PayloadAction) => { - state.seamSize = action.payload; + setMaskBlur: (state, action: PayloadAction) => { + state.maskBlur = action.payload; }, - setSeamBlur: (state, action: PayloadAction) => { - state.seamBlur = action.payload; - }, - setSeamStrength: (state, action: PayloadAction) => { - state.seamStrength = action.payload; - }, - setSeamSteps: (state, action: PayloadAction) => { - state.seamSteps = action.payload; + setMaskBlurMethod: (state, action: PayloadAction) => { + state.maskBlurMethod = action.payload; }, setTileSize: (state, action: PayloadAction) => { state.tileSize = action.payload; @@ -312,10 +303,8 @@ export const { setPositivePrompt, setNegativePrompt, setScheduler, - setSeamBlur, - setSeamSize, - setSeamSteps, - setSeamStrength, + setMaskBlur, + setMaskBlurMethod, setSeed, setSeedWeights, setShouldFitToWidthHeight, diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasParameters.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasParameters.tsx index de7ce3b084..fcfffee48b 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasParameters.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasParameters.tsx @@ -2,10 +2,10 @@ import ParamDynamicPromptsCollapse from 'features/dynamicPrompts/components/Para import ParamLoraCollapse from 'features/lora/components/ParamLoraCollapse'; import ParamAdvancedCollapse from 'features/parameters/components/Parameters/Advanced/ParamAdvancedCollapse'; import ParamInfillAndScalingCollapse from 'features/parameters/components/Parameters/Canvas/InfillAndScaling/ParamInfillAndScalingCollapse'; -import ParamSeamCorrectionCollapse from 'features/parameters/components/Parameters/Canvas/SeamCorrection/ParamSeamCorrectionCollapse'; import ParamControlNetCollapse from 'features/parameters/components/Parameters/ControlNet/ParamControlNetCollapse'; import ParamSymmetryCollapse from 'features/parameters/components/Parameters/Symmetry/ParamSymmetryCollapse'; // import ParamVariationCollapse from 'features/parameters/components/Parameters/Variations/ParamVariationCollapse'; +import ParamMaskAdjustmentCollapse from 'features/parameters/components/Parameters/Canvas/MaskAdjustment/ParamMaskAdjustmentCollapse'; import ParamPromptArea from 'features/parameters/components/Parameters/Prompt/ParamPromptArea'; import ProcessButtons from 'features/parameters/components/ProcessButtons/ProcessButtons'; import UnifiedCanvasCoreParameters from './UnifiedCanvasCoreParameters'; @@ -21,7 +21,7 @@ const UnifiedCanvasParameters = () => { {/* */} - +