feat(ui): extract aspect ratios from canvas reducers

This commit is contained in:
psychedelicious
2025-07-05 20:03:52 +10:00
parent 16c8017f1a
commit 8d83caaae0
3 changed files with 59 additions and 77 deletions

View File

@@ -32,7 +32,6 @@ import {
} from 'features/controlLayers/util/getScaledBoundingBoxDimensions';
import { simplifyFlatNumbersArray } from 'features/controlLayers/util/simplify';
import { isMainModelBase, zModelIdentifierField } from 'features/nodes/types/common';
import { ASPECT_RATIO_MAP } from 'features/parameters/components/Bbox/constants';
import { API_BASE_MODELS } from 'features/parameters/types/constants';
import { getGridSize, getIsSizeOptimal, getOptimalDimension } from 'features/parameters/util/optimalDimension';
import type { IRect } from 'konva/lib/types';
@@ -69,9 +68,13 @@ import type {
T2IAdapterConfig,
} from './types';
import {
ASPECT_RATIO_MAP,
CHATGPT_ASPECT_RATIOS,
DEFAULT_ASPECT_RATIO_CONFIG,
FLUX_KONTEXT_ASPECT_RATIOS,
getEntityIdentifier,
getInitialCanvasState,
IMAGEN_ASPECT_RATIOS,
isChatGPT4oAspectRatioID,
isFluxKontextAspectRatioID,
isFLUXReduxConfig,
@@ -1100,62 +1103,21 @@ export const canvasSlice = createSlice({
(state.bbox.modelBase === 'imagen3' || state.bbox.modelBase === 'imagen4') &&
isImagenAspectRatioID(id)
) {
// Imagen3 has specific output sizes that are not exactly the same as the aspect ratio. Need special handling.
if (id === '16:9') {
state.bbox.rect.width = 1408;
state.bbox.rect.height = 768;
} else if (id === '4:3') {
state.bbox.rect.width = 1280;
state.bbox.rect.height = 896;
} else if (id === '1:1') {
state.bbox.rect.width = 1024;
state.bbox.rect.height = 1024;
} else if (id === '3:4') {
state.bbox.rect.width = 896;
state.bbox.rect.height = 1280;
} else if (id === '9:16') {
state.bbox.rect.width = 768;
state.bbox.rect.height = 1408;
}
const { width, height } = IMAGEN_ASPECT_RATIOS[id];
state.bbox.rect.width = width;
state.bbox.rect.height = height;
state.bbox.aspectRatio.value = state.bbox.rect.width / state.bbox.rect.height;
state.bbox.aspectRatio.isLocked = true;
} else if (state.bbox.modelBase === 'chatgpt-4o' && isChatGPT4oAspectRatioID(id)) {
// gpt-image has specific output sizes that are not exactly the same as the aspect ratio. Need special handling.
if (id === '3:2') {
state.bbox.rect.width = 1536;
state.bbox.rect.height = 1024;
} else if (id === '1:1') {
state.bbox.rect.width = 1024;
state.bbox.rect.height = 1024;
} else if (id === '2:3') {
state.bbox.rect.width = 1024;
state.bbox.rect.height = 1536;
}
const { width, height } = CHATGPT_ASPECT_RATIOS[id];
state.bbox.rect.width = width;
state.bbox.rect.height = height;
state.bbox.aspectRatio.value = state.bbox.rect.width / state.bbox.rect.height;
state.bbox.aspectRatio.isLocked = true;
} else if (state.bbox.modelBase === 'flux-kontext' && isFluxKontextAspectRatioID(id)) {
if (id === '3:4') {
state.bbox.rect.width = 880;
state.bbox.rect.height = 1184;
} else if (id === '4:3') {
state.bbox.rect.width = 1184;
state.bbox.rect.height = 880;
} else if (id === '9:16') {
state.bbox.rect.width = 752;
state.bbox.rect.height = 1392;
} else if (id === '16:9') {
state.bbox.rect.width = 1392;
state.bbox.rect.height = 752;
} else if (id === '21:9') {
state.bbox.rect.width = 1568;
state.bbox.rect.height = 672;
} else if (id === '9:21') {
state.bbox.rect.width = 672;
state.bbox.rect.height = 1568;
} else if (id === '1:1') {
state.bbox.rect.width = 1024;
state.bbox.rect.height = 1024;
}
const { width, height } = FLUX_KONTEXT_ASPECT_RATIOS[id];
state.bbox.rect.width = width;
state.bbox.rect.height = height;
state.bbox.aspectRatio.value = state.bbox.rect.width / state.bbox.rect.height;
state.bbox.aspectRatio.isLocked = true;
} else {

View File

@@ -434,21 +434,54 @@ export type LoRA = {
export type EphemeralProgressImage = { sessionId: string; image: ProgressImage };
export const zAspectRatioID = z.enum(['Free', '21:9', '9:21', '16:9', '3:2', '4:3', '1:1', '3:4', '2:3', '9:16']);
export const zImagen3AspectRatioID = z.enum(['16:9', '4:3', '1:1', '3:4', '9:16']);
export const isImagenAspectRatioID = (v: unknown): v is z.infer<typeof zImagen3AspectRatioID> =>
zImagen3AspectRatioID.safeParse(v).success;
export const zChatGPT4oAspectRatioID = z.enum(['3:2', '1:1', '2:3']);
export const isChatGPT4oAspectRatioID = (v: unknown): v is z.infer<typeof zChatGPT4oAspectRatioID> =>
zChatGPT4oAspectRatioID.safeParse(v).success;
export const zFluxKontextAspectRatioID = z.enum(['21:9', '4:3', '1:1', '3:4', '9:21', '16:9', '9:16']);
export const isFluxKontextAspectRatioID = (v: unknown): v is z.infer<typeof zFluxKontextAspectRatioID> =>
zFluxKontextAspectRatioID.safeParse(v).success;
export type AspectRatioID = z.infer<typeof zAspectRatioID>;
export const isAspectRatioID = (v: unknown): v is AspectRatioID => zAspectRatioID.safeParse(v).success;
export const ASPECT_RATIO_MAP: Record<Exclude<AspectRatioID, 'Free'>, { ratio: number; inverseID: AspectRatioID }> = {
'21:9': { ratio: 21 / 9, inverseID: '9:21' },
'16:9': { ratio: 16 / 9, inverseID: '9:16' },
'3:2': { ratio: 3 / 2, inverseID: '2:3' },
'4:3': { ratio: 4 / 3, inverseID: '4:3' },
'1:1': { ratio: 1, inverseID: '1:1' },
'3:4': { ratio: 3 / 4, inverseID: '4:3' },
'2:3': { ratio: 2 / 3, inverseID: '3:2' },
'9:16': { ratio: 9 / 16, inverseID: '16:9' },
'9:21': { ratio: 9 / 21, inverseID: '21:9' },
};
export const zImagen3AspectRatioID = z.enum(['16:9', '4:3', '1:1', '3:4', '9:16']);
type ImagenAspectRatio = z.infer<typeof zImagen3AspectRatioID>;
export const isImagenAspectRatioID = (v: unknown): v is ImagenAspectRatio => zImagen3AspectRatioID.safeParse(v).success;
export const IMAGEN_ASPECT_RATIOS: Record<ImagenAspectRatio, Dimensions> = {
'16:9': { width: 1408, height: 768 },
'4:3': { width: 1280, height: 896 },
'1:1': { width: 1024, height: 1024 },
'3:4': { width: 896, height: 1280 },
'9:16': { width: 768, height: 1408 },
};
export const zChatGPT4oAspectRatioID = z.enum(['3:2', '1:1', '2:3']);
type ChatGPT4oAspectRatio = z.infer<typeof zChatGPT4oAspectRatioID>;
export const isChatGPT4oAspectRatioID = (v: unknown): v is ChatGPT4oAspectRatio =>
zChatGPT4oAspectRatioID.safeParse(v).success;
export const CHATGPT_ASPECT_RATIOS: Record<ChatGPT4oAspectRatio, Dimensions> = {
'3:2': { width: 1536, height: 1024 },
'1:1': { width: 1024, height: 1024 },
'2:3': { width: 1024, height: 1536 },
} as const;
export const zFluxKontextAspectRatioID = z.enum(['21:9', '4:3', '1:1', '3:4', '9:21', '16:9', '9:16']);
type FluxKontextAspectRatio = z.infer<typeof zFluxKontextAspectRatioID>;
export const isFluxKontextAspectRatioID = (v: unknown): v is z.infer<typeof zFluxKontextAspectRatioID> =>
zFluxKontextAspectRatioID.safeParse(v).success;
export const FLUX_KONTEXT_ASPECT_RATIOS: Record<FluxKontextAspectRatio, Dimensions> = {
'3:4': { width: 880, height: 1184 },
'4:3': { width: 1184, height: 880 },
'9:16': { width: 752, height: 1392 },
'16:9': { width: 1392, height: 752 },
'21:9': { width: 1568, height: 672 },
'9:21': { width: 672, height: 1568 },
'1:1': { width: 1024, height: 1024 },
};
const zAspectRatioConfig = z.object({
id: zAspectRatioID,

View File

@@ -1,13 +0,0 @@
import type { AspectRatioID } from 'features/controlLayers/store/types';
export const ASPECT_RATIO_MAP: Record<Exclude<AspectRatioID, 'Free'>, { ratio: number; inverseID: AspectRatioID }> = {
'21:9': { ratio: 21 / 9, inverseID: '9:21' },
'16:9': { ratio: 16 / 9, inverseID: '9:16' },
'3:2': { ratio: 3 / 2, inverseID: '2:3' },
'4:3': { ratio: 4 / 3, inverseID: '4:3' },
'1:1': { ratio: 1, inverseID: '1:1' },
'3:4': { ratio: 3 / 4, inverseID: '4:3' },
'2:3': { ratio: 2 / 3, inverseID: '3:2' },
'9:16': { ratio: 9 / 16, inverseID: '16:9' },
'9:21': { ratio: 9 / 21, inverseID: '21:9' },
};