ui: Color Infill UI

This commit is contained in:
blessedcoolant 2024-03-30 15:02:51 +05:30 committed by psychedelicious
parent adb7966bb3
commit e55ab5b3a1
8 changed files with 81 additions and 19 deletions

View File

@ -891,6 +891,7 @@
"infillMosaicTileHeight": "Tile Height", "infillMosaicTileHeight": "Tile Height",
"infillMosaicMinColor": "Min Color", "infillMosaicMinColor": "Min Color",
"infillMosaicMaxColor": "Max Color", "infillMosaicMaxColor": "Max Color",
"infillColorValue": "Fill Color",
"info": "Info", "info": "Info",
"invoke": { "invoke": {
"addingImagesTo": "Adding images to", "addingImagesTo": "Adding images to",

View File

@ -69,6 +69,7 @@ export const buildCanvasOutpaintGraph = async (
infillMosaicTileHeight, infillMosaicTileHeight,
infillMosaicMinColor, infillMosaicMinColor,
infillMosaicMaxColor, infillMosaicMaxColor,
infillColorValue,
clipSkip, clipSkip,
seamlessXAxis, seamlessXAxis,
seamlessYAxis, seamlessYAxis,
@ -376,6 +377,7 @@ export const buildCanvasOutpaintGraph = async (
graph.nodes[INPAINT_INFILL] = { graph.nodes[INPAINT_INFILL] = {
type: 'infill_rgba', type: 'infill_rgba',
id: INPAINT_INFILL, id: INPAINT_INFILL,
color: infillColorValue,
is_intermediate, is_intermediate,
}; };
} }

View File

@ -70,6 +70,7 @@ export const buildCanvasSDXLOutpaintGraph = async (
infillMosaicTileHeight, infillMosaicTileHeight,
infillMosaicMinColor, infillMosaicMinColor,
infillMosaicMaxColor, infillMosaicMaxColor,
infillColorValue,
seamlessXAxis, seamlessXAxis,
seamlessYAxis, seamlessYAxis,
canvasCoherenceMode, canvasCoherenceMode,
@ -386,6 +387,7 @@ export const buildCanvasSDXLOutpaintGraph = async (
type: 'infill_rgba', type: 'infill_rgba',
id: INPAINT_INFILL, id: INPAINT_INFILL,
is_intermediate, is_intermediate,
color: infillColorValue,
}; };
} }

View File

@ -0,0 +1,46 @@
import { Box, Flex, FormControl, FormLabel } from '@invoke-ai/ui-library';
import { createSelector } from '@reduxjs/toolkit';
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
import IAIColorPicker from 'common/components/IAIColorPicker';
import { selectGenerationSlice, setInfillColorValue } from 'features/parameters/store/generationSlice';
import { memo, useCallback, useMemo } from 'react';
import type { RgbaColor } from 'react-colorful';
import { useTranslation } from 'react-i18next';
const ParamInfillColorOptions = () => {
const dispatch = useAppDispatch();
const selector = useMemo(
() =>
createSelector(selectGenerationSlice, (generation) => ({
infillColor: generation.infillColorValue,
})),
[]
);
const { infillColor } = useAppSelector(selector);
const infillMethod = useAppSelector((s) => s.generation.infillMethod);
const { t } = useTranslation();
const handleInfillColor = useCallback(
(v: RgbaColor) => {
dispatch(setInfillColorValue(v));
},
[dispatch]
);
return (
<Flex flexDir="column" gap={4}>
<FormControl isDisabled={infillMethod !== 'color'}>
<FormLabel>{t('parameters.infillColorValue')}</FormLabel>
<Box w="full" pt={2} pb={2}>
<IAIColorPicker color={infillColor} onChange={handleInfillColor} />
</Box>
</FormControl>
</Flex>
);
};
export default memo(ParamInfillColorOptions);

View File

