Skip to content

Commit 3579122

Browse files
feat: Scaled Bounding Box Dimensions now respect Aspect Ratio (#4463)
## What type of PR is this? (check all applicable) - [x] Feature ## Have you discussed this change with the InvokeAI team? - [x] Yes ## Description Scale Before Processing Dimensions now respect the Aspect Ratio that is locked in. This makes it way easier to control the setting when using it with locked ratios on the canvas.
2 parents ba2ce72 + 0f2b8dd commit 3579122

File tree

3 files changed

+56
-12
lines changed

3 files changed

+56
-12
lines changed

invokeai/frontend/web/src/features/canvas/store/canvasSlice.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,10 +235,18 @@ export const canvasSlice = createSlice({
235235
state.boundingBoxDimensions.width,
236236
state.boundingBoxDimensions.height,
237237
];
238+
const [currScaledWidth, currScaledHeight] = [
239+
state.scaledBoundingBoxDimensions.width,
240+
state.scaledBoundingBoxDimensions.height,
241+
];
238242
state.boundingBoxDimensions = {
239243
width: currHeight,
240244
height: currWidth,
241245
};
246+
state.scaledBoundingBoxDimensions = {
247+
width: currScaledHeight,
248+
height: currScaledWidth,
249+
};
242250
},
243251
setBoundingBoxCoordinates: (state, action: PayloadAction<Vector2d>) => {
244252
state.boundingBoxCoordinates = floorCoordinates(action.payload);
@@ -788,6 +796,10 @@ export const canvasSlice = createSlice({
788796
state.boundingBoxDimensions.width / ratio,
789797
64
790798
);
799+
state.scaledBoundingBoxDimensions.height = roundToMultiple(
800+
state.scaledBoundingBoxDimensions.width / ratio,
801+
64
802+
);
791803
}
792804
});
793805
},

invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/InfillAndScaling/ParamScaledHeight.tsx

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { createSelector } from '@reduxjs/toolkit';
22
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
33
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
44
import IAISlider from 'common/components/IAISlider';
5+
import { roundToMultiple } from 'common/util/roundDownToMultiple';
56
import { canvasSelector } from 'features/canvas/store/canvasSelectors';
67
import { setScaledBoundingBoxDimensions } from 'features/canvas/store/canvasSlice';
78
import { generationSelector } from 'features/parameters/store/generationSelectors';
@@ -12,20 +13,21 @@ const selector = createSelector(
1213
[generationSelector, canvasSelector],
1314
(generation, canvas) => {
1415
const { scaledBoundingBoxDimensions, boundingBoxScaleMethod } = canvas;
15-
const { model } = generation;
16+
const { model, aspectRatio } = generation;
1617

1718
return {
1819
model,
1920
scaledBoundingBoxDimensions,
2021
isManual: boundingBoxScaleMethod === 'manual',
22+
aspectRatio,
2123
};
2224
},
2325
defaultSelectorOptions
2426
);
2527

2628
const ParamScaledHeight = () => {
2729
const dispatch = useAppDispatch();
28-
const { model, isManual, scaledBoundingBoxDimensions } =
30+
const { model, isManual, scaledBoundingBoxDimensions, aspectRatio } =
2931
useAppSelector(selector);
3032

3133
const initial = ['sdxl', 'sdxl-refiner'].includes(model?.base_model as string)
@@ -35,19 +37,33 @@ const ParamScaledHeight = () => {
3537
const { t } = useTranslation();
3638

3739
const handleChangeScaledHeight = (v: number) => {
40+
let newWidth = scaledBoundingBoxDimensions.width;
41+
const newHeight = Math.floor(v);
42+
43+
if (aspectRatio) {
44+
newWidth = roundToMultiple(newHeight * aspectRatio, 64);
45+
}
46+
3847
dispatch(
3948
setScaledBoundingBoxDimensions({
40-
...scaledBoundingBoxDimensions,
41-
height: Math.floor(v),
49+
width: newWidth,
50+
height: newHeight,
4251
})
4352
);
4453
};
4554

4655
const handleResetScaledHeight = () => {
56+
let resetWidth = scaledBoundingBoxDimensions.width;
57+
const resetHeight = Math.floor(initial);
58+
59+
if (aspectRatio) {
60+
resetWidth = roundToMultiple(resetHeight * aspectRatio, 64);
61+
}
62+
4763
dispatch(
4864
setScaledBoundingBoxDimensions({
49-
...scaledBoundingBoxDimensions,
50-
height: Math.floor(initial),
65+
width: resetWidth,
66+
height: resetHeight,
5167
})
5268
);
5369
};

invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/InfillAndScaling/ParamScaledWidth.tsx

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { createSelector } from '@reduxjs/toolkit';
22
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
33
import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions';
44
import IAISlider from 'common/components/IAISlider';
5+
import { roundToMultiple } from 'common/util/roundDownToMultiple';
56
import { canvasSelector } from 'features/canvas/store/canvasSelectors';
67
import { setScaledBoundingBoxDimensions } from 'features/canvas/store/canvasSlice';
78
import { generationSelector } from 'features/parameters/store/generationSelectors';
@@ -12,11 +13,12 @@ const selector = createSelector(
1213
[canvasSelector, generationSelector],
1314
(canvas, generation) => {
1415
const { boundingBoxScaleMethod, scaledBoundingBoxDimensions } = canvas;
15-
const { model } = generation;
16+
const { model, aspectRatio } = generation;
1617

1718
return {
1819
model,
1920
scaledBoundingBoxDimensions,
21+
aspectRatio,
2022
isManual: boundingBoxScaleMethod === 'manual',
2123
};
2224
},
@@ -25,7 +27,7 @@ const selector = createSelector(
2527

2628
const ParamScaledWidth = () => {
2729
const dispatch = useAppDispatch();
28-
const { model, isManual, scaledBoundingBoxDimensions } =
30+
const { model, isManual, scaledBoundingBoxDimensions, aspectRatio } =
2931
useAppSelector(selector);
3032

3133
const initial = ['sdxl', 'sdxl-refiner'].includes(model?.base_model as string)
@@ -35,19 +37,33 @@ const ParamScaledWidth = () => {
3537
const { t } = useTranslation();
3638

3739
const handleChangeScaledWidth = (v: number) => {
40+
const newWidth = Math.floor(v);
41+
let newHeight = scaledBoundingBoxDimensions.height;
42+
43+
if (aspectRatio) {
44+
newHeight = roundToMultiple(newWidth / aspectRatio, 64);
45+
}
46+
3847
dispatch(
3948
setScaledBoundingBoxDimensions({
40-
...scaledBoundingBoxDimensions,
41-
width: Math.floor(v),
49+
width: newWidth,
50+
height: newHeight,
4251
})
4352
);
4453
};
4554

4655
const handleResetScaledWidth = () => {
56+
const resetWidth = Math.floor(initial);
57+
let resetHeight = scaledBoundingBoxDimensions.height;
58+
59+
if (aspectRatio) {
60+
resetHeight = roundToMultiple(resetWidth / aspectRatio, 64);
61+
}
62+
4763
dispatch(
4864
setScaledBoundingBoxDimensions({
49-
...scaledBoundingBoxDimensions,
50-
width: Math.floor(initial),
65+
width: resetWidth,
66+
height: resetHeight,
5167
})
5268
);
5369
};

0 commit comments

Comments
 (0)