mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
fix(ui): fix canvas img2img if no init image selected
This commit is contained in:
parent
f488b1a7f2
commit
8ef49c2640
@ -1,26 +1,20 @@
|
|||||||
import { createSelector } from '@reduxjs/toolkit';
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
|
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||||
import { validateSeedWeights } from 'common/util/seedWeightPairs';
|
import { validateSeedWeights } from 'common/util/seedWeightPairs';
|
||||||
import { initialCanvasImageSelector } from 'features/canvas/store/canvasSelectors';
|
|
||||||
import { generationSelector } from 'features/parameters/store/generationSelectors';
|
import { generationSelector } from 'features/parameters/store/generationSelectors';
|
||||||
import { systemSelector } from 'features/system/store/systemSelectors';
|
import { systemSelector } from 'features/system/store/systemSelectors';
|
||||||
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
|
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
|
||||||
import { isEqual } from 'lodash-es';
|
import { isEqual } from 'lodash-es';
|
||||||
|
|
||||||
export const readinessSelector = createSelector(
|
export const readinessSelector = createSelector(
|
||||||
[
|
[generationSelector, systemSelector, activeTabNameSelector],
|
||||||
generationSelector,
|
(generation, system, activeTabName) => {
|
||||||
systemSelector,
|
|
||||||
initialCanvasImageSelector,
|
|
||||||
activeTabNameSelector,
|
|
||||||
],
|
|
||||||
(generation, system) => {
|
|
||||||
const {
|
const {
|
||||||
prompt,
|
prompt,
|
||||||
shouldGenerateVariations,
|
shouldGenerateVariations,
|
||||||
seedWeights,
|
seedWeights,
|
||||||
initialImage,
|
initialImage,
|
||||||
seed,
|
seed,
|
||||||
isImageToImageEnabled,
|
|
||||||
} = generation;
|
} = generation;
|
||||||
|
|
||||||
const { isProcessing, isConnected } = system;
|
const { isProcessing, isConnected } = system;
|
||||||
@ -34,7 +28,7 @@ export const readinessSelector = createSelector(
|
|||||||
reasonsWhyNotReady.push('Missing prompt');
|
reasonsWhyNotReady.push('Missing prompt');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isImageToImageEnabled && !initialImage) {
|
if (activeTabName === 'img2img' && !initialImage) {
|
||||||
isReady = false;
|
isReady = false;
|
||||||
reasonsWhyNotReady.push('No initial image selected');
|
reasonsWhyNotReady.push('No initial image selected');
|
||||||
}
|
}
|
||||||
@ -64,10 +58,5 @@ export const readinessSelector = createSelector(
|
|||||||
// All good
|
// All good
|
||||||
return { isReady, reasonsWhyNotReady };
|
return { isReady, reasonsWhyNotReady };
|
||||||
},
|
},
|
||||||
{
|
defaultSelectorOptions
|
||||||
memoizeOptions: {
|
|
||||||
equalityCheck: isEqual,
|
|
||||||
resultEqualityCheck: isEqual,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
|
@ -79,8 +79,6 @@ export const buildCanvasGraphAndBlobs = async (
|
|||||||
moduleLog.debug(
|
moduleLog.debug(
|
||||||
{
|
{
|
||||||
data: {
|
data: {
|
||||||
// baseDataURL,
|
|
||||||
// maskDataURL,
|
|
||||||
baseIsPartiallyTransparent,
|
baseIsPartiallyTransparent,
|
||||||
baseIsFullyTransparent,
|
baseIsFullyTransparent,
|
||||||
doesMaskHaveBlackPixels,
|
doesMaskHaveBlackPixels,
|
||||||
|
@ -5,8 +5,8 @@ import {
|
|||||||
ImageToImageInvocation,
|
ImageToImageInvocation,
|
||||||
TextToImageInvocation,
|
TextToImageInvocation,
|
||||||
} from 'services/api';
|
} from 'services/api';
|
||||||
import { initialImageSelector } from 'features/parameters/store/generationSelectors';
|
|
||||||
import { O } from 'ts-toolbelt';
|
import { O } from 'ts-toolbelt';
|
||||||
|
import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
|
||||||
|
|
||||||
export const buildImg2ImgNode = (
|
export const buildImg2ImgNode = (
|
||||||
state: RootState,
|
state: RootState,
|
||||||
@ -15,6 +15,8 @@ export const buildImg2ImgNode = (
|
|||||||
const nodeId = uuidv4();
|
const nodeId = uuidv4();
|
||||||
const { generation } = state;
|
const { generation } = state;
|
||||||
|
|
||||||
|
const activeTabName = activeTabNameSelector(state);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
prompt,
|
prompt,
|
||||||
negativePrompt,
|
negativePrompt,
|
||||||
@ -33,11 +35,6 @@ export const buildImg2ImgNode = (
|
|||||||
|
|
||||||
// const initialImage = initialImageSelector(state);
|
// const initialImage = initialImageSelector(state);
|
||||||
|
|
||||||
if (!initialImage) {
|
|
||||||
// TODO: handle this
|
|
||||||
throw 'no initial image';
|
|
||||||
}
|
|
||||||
|
|
||||||
const imageToImageNode: ImageToImageInvocation = {
|
const imageToImageNode: ImageToImageInvocation = {
|
||||||
id: nodeId,
|
id: nodeId,
|
||||||
type: 'img2img',
|
type: 'img2img',
|
||||||
@ -48,14 +45,23 @@ export const buildImg2ImgNode = (
|
|||||||
cfg_scale: cfgScale,
|
cfg_scale: cfgScale,
|
||||||
scheduler: sampler as ImageToImageInvocation['scheduler'],
|
scheduler: sampler as ImageToImageInvocation['scheduler'],
|
||||||
model,
|
model,
|
||||||
image: {
|
|
||||||
image_name: initialImage.name,
|
|
||||||
image_type: initialImage.type,
|
|
||||||
},
|
|
||||||
strength,
|
strength,
|
||||||
fit,
|
fit,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// on Canvas tab, we do not manually specific init image
|
||||||
|
if (activeTabName === 'img2img') {
|
||||||
|
if (!initialImage) {
|
||||||
|
// TODO: handle this more better
|
||||||
|
throw 'no initial image';
|
||||||
|
}
|
||||||
|
|
||||||
|
imageToImageNode.image = {
|
||||||
|
image_name: initialImage.name,
|
||||||
|
image_type: initialImage.type,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
if (!shouldRandomizeSeed) {
|
if (!shouldRandomizeSeed) {
|
||||||
imageToImageNode.seed = seed;
|
imageToImageNode.seed = seed;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { createSelector } from '@reduxjs/toolkit';
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
|
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||||
import IAISlider from 'common/components/IAISlider';
|
import IAISlider from 'common/components/IAISlider';
|
||||||
import { generationSelector } from 'features/parameters/store/generationSelectors';
|
import { generationSelector } from 'features/parameters/store/generationSelectors';
|
||||||
import { setImg2imgStrength } from 'features/parameters/store/generationSlice';
|
import { setImg2imgStrength } from 'features/parameters/store/generationSlice';
|
||||||
@ -13,32 +14,25 @@ const selector = createSelector(
|
|||||||
(generation, hotkeys, config) => {
|
(generation, hotkeys, config) => {
|
||||||
const { initial, min, sliderMax, inputMax, fineStep, coarseStep } =
|
const { initial, min, sliderMax, inputMax, fineStep, coarseStep } =
|
||||||
config.sd.img2imgStrength;
|
config.sd.img2imgStrength;
|
||||||
const { img2imgStrength, isImageToImageEnabled } = generation;
|
const { img2imgStrength } = generation;
|
||||||
|
|
||||||
const step = hotkeys.shift ? fineStep : coarseStep;
|
const step = hotkeys.shift ? fineStep : coarseStep;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
img2imgStrength,
|
img2imgStrength,
|
||||||
isImageToImageEnabled,
|
|
||||||
initial,
|
initial,
|
||||||
min,
|
min,
|
||||||
sliderMax,
|
sliderMax,
|
||||||
inputMax,
|
inputMax,
|
||||||
step,
|
step,
|
||||||
};
|
};
|
||||||
}
|
},
|
||||||
|
defaultSelectorOptions
|
||||||
);
|
);
|
||||||
|
|
||||||
const ImageToImageStrength = () => {
|
const ImageToImageStrength = () => {
|
||||||
const {
|
const { img2imgStrength, initial, min, sliderMax, inputMax, step } =
|
||||||
img2imgStrength,
|
useAppSelector(selector);
|
||||||
isImageToImageEnabled,
|
|
||||||
initial,
|
|
||||||
min,
|
|
||||||
sliderMax,
|
|
||||||
inputMax,
|
|
||||||
step,
|
|
||||||
} = useAppSelector(selector);
|
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
@ -64,7 +58,6 @@ const ImageToImageStrength = () => {
|
|||||||
withInput
|
withInput
|
||||||
withSliderMarks
|
withSliderMarks
|
||||||
withReset
|
withReset
|
||||||
isDisabled={!isImageToImageEnabled}
|
|
||||||
sliderNumberInputProps={{ max: inputMax }}
|
sliderNumberInputProps={{ max: inputMax }}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@ -1,49 +0,0 @@
|
|||||||
import { Flex } from '@chakra-ui/react';
|
|
||||||
import { createSelector } from '@reduxjs/toolkit';
|
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
|
||||||
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
|
||||||
import IAISwitch from 'common/components/IAISwitch';
|
|
||||||
import { generationSelector } from 'features/parameters/store/generationSelectors';
|
|
||||||
import { uiSelector } from 'features/ui/store/uiSelectors';
|
|
||||||
import { shouldShowImageParametersChanged } from 'features/ui/store/uiSlice';
|
|
||||||
import { ChangeEvent } from 'react';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
|
|
||||||
const selector = createSelector(
|
|
||||||
[uiSelector, generationSelector],
|
|
||||||
(ui, generation) => {
|
|
||||||
const { isImageToImageEnabled } = generation;
|
|
||||||
const { shouldShowImageParameters } = ui;
|
|
||||||
return {
|
|
||||||
isImageToImageEnabled,
|
|
||||||
shouldShowImageParameters,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
defaultSelectorOptions
|
|
||||||
);
|
|
||||||
|
|
||||||
export default function ImageToImageToggle() {
|
|
||||||
const { shouldShowImageParameters } = useAppSelector(selector);
|
|
||||||
|
|
||||||
const { t } = useTranslation();
|
|
||||||
|
|
||||||
const dispatch = useAppDispatch();
|
|
||||||
|
|
||||||
const handleChange = (e: ChangeEvent<HTMLInputElement>) =>
|
|
||||||
dispatch(shouldShowImageParametersChanged(e.target.checked));
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Flex py={1.5} px={4} borderRadius={4}>
|
|
||||||
<IAISwitch
|
|
||||||
label={t('parameters.initialImage')}
|
|
||||||
isChecked={shouldShowImageParameters}
|
|
||||||
width="full"
|
|
||||||
onChange={handleChange}
|
|
||||||
justifyContent="space-between"
|
|
||||||
formLabelProps={{
|
|
||||||
fontWeight: 400,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Flex>
|
|
||||||
);
|
|
||||||
}
|
|
@ -5,28 +5,27 @@ import SelectImagePlaceholder from 'common/components/SelectImagePlaceholder';
|
|||||||
import { useGetUrl } from 'common/util/getUrl';
|
import { useGetUrl } from 'common/util/getUrl';
|
||||||
import { clearInitialImage } from 'features/parameters/store/generationSlice';
|
import { clearInitialImage } from 'features/parameters/store/generationSlice';
|
||||||
import { addToast } from 'features/system/store/systemSlice';
|
import { addToast } from 'features/system/store/systemSlice';
|
||||||
import { isEqual } from 'lodash-es';
|
|
||||||
import { DragEvent, useCallback, useState } from 'react';
|
import { DragEvent, useCallback, useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { ImageType } from 'services/api';
|
import { ImageType } from 'services/api';
|
||||||
import ImageToImageOverlay from 'common/components/ImageToImageOverlay';
|
import ImageToImageOverlay from 'common/components/ImageToImageOverlay';
|
||||||
import { generationSelector } from 'features/parameters/store/generationSelectors';
|
import { generationSelector } from 'features/parameters/store/generationSelectors';
|
||||||
import { initialImageSelected } from 'features/parameters/store/actions';
|
import { initialImageSelected } from 'features/parameters/store/actions';
|
||||||
|
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
|
||||||
|
|
||||||
const selector = createSelector(
|
const selector = createSelector(
|
||||||
[generationSelector],
|
[generationSelector],
|
||||||
(generation) => {
|
(generation) => {
|
||||||
const { initialImage, isImageToImageEnabled } = generation;
|
const { initialImage } = generation;
|
||||||
return {
|
return {
|
||||||
initialImage,
|
initialImage,
|
||||||
isImageToImageEnabled,
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
{ memoizeOptions: { resultEqualityCheck: isEqual } }
|
defaultSelectorOptions
|
||||||
);
|
);
|
||||||
|
|
||||||
const InitialImagePreview = () => {
|
const InitialImagePreview = () => {
|
||||||
const { initialImage, isImageToImageEnabled } = useAppSelector(selector);
|
const { initialImage } = useAppSelector(selector);
|
||||||
const { getUrl } = useGetUrl();
|
const { getUrl } = useGetUrl();
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@ -73,8 +72,6 @@ const InitialImagePreview = () => {
|
|||||||
sx={{
|
sx={{
|
||||||
height: 'full',
|
height: 'full',
|
||||||
width: 'full',
|
width: 'full',
|
||||||
opacity: isImageToImageEnabled ? 1 : 0.5,
|
|
||||||
filter: isImageToImageEnabled ? 'none' : 'auto',
|
|
||||||
blur: '5px',
|
blur: '5px',
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
@ -107,26 +104,6 @@ const InitialImagePreview = () => {
|
|||||||
)}
|
)}
|
||||||
{!initialImage?.url && <SelectImagePlaceholder />}
|
{!initialImage?.url && <SelectImagePlaceholder />}
|
||||||
</Flex>
|
</Flex>
|
||||||
{/* {!isImageToImageEnabled && (
|
|
||||||
<Flex
|
|
||||||
sx={{
|
|
||||||
w: 'full',
|
|
||||||
h: 'full',
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center',
|
|
||||||
position: 'absolute',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Text
|
|
||||||
fontWeight={500}
|
|
||||||
fontSize="md"
|
|
||||||
userSelect="none"
|
|
||||||
color="base.200"
|
|
||||||
>
|
|
||||||
Image to Image is Disabled
|
|
||||||
</Text>
|
|
||||||
</Flex>
|
|
||||||
)} */}
|
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -35,7 +35,6 @@ export interface GenerationState {
|
|||||||
shouldUseSymmetry: boolean;
|
shouldUseSymmetry: boolean;
|
||||||
horizontalSymmetrySteps: number;
|
horizontalSymmetrySteps: number;
|
||||||
verticalSymmetrySteps: number;
|
verticalSymmetrySteps: number;
|
||||||
isImageToImageEnabled: boolean;
|
|
||||||
model: string;
|
model: string;
|
||||||
shouldUseSeamless: boolean;
|
shouldUseSeamless: boolean;
|
||||||
seamlessXAxis: boolean;
|
seamlessXAxis: boolean;
|
||||||
@ -71,7 +70,6 @@ export const initialGenerationState: GenerationState = {
|
|||||||
shouldUseSymmetry: false,
|
shouldUseSymmetry: false,
|
||||||
horizontalSymmetrySteps: 0,
|
horizontalSymmetrySteps: 0,
|
||||||
verticalSymmetrySteps: 0,
|
verticalSymmetrySteps: 0,
|
||||||
isImageToImageEnabled: false,
|
|
||||||
model: '',
|
model: '',
|
||||||
shouldUseSeamless: false,
|
shouldUseSeamless: false,
|
||||||
seamlessXAxis: true,
|
seamlessXAxis: true,
|
||||||
@ -233,10 +231,6 @@ export const generationSlice = createSlice({
|
|||||||
},
|
},
|
||||||
initialImageChanged: (state, action: PayloadAction<InvokeAI.Image>) => {
|
initialImageChanged: (state, action: PayloadAction<InvokeAI.Image>) => {
|
||||||
state.initialImage = action.payload;
|
state.initialImage = action.payload;
|
||||||
state.isImageToImageEnabled = true;
|
|
||||||
},
|
|
||||||
isImageToImageEnabledChanged: (state, action: PayloadAction<boolean>) => {
|
|
||||||
state.isImageToImageEnabled = action.payload;
|
|
||||||
},
|
},
|
||||||
modelSelected: (state, action: PayloadAction<string>) => {
|
modelSelected: (state, action: PayloadAction<string>) => {
|
||||||
state.model = action.payload;
|
state.model = action.payload;
|
||||||
@ -249,9 +243,6 @@ export const {
|
|||||||
clearInitialImage,
|
clearInitialImage,
|
||||||
resetParametersState,
|
resetParametersState,
|
||||||
resetSeed,
|
resetSeed,
|
||||||
setAllImageToImageParameters,
|
|
||||||
setAllParameters,
|
|
||||||
setAllTextToImageParameters,
|
|
||||||
setCfgScale,
|
setCfgScale,
|
||||||
setHeight,
|
setHeight,
|
||||||
setImg2imgStrength,
|
setImg2imgStrength,
|
||||||
@ -282,7 +273,6 @@ export const {
|
|||||||
setHorizontalSymmetrySteps,
|
setHorizontalSymmetrySteps,
|
||||||
setVerticalSymmetrySteps,
|
setVerticalSymmetrySteps,
|
||||||
initialImageChanged,
|
initialImageChanged,
|
||||||
isImageToImageEnabledChanged,
|
|
||||||
modelSelected,
|
modelSelected,
|
||||||
setShouldUseNoiseSettings,
|
setShouldUseNoiseSettings,
|
||||||
setSeamless,
|
setSeamless,
|
||||||
|
Loading…
Reference in New Issue
Block a user