@ -13,7 +13,7 @@ import { memo, useCallback, useMemo } from 'react';
import type { RgbaColor } from 'react-colorful'; import type { RgbaColor } from 'react-colorful';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
const ParamMosaicInfillTileSize = () => { const ParamInfillMosaicTileSize = () => {
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
const selector = useMemo( const selector = useMemo(
@ -124,4 +124,4 @@ const ParamMosaicInfillTileSize = () => {
); );
}; };
export default memo(ParamMosaicInfillTileSize); export default memo(ParamInfillMosaicTileSize);

View File

@ -1,9 +1,10 @@
import { useAppSelector } from 'app/store/storeHooks'; import { useAppSelector } from 'app/store/storeHooks';
import { memo } from 'react'; import { memo } from 'react';
import ParamInfillColorOptions from './ParamInfillColorOptions';
import ParamInfillMosaicOptions from './ParamInfillMosaicOptions';
import ParamInfillPatchmatchDownscaleSize from './ParamInfillPatchmatchDownscaleSize'; import ParamInfillPatchmatchDownscaleSize from './ParamInfillPatchmatchDownscaleSize';
import ParamInfillTilesize from './ParamInfillTilesize'; import ParamInfillTilesize from './ParamInfillTilesize';
import ParamMosaicInfillOptions from './ParamMosaicInfillOptions';
const ParamInfillOptions = () => { const ParamInfillOptions = () => {
const infillMethod = useAppSelector((s) => s.generation.infillMethod); const infillMethod = useAppSelector((s) => s.generation.infillMethod);
@ -16,7 +17,11 @@ const ParamInfillOptions = () => {
} }
if (infillMethod === 'mosaic') { if (infillMethod === 'mosaic') {
return <ParamMosaicInfillOptions />; return <ParamInfillMosaicOptions />;
}
if (infillMethod === 'color') {
return <ParamInfillColorOptions />;
} }
return null; return null;

View File

@ -44,8 +44,6 @@ const initialGenerationState: GenerationState = {
shouldFitToWidthHeight: true, shouldFitToWidthHeight: true,
shouldRandomizeSeed: true, shouldRandomizeSeed: true,
steps: 50, steps: 50,
infillTileSize: 32,
infillPatchmatchDownscaleSize: 1,
width: 512, width: 512,
model: null, model: null,
vae: null, vae: null,
@ -56,10 +54,13 @@ const initialGenerationState: GenerationState = {
shouldUseCpuNoise: true, shouldUseCpuNoise: true,
shouldShowAdvancedOptions: false, shouldShowAdvancedOptions: false,
aspectRatio: { ...initialAspectRatioState }, aspectRatio: { ...initialAspectRatioState },
infillTileSize: 32,
infillPatchmatchDownscaleSize: 1,
infillMosaicTileWidth: 64, infillMosaicTileWidth: 64,
infillMosaicTileHeight: 64, infillMosaicTileHeight: 64,
infillMosaicMinColor: { r: 0, g: 0, b: 0, a: 1 }, infillMosaicMinColor: { r: 0, g: 0, b: 0, a: 1 },
infillMosaicMaxColor: { r: 255, g: 255, b: 255, a: 1 }, infillMosaicMaxColor: { r: 255, g: 255, b: 255, a: 1 },
infillColorValue: { r: 0, g: 0, b: 0, a: 1 },
}; };
export const generationSlice = createSlice({ export const generationSlice = createSlice({
@ -121,15 +122,6 @@ export const generationSlice = createSlice({
setCanvasCoherenceMinDenoise: (state, action: PayloadAction<number>) => { setCanvasCoherenceMinDenoise: (state, action: PayloadAction<number>) => {
state.canvasCoherenceMinDenoise = action.payload; state.canvasCoherenceMinDenoise = action.payload;
}, },
setInfillMethod: (state, action: PayloadAction<string>) => {
state.infillMethod = action.payload;
},
setInfillTileSize: (state, action: PayloadAction<number>) => {
state.infillTileSize = action.payload;
},
setInfillPatchmatchDownscaleSize: (state, action: PayloadAction<number>) => {
state.infillPatchmatchDownscaleSize = action.payload;
},
initialImageChanged: (state, action: PayloadAction<ImageDTO>) => { initialImageChanged: (state, action: PayloadAction<ImageDTO>) => {
const { image_name, width, height } = action.payload; const { image_name, width, height } = action.payload;
state.initialImage = { imageName: image_name, width, height }; state.initialImage = { imageName: image_name, width, height };
@ -211,6 +203,15 @@ export const generationSlice = createSlice({
aspectRatioChanged: (state, action: PayloadAction<AspectRatioState>) => { aspectRatioChanged: (state, action: PayloadAction<AspectRatioState>) => {
state.aspectRatio = action.payload; state.aspectRatio = action.payload;
}, },
setInfillMethod: (state, action: PayloadAction<string>) => {
state.infillMethod = action.payload;
},
setInfillTileSize: (state, action: PayloadAction<number>) => {
state.infillTileSize = action.payload;
},
setInfillPatchmatchDownscaleSize: (state, action: PayloadAction<number>) => {
state.infillPatchmatchDownscaleSize = action.payload;
},
setInfillMosaicTileWidth: (state, action: PayloadAction<number>) => { setInfillMosaicTileWidth: (state, action: PayloadAction<number>) => {
state.infillMosaicTileWidth = action.payload; state.infillMosaicTileWidth = action.payload;
}, },
@ -223,6 +224,9 @@ export const generationSlice = createSlice({
setInfillMosaicMaxColor: (state, action: PayloadAction<RgbaColor>) => { setInfillMosaicMaxColor: (state, action: PayloadAction<RgbaColor>) => {
state.infillMosaicMaxColor = action.payload; state.infillMosaicMaxColor = action.payload;
}, },
setInfillColorValue: (state, action: PayloadAction<RgbaColor>) => {
state.infillColorValue = action.payload;
},
}, },
extraReducers: (builder) => { extraReducers: (builder) => {
builder.addCase(configChanged, (state, action) => { builder.addCase(configChanged, (state, action) => {
@ -266,8 +270,6 @@ export const {
setShouldFitToWidthHeight, setShouldFitToWidthHeight,
setShouldRandomizeSeed, setShouldRandomizeSeed,
setSteps, setSteps,
setInfillTileSize,
setInfillPatchmatchDownscaleSize,
initialImageChanged, initialImageChanged,
modelChanged, modelChanged,
vaeSelected, vaeSelected,
@ -281,10 +283,13 @@ export const {
heightChanged, heightChanged,
widthRecalled, widthRecalled,
heightRecalled, heightRecalled,
setInfillTileSize,
setInfillPatchmatchDownscaleSize,
setInfillMosaicTileWidth, setInfillMosaicTileWidth,
setInfillMosaicTileHeight, setInfillMosaicTileHeight,
setInfillMosaicMinColor, setInfillMosaicMinColor,
setInfillMosaicMaxColor, setInfillMosaicMaxColor,
setInfillColorValue,
} = generationSlice.actions; } = generationSlice.actions;
export const { selectOptimalDimension } = generationSlice.selectors; export const { selectOptimalDimension } = generationSlice.selectors;

View File

@ -40,8 +40,6 @@ export interface GenerationState {
shouldFitToWidthHeight: boolean; shouldFitToWidthHeight: boolean;
shouldRandomizeSeed: boolean; shouldRandomizeSeed: boolean;
steps: ParameterSteps; steps: ParameterSteps;
infillTileSize: number;
infillPatchmatchDownscaleSize: number;
width: ParameterWidth; width: ParameterWidth;
model: ParameterModel | null; model: ParameterModel | null;
vae: ParameterVAEModel | null; vae: ParameterVAEModel | null;
@ -52,10 +50,13 @@ export interface GenerationState {
shouldUseCpuNoise: boolean; shouldUseCpuNoise: boolean;
shouldShowAdvancedOptions: boolean; shouldShowAdvancedOptions: boolean;
aspectRatio: AspectRatioState; aspectRatio: AspectRatioState;
infillTileSize: number;
infillPatchmatchDownscaleSize: number;
infillMosaicTileWidth: number; infillMosaicTileWidth: number;
infillMosaicTileHeight: number; infillMosaicTileHeight: number;
infillMosaicMinColor: RgbaColor; infillMosaicMinColor: RgbaColor;
infillMosaicMaxColor: RgbaColor; infillMosaicMaxColor: RgbaColor;
infillColorValue: RgbaColor;
} }
export type PayloadActionWithOptimalDimension<T = void> = PayloadAction<T, string, { optimalDimension: number }>; export type PayloadActionWithOptimalDimension<T = void> = PayloadAction<T, string, { optimalDimension: number }>;