From d01d5b6fa983bf193771548c2d8ee00f1483cec6 Mon Sep 17 00:00:00 2001 From: blessedcoolant <54517381+blessedcoolant@users.noreply.github.com> Date: Sun, 9 Jul 2023 23:18:06 +1200 Subject: [PATCH 1/6] feat: Add Aspect Ratio --- invokeai/frontend/web/public/locales/en.json | 3 +- .../Parameters/Core/ParamAspectRatio.tsx | 49 +++++++++++++++++++ .../Parameters/Core/ParamHeight.tsx | 18 ++++--- .../components/Parameters/Core/ParamSize.tsx | 35 +++++++++++++ .../components/Parameters/Core/ParamWidth.tsx | 18 ++++--- .../parameters/store/generationSlice.ts | 10 +++- .../ImageToImageTabCoreParameters.tsx | 15 +++--- .../TextToImageTabCoreParameters.tsx | 15 +++--- .../UnifiedCanvasCoreParameters.tsx | 6 +-- .../web/src/features/ui/store/uiSlice.ts | 5 ++ .../web/src/features/ui/store/uiTypes.ts | 1 + 11 files changed, 140 insertions(+), 35 deletions(-) create mode 100644 invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamAspectRatio.tsx create mode 100644 invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamSize.tsx diff --git a/invokeai/frontend/web/public/locales/en.json b/invokeai/frontend/web/public/locales/en.json index b403fde2c6..29a3c0907c 100644 --- a/invokeai/frontend/web/public/locales/en.json +++ b/invokeai/frontend/web/public/locales/en.json @@ -528,7 +528,8 @@ "hidePreview": "Hide Preview", "showPreview": "Show Preview", "controlNetControlMode": "Control Mode", - "clipSkip": "Clip Skip" + "clipSkip": "Clip Skip", + "aspectRatio": "Aspect Ratio" }, "settings": { "models": "Models", diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamAspectRatio.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamAspectRatio.tsx new file mode 100644 index 0000000000..f14a88af75 --- /dev/null +++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamAspectRatio.tsx @@ -0,0 +1,49 @@ +import { Flex } from '@chakra-ui/react'; +import { RootState } from 'app/store/store'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; +import IAIButton from 'common/components/IAIButton'; +import { setAspectRatio } from 'features/ui/store/uiSlice'; +import { ReactNode } from 'react'; + +const aspectRatios = [ + { name: 'Free', value: null }, + { name: '4:3', value: 4 / 3 }, + { name: '16:9', value: 16 / 9 }, + { name: '3:2', value: 3 / 2 }, +]; + +export const roundToEight = (number: number) => { + return Math.round(number / 8) * 8; +}; + +export default function ParamAspectRatio() { + const aspectRatio = useAppSelector( + (state: RootState) => state.ui.aspectRatio + ); + + const dispatch = useAppDispatch(); + + const renderAspectRatios = () => { + const aspectRatiosToRender: ReactNode[] = []; + aspectRatios.forEach((ratio) => { + aspectRatiosToRender.push( + dispatch(setAspectRatio(ratio.value))} + > + {ratio.name} + + ); + }); + return aspectRatiosToRender; + }; + + return ( + + {renderAspectRatios()} + + ); +} diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamHeight.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamHeight.tsx index 6939ede424..617fe07fc5 100644 --- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamHeight.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamHeight.tsx @@ -3,18 +3,21 @@ import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions'; import IAISlider, { IAIFullSliderProps } from 'common/components/IAISlider'; import { generationSelector } from 'features/parameters/store/generationSelectors'; -import { setHeight } from 'features/parameters/store/generationSlice'; +import { setHeight, setWidth } from 'features/parameters/store/generationSlice'; import { configSelector } from 'features/system/store/configSelectors'; import { hotkeysSelector } from 'features/ui/store/hotkeysSlice'; +import { uiSelector } from 'features/ui/store/uiSelectors'; import { memo, useCallback } from 'react'; import { useTranslation } from 'react-i18next'; +import { roundToEight } from './ParamAspectRatio'; const selector = createSelector( - [generationSelector, hotkeysSelector, configSelector], - (generation, hotkeys, config) => { + [generationSelector, hotkeysSelector, configSelector, uiSelector], + (generation, hotkeys, config, ui) => { const { initial, min, sliderMax, inputMax, fineStep, coarseStep } = config.sd.height; const { height } = generation; + const { aspectRatio } = ui; const step = hotkeys.shift ? fineStep : coarseStep; @@ -25,6 +28,7 @@ const selector = createSelector( sliderMax, inputMax, step, + aspectRatio, }; }, defaultSelectorOptions @@ -36,7 +40,7 @@ type ParamHeightProps = Omit< >; const ParamHeight = (props: ParamHeightProps) => { - const { height, initial, min, sliderMax, inputMax, step } = + const { height, initial, min, sliderMax, inputMax, step, aspectRatio } = useAppSelector(selector); const dispatch = useAppDispatch(); const { t } = useTranslation(); @@ -44,13 +48,15 @@ const ParamHeight = (props: ParamHeightProps) => { const handleChange = useCallback( (v: number) => { dispatch(setHeight(v)); + if (aspectRatio) dispatch(setWidth(roundToEight(height * aspectRatio))); }, - [dispatch] + [dispatch, height, aspectRatio] ); const handleReset = useCallback(() => { dispatch(setHeight(initial)); - }, [dispatch, initial]); + if (aspectRatio) dispatch(setWidth(roundToEight(height * aspectRatio))); + }, [dispatch, initial, height, aspectRatio]); return ( state.generation.shouldFitToWidthHeight + ); + return ( + + + + {t('parameters.aspectRatio')} + + + + + + + + + ); +} diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamWidth.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamWidth.tsx index b4121184b5..daf08e2ada 100644 --- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamWidth.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamWidth.tsx @@ -3,18 +3,21 @@ import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions'; import IAISlider, { IAIFullSliderProps } from 'common/components/IAISlider'; import { generationSelector } from 'features/parameters/store/generationSelectors'; -import { setWidth } from 'features/parameters/store/generationSlice'; +import { setHeight, setWidth } from 'features/parameters/store/generationSlice'; import { configSelector } from 'features/system/store/configSelectors'; import { hotkeysSelector } from 'features/ui/store/hotkeysSlice'; +import { uiSelector } from 'features/ui/store/uiSelectors'; import { memo, useCallback } from 'react'; import { useTranslation } from 'react-i18next'; +import { roundToEight } from './ParamAspectRatio'; const selector = createSelector( - [generationSelector, hotkeysSelector, configSelector], - (generation, hotkeys, config) => { + [generationSelector, hotkeysSelector, configSelector, uiSelector], + (generation, hotkeys, config, ui) => { const { initial, min, sliderMax, inputMax, fineStep, coarseStep } = config.sd.width; const { width } = generation; + const { aspectRatio } = ui; const step = hotkeys.shift ? fineStep : coarseStep; @@ -25,6 +28,7 @@ const selector = createSelector( sliderMax, inputMax, step, + aspectRatio, }; }, defaultSelectorOptions @@ -33,7 +37,7 @@ const selector = createSelector( type ParamWidthProps = Omit; const ParamWidth = (props: ParamWidthProps) => { - const { width, initial, min, sliderMax, inputMax, step } = + const { width, initial, min, sliderMax, inputMax, step, aspectRatio } = useAppSelector(selector); const dispatch = useAppDispatch(); const { t } = useTranslation(); @@ -41,13 +45,15 @@ const ParamWidth = (props: ParamWidthProps) => { const handleChange = useCallback( (v: number) => { dispatch(setWidth(v)); + if (aspectRatio) dispatch(setHeight(roundToEight(width / aspectRatio))); }, - [dispatch] + [dispatch, aspectRatio, width] ); const handleReset = useCallback(() => { dispatch(setWidth(initial)); - }, [dispatch, initial]); + if (aspectRatio) dispatch(setHeight(roundToEight(width / aspectRatio))); + }, [dispatch, initial, width, aspectRatio]); return ( { + const ratio = action.payload; + if (ratio) state.height = roundToEight(state.width / ratio); + }); }, }); diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/ImageToImage/ImageToImageTabCoreParameters.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/ImageToImage/ImageToImageTabCoreParameters.tsx index b333a0caf2..cda908da50 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/ImageToImage/ImageToImageTabCoreParameters.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/ImageToImage/ImageToImageTabCoreParameters.tsx @@ -4,11 +4,10 @@ import { useAppSelector } from 'app/store/storeHooks'; import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions'; import IAICollapse from 'common/components/IAICollapse'; import ParamCFGScale from 'features/parameters/components/Parameters/Core/ParamCFGScale'; -import ParamHeight from 'features/parameters/components/Parameters/Core/ParamHeight'; import ParamIterations from 'features/parameters/components/Parameters/Core/ParamIterations'; import ParamModelandVAEandScheduler from 'features/parameters/components/Parameters/Core/ParamModelandVAEandScheduler'; +import ParamSize from 'features/parameters/components/Parameters/Core/ParamSize'; import ParamSteps from 'features/parameters/components/Parameters/Core/ParamSteps'; -import ParamWidth from 'features/parameters/components/Parameters/Core/ParamWidth'; import ImageToImageFit from 'features/parameters/components/Parameters/ImageToImage/ImageToImageFit'; import ImageToImageStrength from 'features/parameters/components/Parameters/ImageToImage/ImageToImageStrength'; import ParamSeedFull from 'features/parameters/components/Parameters/Seed/ParamSeedFull'; @@ -47,15 +46,14 @@ const ImageToImageTabCoreParameters = () => { > {shouldUseSliders ? ( <> + + + - - - - - + ) : ( <> @@ -68,8 +66,7 @@ const ImageToImageTabCoreParameters = () => { - - + )} diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/TextToImage/TextToImageTabCoreParameters.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/TextToImage/TextToImageTabCoreParameters.tsx index b007497db2..de8f64e661 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/TextToImage/TextToImageTabCoreParameters.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/TextToImage/TextToImageTabCoreParameters.tsx @@ -5,11 +5,10 @@ import { useAppSelector } from 'app/store/storeHooks'; import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions'; import IAICollapse from 'common/components/IAICollapse'; import ParamCFGScale from 'features/parameters/components/Parameters/Core/ParamCFGScale'; -import ParamHeight from 'features/parameters/components/Parameters/Core/ParamHeight'; import ParamIterations from 'features/parameters/components/Parameters/Core/ParamIterations'; import ParamModelandVAEandScheduler from 'features/parameters/components/Parameters/Core/ParamModelandVAEandScheduler'; +import ParamSize from 'features/parameters/components/Parameters/Core/ParamSize'; import ParamSteps from 'features/parameters/components/Parameters/Core/ParamSteps'; -import ParamWidth from 'features/parameters/components/Parameters/Core/ParamWidth'; import ParamSeedFull from 'features/parameters/components/Parameters/Seed/ParamSeedFull'; import { memo } from 'react'; @@ -43,15 +42,14 @@ const TextToImageTabCoreParameters = () => { > {shouldUseSliders ? ( <> + + + - - - - - + ) : ( <> @@ -64,8 +62,7 @@ const TextToImageTabCoreParameters = () => { - - + )} diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasCoreParameters.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasCoreParameters.tsx index ecce61c218..6ea9d4bc8d 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasCoreParameters.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/UnifiedCanvas/UnifiedCanvasCoreParameters.tsx @@ -44,13 +44,13 @@ const UnifiedCanvasCoreParameters = () => { > {shouldUseSliders ? ( <> + + + - - - diff --git a/invokeai/frontend/web/src/features/ui/store/uiSlice.ts b/invokeai/frontend/web/src/features/ui/store/uiSlice.ts index 04fee42126..4f38f84fe2 100644 --- a/invokeai/frontend/web/src/features/ui/store/uiSlice.ts +++ b/invokeai/frontend/web/src/features/ui/store/uiSlice.ts @@ -21,6 +21,7 @@ export const initialUIState: UIState = { shouldShowProgressInViewer: true, shouldShowEmbeddingPicker: false, shouldShowAdvancedOptions: false, + aspectRatio: null, favoriteSchedulers: [], }; @@ -104,6 +105,9 @@ export const uiSlice = createSlice({ setShouldShowAdvancedOptions: (state, action: PayloadAction) => { state.shouldShowAdvancedOptions = action.payload; }, + setAspectRatio: (state, action: PayloadAction) => { + state.aspectRatio = action.payload; + }, }, extraReducers(builder) { builder.addCase(initialImageChanged, (state) => { @@ -132,6 +136,7 @@ export const { favoriteSchedulersChanged, toggleEmbeddingPicker, setShouldShowAdvancedOptions, + setAspectRatio, } = uiSlice.actions; export default uiSlice.reducer; diff --git a/invokeai/frontend/web/src/features/ui/store/uiTypes.ts b/invokeai/frontend/web/src/features/ui/store/uiTypes.ts index 2356446030..e574f0ab79 100644 --- a/invokeai/frontend/web/src/features/ui/store/uiTypes.ts +++ b/invokeai/frontend/web/src/features/ui/store/uiTypes.ts @@ -29,5 +29,6 @@ export interface UIState { shouldShowProgressInViewer: boolean; shouldShowEmbeddingPicker: boolean; shouldShowAdvancedOptions: boolean; + aspectRatio: number | null; favoriteSchedulers: SchedulerParam[]; } From cafd97e5bceb9812c65eb4f785f59d49bbc304d6 Mon Sep 17 00:00:00 2001 From: blessedcoolant <54517381+blessedcoolant@users.noreply.github.com> Date: Sun, 9 Jul 2023 23:24:15 +1200 Subject: [PATCH 2/6] fix: Reset handler not adjusting correctly --- .../parameters/components/Parameters/Core/ParamHeight.tsx | 4 ++-- .../parameters/components/Parameters/Core/ParamWidth.tsx | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamHeight.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamHeight.tsx index 617fe07fc5..8d0c6fbb6e 100644 --- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamHeight.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamHeight.tsx @@ -55,8 +55,8 @@ const ParamHeight = (props: ParamHeightProps) => { const handleReset = useCallback(() => { dispatch(setHeight(initial)); - if (aspectRatio) dispatch(setWidth(roundToEight(height * aspectRatio))); - }, [dispatch, initial, height, aspectRatio]); + if (aspectRatio) dispatch(setWidth(roundToEight(initial * aspectRatio))); + }, [dispatch, initial, aspectRatio]); return ( { const handleReset = useCallback(() => { dispatch(setWidth(initial)); - if (aspectRatio) dispatch(setHeight(roundToEight(width / aspectRatio))); - }, [dispatch, initial, width, aspectRatio]); + if (aspectRatio) dispatch(setHeight(roundToEight(initial / aspectRatio))); + }, [dispatch, initial, aspectRatio]); return ( Date: Sun, 9 Jul 2023 22:13:26 +1000 Subject: [PATCH 3/6] fix(ui): fix number input on aspect ratio --- .../components/Parameters/Core/ParamHeight.tsx | 14 ++++++++++---- .../components/Parameters/Core/ParamWidth.tsx | 14 ++++++++++---- .../features/parameters/store/generationSlice.ts | 4 +++- 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamHeight.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamHeight.tsx index 8d0c6fbb6e..63abe0ddf9 100644 --- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamHeight.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamHeight.tsx @@ -2,6 +2,7 @@ import { createSelector } from '@reduxjs/toolkit'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions'; import IAISlider, { IAIFullSliderProps } from 'common/components/IAISlider'; +import { roundToMultiple } from 'common/util/roundDownToMultiple'; import { generationSelector } from 'features/parameters/store/generationSelectors'; import { setHeight, setWidth } from 'features/parameters/store/generationSlice'; import { configSelector } from 'features/system/store/configSelectors'; @@ -9,7 +10,6 @@ import { hotkeysSelector } from 'features/ui/store/hotkeysSlice'; import { uiSelector } from 'features/ui/store/uiSelectors'; import { memo, useCallback } from 'react'; import { useTranslation } from 'react-i18next'; -import { roundToEight } from './ParamAspectRatio'; const selector = createSelector( [generationSelector, hotkeysSelector, configSelector, uiSelector], @@ -48,14 +48,20 @@ const ParamHeight = (props: ParamHeightProps) => { const handleChange = useCallback( (v: number) => { dispatch(setHeight(v)); - if (aspectRatio) dispatch(setWidth(roundToEight(height * aspectRatio))); + if (aspectRatio) { + const newWidth = roundToMultiple(v * aspectRatio, 8); + dispatch(setWidth(newWidth)); + } }, - [dispatch, height, aspectRatio] + [dispatch, aspectRatio] ); const handleReset = useCallback(() => { dispatch(setHeight(initial)); - if (aspectRatio) dispatch(setWidth(roundToEight(initial * aspectRatio))); + if (aspectRatio) { + const newWidth = roundToMultiple(initial * aspectRatio, 8); + dispatch(setWidth(newWidth)); + } }, [dispatch, initial, aspectRatio]); return ( diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamWidth.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamWidth.tsx index fd6decea11..991db19097 100644 --- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamWidth.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamWidth.tsx @@ -2,6 +2,7 @@ import { createSelector } from '@reduxjs/toolkit'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions'; import IAISlider, { IAIFullSliderProps } from 'common/components/IAISlider'; +import { roundToMultiple } from 'common/util/roundDownToMultiple'; import { generationSelector } from 'features/parameters/store/generationSelectors'; import { setHeight, setWidth } from 'features/parameters/store/generationSlice'; import { configSelector } from 'features/system/store/configSelectors'; @@ -9,7 +10,6 @@ import { hotkeysSelector } from 'features/ui/store/hotkeysSlice'; import { uiSelector } from 'features/ui/store/uiSelectors'; import { memo, useCallback } from 'react'; import { useTranslation } from 'react-i18next'; -import { roundToEight } from './ParamAspectRatio'; const selector = createSelector( [generationSelector, hotkeysSelector, configSelector, uiSelector], @@ -45,14 +45,20 @@ const ParamWidth = (props: ParamWidthProps) => { const handleChange = useCallback( (v: number) => { dispatch(setWidth(v)); - if (aspectRatio) dispatch(setHeight(roundToEight(width / aspectRatio))); + if (aspectRatio) { + const newHeight = roundToMultiple(v / aspectRatio, 8); + dispatch(setHeight(newHeight)); + } }, - [dispatch, aspectRatio, width] + [dispatch, aspectRatio] ); const handleReset = useCallback(() => { dispatch(setWidth(initial)); - if (aspectRatio) dispatch(setHeight(roundToEight(initial / aspectRatio))); + if (aspectRatio) { + const newHeight = roundToMultiple(initial / aspectRatio, 8); + dispatch(setHeight(newHeight)); + } }, [dispatch, initial, aspectRatio]); return ( diff --git a/invokeai/frontend/web/src/features/parameters/store/generationSlice.ts b/invokeai/frontend/web/src/features/parameters/store/generationSlice.ts index 692e0113d6..89e2f29972 100644 --- a/invokeai/frontend/web/src/features/parameters/store/generationSlice.ts +++ b/invokeai/frontend/web/src/features/parameters/store/generationSlice.ts @@ -268,7 +268,9 @@ export const generationSlice = createSlice({ }); builder.addCase(setAspectRatio, (state, action) => { const ratio = action.payload; - if (ratio) state.height = roundToEight(state.width / ratio); + if (ratio) { + state.height = roundToMultiple(state.width / ratio, 8); + } }); }, }); From 0e178c3bb7bca9ed4e827d9f8e7a803a9f350922 Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Sun, 9 Jul 2023 22:13:38 +1000 Subject: [PATCH 4/6] feat(ui): aspect ratio styling --- .../Parameters/Core/ParamAspectRatio.tsx | 40 +++++++------------ .../components/Parameters/Core/ParamSize.tsx | 31 ++++++++++---- 2 files changed, 37 insertions(+), 34 deletions(-) diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamAspectRatio.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamAspectRatio.tsx index f14a88af75..1b575b5793 100644 --- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamAspectRatio.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamAspectRatio.tsx @@ -1,9 +1,8 @@ -import { Flex } from '@chakra-ui/react'; +import { ButtonGroup, Flex } from '@chakra-ui/react'; import { RootState } from 'app/store/store'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import IAIButton from 'common/components/IAIButton'; import { setAspectRatio } from 'features/ui/store/uiSlice'; -import { ReactNode } from 'react'; const aspectRatios = [ { name: 'Free', value: null }, @@ -12,10 +11,6 @@ const aspectRatios = [ { name: '3:2', value: 3 / 2 }, ]; -export const roundToEight = (number: number) => { - return Math.round(number / 8) * 8; -}; - export default function ParamAspectRatio() { const aspectRatio = useAppSelector( (state: RootState) => state.ui.aspectRatio @@ -23,27 +18,20 @@ export default function ParamAspectRatio() { const dispatch = useAppDispatch(); - const renderAspectRatios = () => { - const aspectRatiosToRender: ReactNode[] = []; - aspectRatios.forEach((ratio) => { - aspectRatiosToRender.push( - dispatch(setAspectRatio(ratio.value))} - > - {ratio.name} - - ); - }); - return aspectRatiosToRender; - }; - return ( - - {renderAspectRatios()} + + + {aspectRatios.map((ratio) => ( + dispatch(setAspectRatio(ratio.value))} + > + {ratio.name} + + ))} + ); } diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamSize.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamSize.tsx index 55340ce799..15637bb091 100644 --- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamSize.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamSize.tsx @@ -1,4 +1,4 @@ -import { Flex, Text } from '@chakra-ui/react'; +import { Flex, Spacer, Text } from '@chakra-ui/react'; import { RootState } from 'app/store/store'; import { useAppSelector } from 'app/store/storeHooks'; import { useTranslation } from 'react-i18next'; @@ -13,17 +13,32 @@ export default function ParamSize() { ); return ( - + {t('parameters.aspectRatio')} + From dfe338fc5099154854ebf1c728abbe355925d924 Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Sun, 9 Jul 2023 22:47:54 +1000 Subject: [PATCH 5/6] fix(ui): fix missing import --- .../web/src/features/parameters/store/generationSlice.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/invokeai/frontend/web/src/features/parameters/store/generationSlice.ts b/invokeai/frontend/web/src/features/parameters/store/generationSlice.ts index 89e2f29972..5e476e1b3b 100644 --- a/invokeai/frontend/web/src/features/parameters/store/generationSlice.ts +++ b/invokeai/frontend/web/src/features/parameters/store/generationSlice.ts @@ -1,6 +1,7 @@ import type { PayloadAction } from '@reduxjs/toolkit'; import { createSlice } from '@reduxjs/toolkit'; import { DEFAULT_SCHEDULER_NAME } from 'app/constants'; +import { roundToMultiple } from 'common/util/roundDownToMultiple'; import { configChanged } from 'features/system/store/configSlice'; import { setAspectRatio, @@ -9,7 +10,6 @@ import { import { clamp } from 'lodash-es'; import { ImageDTO } from 'services/api/types'; import { clipSkipMap } from '../components/Parameters/Advanced/ParamClipSkip'; -import { roundToEight } from '../components/Parameters/Core/ParamAspectRatio'; import { CfgScaleParam, HeightParam, From 964c71dcb02d5ddbd1c376e963ddd0bf31a1bbe7 Mon Sep 17 00:00:00 2001 From: blessedcoolant <54517381+blessedcoolant@users.noreply.github.com> Date: Mon, 10 Jul 2023 18:10:57 +1200 Subject: [PATCH 6/6] feat: Add Swap Sizes --- invokeai/frontend/web/public/locales/en.json | 5 +++-- .../Parameters/Core/ParamAspectRatio.tsx | 6 ++--- .../components/Parameters/Core/ParamSize.tsx | 22 +++++++++++++++---- .../parameters/store/generationSlice.ts | 8 ++++++- 4 files changed, 31 insertions(+), 10 deletions(-) diff --git a/invokeai/frontend/web/public/locales/en.json b/invokeai/frontend/web/public/locales/en.json index 29a3c0907c..6734f1dcd1 100644 --- a/invokeai/frontend/web/public/locales/en.json +++ b/invokeai/frontend/web/public/locales/en.json @@ -529,7 +529,7 @@ "showPreview": "Show Preview", "controlNetControlMode": "Control Mode", "clipSkip": "Clip Skip", - "aspectRatio": "Aspect Ratio" + "aspectRatio": "Ratio" }, "settings": { "models": "Models", @@ -672,6 +672,7 @@ }, "ui": { "showProgressImages": "Show Progress Images", - "hideProgressImages": "Hide Progress Images" + "hideProgressImages": "Hide Progress Images", + "swapSizes": "Swap Sizes" } } diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamAspectRatio.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamAspectRatio.tsx index 1b575b5793..0a568fb84d 100644 --- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamAspectRatio.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamAspectRatio.tsx @@ -6,9 +6,9 @@ import { setAspectRatio } from 'features/ui/store/uiSlice'; const aspectRatios = [ { name: 'Free', value: null }, - { name: '4:3', value: 4 / 3 }, - { name: '16:9', value: 16 / 9 }, - { name: '3:2', value: 3 / 2 }, + { name: 'Portrait', value: 0.67 / 1 }, + { name: 'Wide', value: 16 / 9 }, + { name: 'Square', value: 1 / 1 }, ]; export default function ParamAspectRatio() { diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamSize.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamSize.tsx index 15637bb091..496431ff3d 100644 --- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamSize.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Core/ParamSize.tsx @@ -1,13 +1,17 @@ import { Flex, Spacer, Text } from '@chakra-ui/react'; import { RootState } from 'app/store/store'; -import { useAppSelector } from 'app/store/storeHooks'; +import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; +import IAIIconButton from 'common/components/IAIIconButton'; +import { toggleSize } from 'features/parameters/store/generationSlice'; import { useTranslation } from 'react-i18next'; +import { MdOutlineSwapVert } from 'react-icons/md'; import ParamAspectRatio from './ParamAspectRatio'; import ParamHeight from './ParamHeight'; import ParamWidth from './ParamWidth'; export default function ParamSize() { const { t } = useTranslation(); + const dispatch = useAppDispatch(); const shouldFitToWidthHeight = useAppSelector( (state: RootState) => state.generation.shouldFitToWidthHeight ); @@ -40,10 +44,20 @@ export default function ParamSize() { + } + fontSize={20} + onClick={() => dispatch(toggleSize())} + /> - - - + + + + + ); diff --git a/invokeai/frontend/web/src/features/parameters/store/generationSlice.ts b/invokeai/frontend/web/src/features/parameters/store/generationSlice.ts index 5e476e1b3b..56728f216f 100644 --- a/invokeai/frontend/web/src/features/parameters/store/generationSlice.ts +++ b/invokeai/frontend/web/src/features/parameters/store/generationSlice.ts @@ -143,6 +143,11 @@ export const generationSlice = createSlice({ setWidth: (state, action: PayloadAction) => { state.width = action.payload; }, + toggleSize: (state) => { + const [width, height] = [state.width, state.height]; + state.width = height; + state.height = width; + }, setScheduler: (state, action: PayloadAction) => { state.scheduler = action.payload; }, @@ -281,7 +286,9 @@ export const { resetParametersState, resetSeed, setCfgScale, + setWidth, setHeight, + toggleSize, setImg2imgStrength, setInfillMethod, setIterations, @@ -302,7 +309,6 @@ export const { setThreshold, setTileSize, setVariationAmount, - setWidth, setShouldUseSymmetry, setHorizontalSymmetrySteps, setVerticalSymmetrySteps,