mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
translations and lint fix
This commit is contained in:
parent
4a09cc57be
commit
9e3412d776
@ -1027,6 +1027,7 @@
|
|||||||
"imageActions": "Image Actions",
|
"imageActions": "Image Actions",
|
||||||
"sendToImg2Img": "Send to Image to Image",
|
"sendToImg2Img": "Send to Image to Image",
|
||||||
"sendToUnifiedCanvas": "Send To Unified Canvas",
|
"sendToUnifiedCanvas": "Send To Unified Canvas",
|
||||||
|
"sendToUpscale": "Send To Upscale",
|
||||||
"showOptionsPanel": "Show Side Panel (O or T)",
|
"showOptionsPanel": "Show Side Panel (O or T)",
|
||||||
"shuffle": "Shuffle Seed",
|
"shuffle": "Shuffle Seed",
|
||||||
"steps": "Steps",
|
"steps": "Steps",
|
||||||
@ -1640,6 +1641,22 @@
|
|||||||
"layers_one": "Layer",
|
"layers_one": "Layer",
|
||||||
"layers_other": "Layers"
|
"layers_other": "Layers"
|
||||||
},
|
},
|
||||||
|
"upscaling": {
|
||||||
|
"creativity": "Creativity",
|
||||||
|
"currentImageSize": "Current Image Size",
|
||||||
|
"outputImageSize": "Output Image Size",
|
||||||
|
"sharpness": "Sharpness",
|
||||||
|
"structure": "Structure",
|
||||||
|
"tiledVAE": "Tiled VAE",
|
||||||
|
"toInstall": "to install",
|
||||||
|
"upscaleModel": "Upcale Model",
|
||||||
|
"visit": "Visit",
|
||||||
|
"warningNoMainModel": "a model",
|
||||||
|
"warningNoTile": "a {{base_model}} tile controlnet required by this feature",
|
||||||
|
"warningNoTileOrUpscaleModel": "an upscaler model and {{base_model}} tile controlnet required by this feature",
|
||||||
|
"warningNoUpscaleModel": "an upscaler model required by this feature",
|
||||||
|
"x": "x"
|
||||||
|
},
|
||||||
"ui": {
|
"ui": {
|
||||||
"tabs": {
|
"tabs": {
|
||||||
"generation": "Generation",
|
"generation": "Generation",
|
||||||
|
@ -86,7 +86,7 @@ addGalleryOffsetChangedListener(startAppListening);
|
|||||||
addEnqueueRequestedCanvasListener(startAppListening);
|
addEnqueueRequestedCanvasListener(startAppListening);
|
||||||
addEnqueueRequestedNodes(startAppListening);
|
addEnqueueRequestedNodes(startAppListening);
|
||||||
addEnqueueRequestedLinear(startAppListening);
|
addEnqueueRequestedLinear(startAppListening);
|
||||||
addEnqueueRequestedUpscale(startAppListening)
|
addEnqueueRequestedUpscale(startAppListening);
|
||||||
addAnyEnqueuedListener(startAppListening);
|
addAnyEnqueuedListener(startAppListening);
|
||||||
addBatchEnqueuedListener(startAppListening);
|
addBatchEnqueuedListener(startAppListening);
|
||||||
|
|
||||||
|
@ -10,13 +10,11 @@ export const addEnqueueRequestedUpscale = (startAppListening: AppStartListening)
|
|||||||
predicate: (action): action is ReturnType<typeof enqueueRequested> =>
|
predicate: (action): action is ReturnType<typeof enqueueRequested> =>
|
||||||
enqueueRequested.match(action) && action.payload.tabName === 'upscaling',
|
enqueueRequested.match(action) && action.payload.tabName === 'upscaling',
|
||||||
effect: async (action, { getState, dispatch }) => {
|
effect: async (action, { getState, dispatch }) => {
|
||||||
|
|
||||||
const state = getState();
|
const state = getState();
|
||||||
const { shouldShowProgressInViewer } = state.ui;
|
const { shouldShowProgressInViewer } = state.ui;
|
||||||
const { prepend } = action.payload;
|
const { prepend } = action.payload;
|
||||||
|
|
||||||
|
const graph = await buildMultidiffusionUpscsaleGraph(state);
|
||||||
const graph = await buildMultidiffusionUpscsaleGraph(state)
|
|
||||||
|
|
||||||
const batchConfig = prepareLinearUIBatch(state, graph, prepend);
|
const batchConfig = prepareLinearUIBatch(state, graph, prepend);
|
||||||
|
|
||||||
|
@ -94,7 +94,7 @@ export const addImageUploadedFulfilledListener = (startAppListening: AppStartLis
|
|||||||
dispatch(upscaleInitialImageChanged(imageDTO));
|
dispatch(upscaleInitialImageChanged(imageDTO));
|
||||||
toast({
|
toast({
|
||||||
...DEFAULT_UPLOADED_TOAST,
|
...DEFAULT_UPLOADED_TOAST,
|
||||||
description: "set as upscale initial image",
|
description: 'set as upscale initial image',
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,12 @@ import { forEach } from 'lodash-es';
|
|||||||
import type { Logger } from 'roarr';
|
import type { Logger } from 'roarr';
|
||||||
import { modelConfigsAdapterSelectors, modelsApi } from 'services/api/endpoints/models';
|
import { modelConfigsAdapterSelectors, modelsApi } from 'services/api/endpoints/models';
|
||||||
import type { AnyModelConfig } from 'services/api/types';
|
import type { AnyModelConfig } from 'services/api/types';
|
||||||
import { isNonRefinerMainModelConfig, isRefinerMainModelModelConfig, isSpandrelImageToImageModelConfig, isVAEModelConfig } from 'services/api/types';
|
import {
|
||||||
|
isNonRefinerMainModelConfig,
|
||||||
|
isRefinerMainModelModelConfig,
|
||||||
|
isSpandrelImageToImageModelConfig,
|
||||||
|
isVAEModelConfig,
|
||||||
|
} from 'services/api/types';
|
||||||
|
|
||||||
export const addModelsLoadedListener = (startAppListening: AppStartListening) => {
|
export const addModelsLoadedListener = (startAppListening: AppStartListening) => {
|
||||||
startAppListening({
|
startAppListening({
|
||||||
@ -193,10 +198,9 @@ const handleSpandrelImageToImageModels: ModelHandler = (models, state, dispatch,
|
|||||||
|
|
||||||
const firstModel = upscaleModels[0];
|
const firstModel = upscaleModels[0];
|
||||||
if (firstModel) {
|
if (firstModel) {
|
||||||
dispatch(upscaleModelChanged(firstModel))
|
dispatch(upscaleModelChanged(firstModel));
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch(upscaleModelChanged(null))
|
dispatch(upscaleModelChanged(null));
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -70,7 +70,7 @@ const allReducers = {
|
|||||||
[controlLayersSlice.name]: undoable(controlLayersSlice.reducer, controlLayersUndoableConfig),
|
[controlLayersSlice.name]: undoable(controlLayersSlice.reducer, controlLayersUndoableConfig),
|
||||||
[workflowSettingsSlice.name]: workflowSettingsSlice.reducer,
|
[workflowSettingsSlice.name]: workflowSettingsSlice.reducer,
|
||||||
[api.reducerPath]: api.reducer,
|
[api.reducerPath]: api.reducer,
|
||||||
[upscaleSlice.name]: upscaleSlice.reducer
|
[upscaleSlice.name]: upscaleSlice.reducer,
|
||||||
};
|
};
|
||||||
|
|
||||||
const rootReducer = combineReducers(allReducers);
|
const rootReducer = combineReducers(allReducers);
|
||||||
@ -116,7 +116,7 @@ const persistConfigs: { [key in keyof typeof allReducers]?: PersistConfig } = {
|
|||||||
[hrfPersistConfig.name]: hrfPersistConfig,
|
[hrfPersistConfig.name]: hrfPersistConfig,
|
||||||
[controlLayersPersistConfig.name]: controlLayersPersistConfig,
|
[controlLayersPersistConfig.name]: controlLayersPersistConfig,
|
||||||
[workflowSettingsPersistConfig.name]: workflowSettingsPersistConfig,
|
[workflowSettingsPersistConfig.name]: workflowSettingsPersistConfig,
|
||||||
[upscalePersistConfig.name]: upscalePersistConfig
|
[upscalePersistConfig.name]: upscalePersistConfig,
|
||||||
};
|
};
|
||||||
|
|
||||||
const unserialize: UnserializeFunction = (data, key) => {
|
const unserialize: UnserializeFunction = (data, key) => {
|
||||||
|
@ -41,9 +41,19 @@ const createSelector = (templates: Templates) =>
|
|||||||
selectDynamicPromptsSlice,
|
selectDynamicPromptsSlice,
|
||||||
selectControlLayersSlice,
|
selectControlLayersSlice,
|
||||||
activeTabNameSelector,
|
activeTabNameSelector,
|
||||||
selectUpscalelice
|
selectUpscalelice,
|
||||||
],
|
],
|
||||||
(controlAdapters, generation, system, nodes, workflowSettings, dynamicPrompts, controlLayers, activeTabName, upscale) => {
|
(
|
||||||
|
controlAdapters,
|
||||||
|
generation,
|
||||||
|
system,
|
||||||
|
nodes,
|
||||||
|
workflowSettings,
|
||||||
|
dynamicPrompts,
|
||||||
|
controlLayers,
|
||||||
|
activeTabName,
|
||||||
|
upscale
|
||||||
|
) => {
|
||||||
const { model } = generation;
|
const { model } = generation;
|
||||||
const { size } = controlLayers.present;
|
const { size } = controlLayers.present;
|
||||||
const { positivePrompt } = controlLayers.present;
|
const { positivePrompt } = controlLayers.present;
|
||||||
@ -196,16 +206,16 @@ const createSelector = (templates: Templates) =>
|
|||||||
reasons.push({ prefix, content });
|
reasons.push({ prefix, content });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else if (activeTabName === "upscaling") {
|
} else if (activeTabName === 'upscaling') {
|
||||||
if (!upscale.upscaleInitialImage) {
|
if (!upscale.upscaleInitialImage) {
|
||||||
reasons.push({ content: "No Initial image" })
|
reasons.push({ content: 'No Initial image' });
|
||||||
}
|
}
|
||||||
if (!upscale.upscaleModel) {
|
if (!upscale.upscaleModel) {
|
||||||
reasons.push({ content: "No upscale model selected" })
|
reasons.push({ content: 'No upscale model selected' });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!upscale.tileControlnetModel) {
|
if (!upscale.tileControlnetModel) {
|
||||||
reasons.push({ content: "No valid tile controlnet available" })
|
reasons.push({ content: 'No valid tile controlnet available' });
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Handling for all other tabs
|
// Handling for all other tabs
|
||||||
|
@ -91,8 +91,6 @@ export type SelectForCompareDropData = BaseDropData & {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export type TypesafeDroppableData =
|
export type TypesafeDroppableData =
|
||||||
| CurrentImageDropData
|
| CurrentImageDropData
|
||||||
| ControlAdapterDropData
|
| ControlAdapterDropData
|
||||||
@ -166,11 +164,11 @@ interface DragEvent {
|
|||||||
over: TypesafeOver | null;
|
over: TypesafeOver | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DragStartEvent extends Pick<DragEvent, 'active'> { }
|
export interface DragStartEvent extends Pick<DragEvent, 'active'> {}
|
||||||
interface DragMoveEvent extends DragEvent { }
|
interface DragMoveEvent extends DragEvent {}
|
||||||
interface DragOverEvent extends DragMoveEvent { }
|
interface DragOverEvent extends DragMoveEvent {}
|
||||||
export interface DragEndEvent extends DragEvent { }
|
export interface DragEndEvent extends DragEvent {}
|
||||||
interface DragCancelEvent extends DragEndEvent { }
|
interface DragCancelEvent extends DragEndEvent {}
|
||||||
|
|
||||||
export interface DndContextTypesafeProps
|
export interface DndContextTypesafeProps
|
||||||
extends Omit<DndContextProps, 'onDragStart' | 'onDragMove' | 'onDragOver' | 'onDragEnd' | 'onDragCancel'> {
|
extends Omit<DndContextProps, 'onDragStart' | 'onDragMove' | 'onDragOver' | 'onDragEnd' | 'onDragCancel'> {
|
||||||
|
@ -192,7 +192,7 @@ const SingleSelectionMenuItems = (props: SingleSelectionMenuItemsProps) => {
|
|||||||
</MenuItem>
|
</MenuItem>
|
||||||
)}
|
)}
|
||||||
<MenuItem icon={<PiShareFatBold />} onClickCapture={handleSendToUpscale} id="send-to-upscale">
|
<MenuItem icon={<PiShareFatBold />} onClickCapture={handleSendToUpscale} id="send-to-upscale">
|
||||||
Send to upscale
|
{t('parameters.sendToUpscale')}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
<MenuDivider />
|
<MenuDivider />
|
||||||
<MenuItem icon={<PiFoldersBold />} onClickCapture={handleChangeBoard}>
|
<MenuItem icon={<PiFoldersBold />} onClickCapture={handleChangeBoard}>
|
||||||
|
@ -4,97 +4,103 @@ import { Graph } from 'features/nodes/util/graph/generation/Graph';
|
|||||||
import { isParamESRGANModelName } from 'features/parameters/store/postprocessingSlice';
|
import { isParamESRGANModelName } from 'features/parameters/store/postprocessingSlice';
|
||||||
import { assert } from 'tsafe';
|
import { assert } from 'tsafe';
|
||||||
|
|
||||||
import { CLIP_SKIP, CONTROL_NET_COLLECT, ESRGAN, IMAGE_TO_LATENTS, LATENTS_TO_IMAGE, MAIN_MODEL_LOADER, NEGATIVE_CONDITIONING, NOISE, POSITIVE_CONDITIONING, RESIZE, SDXL_MODEL_LOADER, TILED_MULTI_DIFFUSION_DENOISE_LATENTS, UNSHARP_MASK, VAE_LOADER } from './constants';
|
import {
|
||||||
|
CLIP_SKIP,
|
||||||
|
CONTROL_NET_COLLECT,
|
||||||
|
ESRGAN,
|
||||||
|
IMAGE_TO_LATENTS,
|
||||||
|
LATENTS_TO_IMAGE,
|
||||||
|
MAIN_MODEL_LOADER,
|
||||||
|
NEGATIVE_CONDITIONING,
|
||||||
|
NOISE,
|
||||||
|
POSITIVE_CONDITIONING,
|
||||||
|
RESIZE,
|
||||||
|
SDXL_MODEL_LOADER,
|
||||||
|
TILED_MULTI_DIFFUSION_DENOISE_LATENTS,
|
||||||
|
UNSHARP_MASK,
|
||||||
|
VAE_LOADER,
|
||||||
|
} from './constants';
|
||||||
import { addLoRAs } from './generation/addLoRAs';
|
import { addLoRAs } from './generation/addLoRAs';
|
||||||
import { addSDXLLoRas } from './generation/addSDXLLoRAs';
|
import { addSDXLLoRas } from './generation/addSDXLLoRAs';
|
||||||
import { getBoardField, getSDXLStylePrompts } from './graphBuilderUtils';
|
import { getBoardField, getSDXLStylePrompts } from './graphBuilderUtils';
|
||||||
|
|
||||||
|
|
||||||
export const buildMultidiffusionUpscsaleGraph = async (state: RootState): Promise<GraphType> => {
|
export const buildMultidiffusionUpscsaleGraph = async (state: RootState): Promise<GraphType> => {
|
||||||
const {
|
const { model, cfgScale: cfg_scale, scheduler, steps, vaePrecision, seed, vae } = state.generation;
|
||||||
model,
|
|
||||||
cfgScale: cfg_scale,
|
|
||||||
scheduler,
|
|
||||||
steps,
|
|
||||||
vaePrecision,
|
|
||||||
seed,
|
|
||||||
vae,
|
|
||||||
} = state.generation;
|
|
||||||
const { positivePrompt, negativePrompt } = state.controlLayers.present;
|
const { positivePrompt, negativePrompt } = state.controlLayers.present;
|
||||||
const { upscaleModel, upscaleInitialImage, sharpness, structure, creativity, tiledVAE, scale, tileControlnetModel } = state.upscale;
|
const { upscaleModel, upscaleInitialImage, sharpness, structure, creativity, tiledVAE, scale, tileControlnetModel } =
|
||||||
|
state.upscale;
|
||||||
|
|
||||||
assert(model, 'No model found in state');
|
assert(model, 'No model found in state');
|
||||||
assert(upscaleModel, 'No upscale model found in state');
|
assert(upscaleModel, 'No upscale model found in state');
|
||||||
assert(upscaleInitialImage, 'No initial image found in state');
|
assert(upscaleInitialImage, 'No initial image found in state');
|
||||||
assert(isParamESRGANModelName(upscaleModel.name), "Model must be valid upscale model")
|
assert(isParamESRGANModelName(upscaleModel.name), 'Model must be valid upscale model');
|
||||||
assert(scale, 'Scale is required')
|
assert(scale, 'Scale is required');
|
||||||
assert(tileControlnetModel, "Tile controlnet is required")
|
assert(tileControlnetModel, 'Tile controlnet is required');
|
||||||
|
|
||||||
const g = new Graph()
|
const g = new Graph();
|
||||||
|
|
||||||
const unsharpMaskNode1 = g.addNode({
|
const unsharpMaskNode1 = g.addNode({
|
||||||
id: `${UNSHARP_MASK}_1`,
|
id: `${UNSHARP_MASK}_1`,
|
||||||
type: 'unsharp_mask',
|
type: 'unsharp_mask',
|
||||||
image: upscaleInitialImage,
|
image: upscaleInitialImage,
|
||||||
radius: 2,
|
radius: 2,
|
||||||
strength: ((sharpness + 10) * 3.75) + 25
|
strength: (sharpness + 10) * 3.75 + 25,
|
||||||
})
|
});
|
||||||
|
|
||||||
const upscaleNode = g.addNode({
|
const upscaleNode = g.addNode({
|
||||||
id: ESRGAN,
|
id: ESRGAN,
|
||||||
type: 'esrgan',
|
type: 'esrgan',
|
||||||
model_name: upscaleModel.name,
|
model_name: upscaleModel.name,
|
||||||
tile_size: 500
|
tile_size: 500,
|
||||||
})
|
});
|
||||||
|
|
||||||
g.addEdge(unsharpMaskNode1, 'image', upscaleNode, 'image')
|
g.addEdge(unsharpMaskNode1, 'image', upscaleNode, 'image');
|
||||||
|
|
||||||
const unsharpMaskNode2 = g.addNode({
|
const unsharpMaskNode2 = g.addNode({
|
||||||
id: `${UNSHARP_MASK}_2`,
|
id: `${UNSHARP_MASK}_2`,
|
||||||
type: 'unsharp_mask',
|
type: 'unsharp_mask',
|
||||||
radius: 2,
|
radius: 2,
|
||||||
strength: 50
|
strength: 50,
|
||||||
})
|
});
|
||||||
|
|
||||||
g.addEdge(upscaleNode, 'image', unsharpMaskNode2, 'image',)
|
g.addEdge(upscaleNode, 'image', unsharpMaskNode2, 'image');
|
||||||
|
|
||||||
const resizeNode = g.addNode({
|
const resizeNode = g.addNode({
|
||||||
id: RESIZE,
|
id: RESIZE,
|
||||||
type: 'img_resize',
|
type: 'img_resize',
|
||||||
width: ((upscaleInitialImage.width * scale) / 8) * 8,
|
width: ((upscaleInitialImage.width * scale) / 8) * 8,
|
||||||
height: ((upscaleInitialImage.height * scale) / 8) * 8,
|
height: ((upscaleInitialImage.height * scale) / 8) * 8,
|
||||||
resample_mode: "lanczos",
|
resample_mode: 'lanczos',
|
||||||
})
|
});
|
||||||
|
|
||||||
g.addEdge(unsharpMaskNode2, 'image', resizeNode, "image")
|
g.addEdge(unsharpMaskNode2, 'image', resizeNode, 'image');
|
||||||
|
|
||||||
const noiseNode = g.addNode({
|
const noiseNode = g.addNode({
|
||||||
id: NOISE,
|
id: NOISE,
|
||||||
type: "noise",
|
type: 'noise',
|
||||||
seed,
|
seed,
|
||||||
})
|
});
|
||||||
|
|
||||||
g.addEdge(resizeNode, 'width', noiseNode, "width")
|
g.addEdge(resizeNode, 'width', noiseNode, 'width');
|
||||||
g.addEdge(resizeNode, 'height', noiseNode, "height")
|
g.addEdge(resizeNode, 'height', noiseNode, 'height');
|
||||||
|
|
||||||
const i2lNode = g.addNode({
|
const i2lNode = g.addNode({
|
||||||
id: IMAGE_TO_LATENTS,
|
id: IMAGE_TO_LATENTS,
|
||||||
type: "i2l",
|
type: 'i2l',
|
||||||
fp32: vaePrecision === "fp32",
|
fp32: vaePrecision === 'fp32',
|
||||||
tiled: tiledVAE
|
tiled: tiledVAE,
|
||||||
})
|
});
|
||||||
|
|
||||||
g.addEdge(resizeNode, 'image', i2lNode, "image")
|
g.addEdge(resizeNode, 'image', i2lNode, 'image');
|
||||||
|
|
||||||
const l2iNode = g.addNode({
|
const l2iNode = g.addNode({
|
||||||
type: "l2i",
|
type: 'l2i',
|
||||||
id: LATENTS_TO_IMAGE,
|
id: LATENTS_TO_IMAGE,
|
||||||
fp32: vaePrecision === "fp32",
|
fp32: vaePrecision === 'fp32',
|
||||||
tiled: tiledVAE,
|
tiled: tiledVAE,
|
||||||
board: getBoardField(state),
|
board: getBoardField(state),
|
||||||
is_intermediate: false,
|
is_intermediate: false,
|
||||||
|
});
|
||||||
})
|
|
||||||
|
|
||||||
const tiledMultidiffusionNode = g.addNode({
|
const tiledMultidiffusionNode = g.addNode({
|
||||||
id: TILED_MULTI_DIFFUSION_DENOISE_LATENTS,
|
id: TILED_MULTI_DIFFUSION_DENOISE_LATENTS,
|
||||||
@ -105,26 +111,28 @@ export const buildMultidiffusionUpscsaleGraph = async (state: RootState): Promis
|
|||||||
steps,
|
steps,
|
||||||
cfg_scale,
|
cfg_scale,
|
||||||
scheduler,
|
scheduler,
|
||||||
denoising_start: (((creativity * -1) + 10) * 4.99) / 100,
|
denoising_start: ((creativity * -1 + 10) * 4.99) / 100,
|
||||||
denoising_end: 1
|
denoising_end: 1,
|
||||||
});
|
});
|
||||||
|
|
||||||
let posCondNode; let negCondNode; let modelNode;
|
let posCondNode;
|
||||||
|
let negCondNode;
|
||||||
|
let modelNode;
|
||||||
|
|
||||||
if (model.base === "sdxl") {
|
if (model.base === 'sdxl') {
|
||||||
const { positiveStylePrompt, negativeStylePrompt } = getSDXLStylePrompts(state);
|
const { positiveStylePrompt, negativeStylePrompt } = getSDXLStylePrompts(state);
|
||||||
|
|
||||||
posCondNode = g.addNode({
|
posCondNode = g.addNode({
|
||||||
type: 'sdxl_compel_prompt',
|
type: 'sdxl_compel_prompt',
|
||||||
id: POSITIVE_CONDITIONING,
|
id: POSITIVE_CONDITIONING,
|
||||||
prompt: positivePrompt,
|
prompt: positivePrompt,
|
||||||
style: positiveStylePrompt
|
style: positiveStylePrompt,
|
||||||
});
|
});
|
||||||
negCondNode = g.addNode({
|
negCondNode = g.addNode({
|
||||||
type: 'sdxl_compel_prompt',
|
type: 'sdxl_compel_prompt',
|
||||||
id: NEGATIVE_CONDITIONING,
|
id: NEGATIVE_CONDITIONING,
|
||||||
prompt: negativePrompt,
|
prompt: negativePrompt,
|
||||||
style: negativeStylePrompt
|
style: negativeStylePrompt,
|
||||||
});
|
});
|
||||||
modelNode = g.addNode({
|
modelNode = g.addNode({
|
||||||
type: 'sdxl_model_loader',
|
type: 'sdxl_model_loader',
|
||||||
@ -163,64 +171,59 @@ export const buildMultidiffusionUpscsaleGraph = async (state: RootState): Promis
|
|||||||
addLoRAs(state, g, tiledMultidiffusionNode, modelNode, null, clipSkipNode, posCondNode, negCondNode);
|
addLoRAs(state, g, tiledMultidiffusionNode, modelNode, null, clipSkipNode, posCondNode, negCondNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
let vaeNode;
|
let vaeNode;
|
||||||
if (vae) {
|
if (vae) {
|
||||||
vaeNode = g.addNode({
|
vaeNode = g.addNode({
|
||||||
id: VAE_LOADER,
|
id: VAE_LOADER,
|
||||||
type: "vae_loader",
|
type: 'vae_loader',
|
||||||
vae_model: vae
|
vae_model: vae,
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
g.addEdge(vaeNode || modelNode, "vae", i2lNode, "vae")
|
g.addEdge(vaeNode || modelNode, 'vae', i2lNode, 'vae');
|
||||||
g.addEdge(vaeNode || modelNode, "vae", l2iNode, "vae")
|
g.addEdge(vaeNode || modelNode, 'vae', l2iNode, 'vae');
|
||||||
|
|
||||||
|
g.addEdge(noiseNode, 'noise', tiledMultidiffusionNode, 'noise');
|
||||||
g.addEdge(noiseNode, "noise", tiledMultidiffusionNode, "noise")
|
g.addEdge(i2lNode, 'latents', tiledMultidiffusionNode, 'latents');
|
||||||
g.addEdge(i2lNode, "latents", tiledMultidiffusionNode, "latents")
|
|
||||||
g.addEdge(posCondNode, 'conditioning', tiledMultidiffusionNode, 'positive_conditioning');
|
g.addEdge(posCondNode, 'conditioning', tiledMultidiffusionNode, 'positive_conditioning');
|
||||||
g.addEdge(negCondNode, 'conditioning', tiledMultidiffusionNode, 'negative_conditioning');
|
g.addEdge(negCondNode, 'conditioning', tiledMultidiffusionNode, 'negative_conditioning');
|
||||||
g.addEdge(modelNode, "unet", tiledMultidiffusionNode, "unet")
|
g.addEdge(modelNode, 'unet', tiledMultidiffusionNode, 'unet');
|
||||||
g.addEdge(tiledMultidiffusionNode, "latents", l2iNode, "latents")
|
g.addEdge(tiledMultidiffusionNode, 'latents', l2iNode, 'latents');
|
||||||
|
|
||||||
|
|
||||||
const controlnetNode1 = g.addNode({
|
const controlnetNode1 = g.addNode({
|
||||||
id: 'controlnet_1',
|
id: 'controlnet_1',
|
||||||
type: "controlnet",
|
type: 'controlnet',
|
||||||
control_model: tileControlnetModel,
|
control_model: tileControlnetModel,
|
||||||
control_mode: "balanced",
|
control_mode: 'balanced',
|
||||||
resize_mode: "just_resize",
|
resize_mode: 'just_resize',
|
||||||
control_weight: ((((structure + 10) * 0.025) + 0.3) * 0.013) + 0.35,
|
control_weight: ((structure + 10) * 0.025 + 0.3) * 0.013 + 0.35,
|
||||||
begin_step_percent: 0,
|
begin_step_percent: 0,
|
||||||
end_step_percent: ((structure + 10) * 0.025) + 0.3
|
end_step_percent: (structure + 10) * 0.025 + 0.3,
|
||||||
})
|
});
|
||||||
|
|
||||||
g.addEdge(resizeNode, "image", controlnetNode1, "image")
|
g.addEdge(resizeNode, 'image', controlnetNode1, 'image');
|
||||||
|
|
||||||
const controlnetNode2 = g.addNode({
|
const controlnetNode2 = g.addNode({
|
||||||
id: "controlnet_2",
|
id: 'controlnet_2',
|
||||||
type: "controlnet",
|
type: 'controlnet',
|
||||||
control_model: tileControlnetModel,
|
control_model: tileControlnetModel,
|
||||||
control_mode: "balanced",
|
control_mode: 'balanced',
|
||||||
resize_mode: "just_resize",
|
resize_mode: 'just_resize',
|
||||||
control_weight: (((structure + 10) * 0.025) + 0.3) * 0.013,
|
control_weight: ((structure + 10) * 0.025 + 0.3) * 0.013,
|
||||||
begin_step_percent: ((structure + 10) * 0.025) + 0.3,
|
begin_step_percent: (structure + 10) * 0.025 + 0.3,
|
||||||
end_step_percent: 0.8
|
end_step_percent: 0.8,
|
||||||
})
|
});
|
||||||
|
|
||||||
g.addEdge(resizeNode, "image", controlnetNode2, "image")
|
g.addEdge(resizeNode, 'image', controlnetNode2, 'image');
|
||||||
|
|
||||||
const collectNode = g.addNode({
|
const collectNode = g.addNode({
|
||||||
id: CONTROL_NET_COLLECT,
|
id: CONTROL_NET_COLLECT,
|
||||||
type: "collect",
|
type: 'collect',
|
||||||
})
|
});
|
||||||
g.addEdge(controlnetNode1, "control", collectNode, "item")
|
g.addEdge(controlnetNode1, 'control', collectNode, 'item');
|
||||||
g.addEdge(controlnetNode2, "control", collectNode, "item")
|
g.addEdge(controlnetNode2, 'control', collectNode, 'item');
|
||||||
|
|
||||||
g.addEdge(collectNode, "collection", tiledMultidiffusionNode, "control")
|
|
||||||
|
|
||||||
|
g.addEdge(collectNode, 'collection', tiledMultidiffusionNode, 'control');
|
||||||
|
|
||||||
return g.getGraph();
|
return g.getGraph();
|
||||||
|
};
|
||||||
}
|
|
||||||
|
@ -53,8 +53,8 @@ export const PROMPT_REGION_NEGATIVE_COND_PREFIX = 'prompt_region_negative_cond';
|
|||||||
export const PROMPT_REGION_POSITIVE_COND_INVERTED_PREFIX = 'prompt_region_positive_cond_inverted';
|
export const PROMPT_REGION_POSITIVE_COND_INVERTED_PREFIX = 'prompt_region_positive_cond_inverted';
|
||||||
export const POSITIVE_CONDITIONING_COLLECT = 'positive_conditioning_collect';
|
export const POSITIVE_CONDITIONING_COLLECT = 'positive_conditioning_collect';
|
||||||
export const NEGATIVE_CONDITIONING_COLLECT = 'negative_conditioning_collect';
|
export const NEGATIVE_CONDITIONING_COLLECT = 'negative_conditioning_collect';
|
||||||
export const UNSHARP_MASK = 'unsharp_mask'
|
export const UNSHARP_MASK = 'unsharp_mask';
|
||||||
export const TILED_MULTI_DIFFUSION_DENOISE_LATENTS = "tiled_multi_diffusion_denoise_latents"
|
export const TILED_MULTI_DIFFUSION_DENOISE_LATENTS = 'tiled_multi_diffusion_denoise_latents';
|
||||||
|
|
||||||
// friendly graph ids
|
// friendly graph ids
|
||||||
export const CONTROL_LAYERS_GRAPH = 'control_layers_graph';
|
export const CONTROL_LAYERS_GRAPH = 'control_layers_graph';
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { CompositeNumberInput, CompositeSlider, FormControl, FormLabel } from '@invoke-ai/ui-library';
|
import { CompositeNumberInput, CompositeSlider, FormControl, FormLabel } from '@invoke-ai/ui-library';
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
|
import { creativityChanged } from 'features/parameters/store/upscaleSlice';
|
||||||
import { memo, useCallback, useMemo } from 'react';
|
import { memo, useCallback, useMemo } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { creativityChanged } from '../../store/upscaleSlice';
|
|
||||||
|
|
||||||
const ParamCreativity = () => {
|
const ParamCreativity = () => {
|
||||||
const creativity = useAppSelector((s) => s.upscale.creativity);
|
const creativity = useAppSelector((s) => s.upscale.creativity);
|
||||||
@ -25,7 +25,7 @@ const ParamCreativity = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<FormLabel>Creativity</FormLabel>
|
<FormLabel>{t('upscaling.creativity')}</FormLabel>
|
||||||
<CompositeSlider
|
<CompositeSlider
|
||||||
value={creativity}
|
value={creativity}
|
||||||
defaultValue={initial}
|
defaultValue={initial}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { CompositeNumberInput, CompositeSlider, FormControl, FormLabel } from '@invoke-ai/ui-library';
|
import { CompositeNumberInput, CompositeSlider, FormControl, FormLabel } from '@invoke-ai/ui-library';
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
|
import { sharpnessChanged } from 'features/parameters/store/upscaleSlice';
|
||||||
import { memo, useCallback, useMemo } from 'react';
|
import { memo, useCallback, useMemo } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { sharpnessChanged } from '../../store/upscaleSlice';
|
|
||||||
|
|
||||||
const ParamSharpness = () => {
|
const ParamSharpness = () => {
|
||||||
const sharpness = useAppSelector((s) => s.upscale.sharpness);
|
const sharpness = useAppSelector((s) => s.upscale.sharpness);
|
||||||
@ -25,7 +25,7 @@ const ParamSharpness = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<FormLabel>Sharpness</FormLabel>
|
<FormLabel>{t('upscaling.sharpness')}</FormLabel>
|
||||||
<CompositeSlider
|
<CompositeSlider
|
||||||
value={sharpness}
|
value={sharpness}
|
||||||
defaultValue={initial}
|
defaultValue={initial}
|
||||||
|
@ -31,7 +31,7 @@ const ParamSpandrelModel = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<FormControl orientation="vertical">
|
<FormControl orientation="vertical">
|
||||||
<FormLabel>Upscale Model</FormLabel>
|
<FormLabel>{t('upscaling.upscaleModel')}</FormLabel>
|
||||||
<Combobox
|
<Combobox
|
||||||
value={value}
|
value={value}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { CompositeNumberInput, CompositeSlider, FormControl, FormLabel } from '@invoke-ai/ui-library';
|
import { CompositeNumberInput, CompositeSlider, FormControl, FormLabel } from '@invoke-ai/ui-library';
|
||||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
|
import { structureChanged } from 'features/parameters/store/upscaleSlice';
|
||||||
import { memo, useCallback, useMemo } from 'react';
|
import { memo, useCallback, useMemo } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { structureChanged } from '../../store/upscaleSlice';
|
|
||||||
|
|
||||||
const ParamStructure = () => {
|
const ParamStructure = () => {
|
||||||
const structure = useAppSelector((s) => s.upscale.structure);
|
const structure = useAppSelector((s) => s.upscale.structure);
|
||||||
@ -25,7 +25,7 @@ const ParamStructure = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<FormLabel>Structure</FormLabel>
|
<FormLabel>{t('upscaling.structure')}</FormLabel>
|
||||||
<CompositeSlider
|
<CompositeSlider
|
||||||
value={structure}
|
value={structure}
|
||||||
defaultValue={initial}
|
defaultValue={initial}
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
import { FormControl, FormLabel, Switch } from '@invoke-ai/ui-library';
|
import { FormControl, FormLabel, Switch } from '@invoke-ai/ui-library';
|
||||||
import { useAppDispatch, useAppSelector } from '../../../../app/store/storeHooks';
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
|
import { tiledVAEChanged } from 'features/parameters/store/upscaleSlice';
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import { tiledVAEChanged } from '../../store/upscaleSlice';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
export const ParamTiledVAEToggle = () => {
|
export const ParamTiledVAEToggle = () => {
|
||||||
|
const { t } = useTranslation();
|
||||||
const tiledVAE = useAppSelector((s) => s.upscale.tiledVAE);
|
const tiledVAE = useAppSelector((s) => s.upscale.tiledVAE);
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
|
|
||||||
@ -16,7 +18,7 @@ export const ParamTiledVAEToggle = () => {
|
|||||||
return (
|
return (
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Switch isChecked={tiledVAE} onChange={handleChange} />
|
<Switch isChecked={tiledVAE} onChange={handleChange} />
|
||||||
<FormLabel>Tiled VAE</FormLabel>
|
<FormLabel>{t('upscaling.tiledVAE')}</FormLabel>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -6,7 +6,6 @@ import { useMemo } from 'react';
|
|||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import type { ImageDTO } from 'services/api/types';
|
import type { ImageDTO } from 'services/api/types';
|
||||||
|
|
||||||
|
|
||||||
const getUpscaledPixels = (imageDTO?: ImageDTO, maxUpscalePixels?: number) => {
|
const getUpscaledPixels = (imageDTO?: ImageDTO, maxUpscalePixels?: number) => {
|
||||||
if (!imageDTO) {
|
if (!imageDTO) {
|
||||||
return;
|
return;
|
||||||
|
@ -10,7 +10,7 @@ import type {
|
|||||||
ParameterSeed,
|
ParameterSeed,
|
||||||
ParameterSteps,
|
ParameterSteps,
|
||||||
ParameterStrength,
|
ParameterStrength,
|
||||||
ParameterVAEModel
|
ParameterVAEModel,
|
||||||
} from 'features/parameters/types/parameterSchemas';
|
} from 'features/parameters/types/parameterSchemas';
|
||||||
import type { RgbaColor } from 'react-colorful';
|
import type { RgbaColor } from 'react-colorful';
|
||||||
|
|
||||||
|
@ -4,7 +4,6 @@ import type { PersistConfig, RootState } from 'app/store/store';
|
|||||||
import type { ParameterSpandrelImageToImageModel } from 'features/parameters/types/parameterSchemas';
|
import type { ParameterSpandrelImageToImageModel } from 'features/parameters/types/parameterSchemas';
|
||||||
import type { ControlNetModelConfig, ImageDTO } from 'services/api/types';
|
import type { ControlNetModelConfig, ImageDTO } from 'services/api/types';
|
||||||
|
|
||||||
|
|
||||||
interface UpscaleState {
|
interface UpscaleState {
|
||||||
_version: 1;
|
_version: 1;
|
||||||
upscaleModel: ParameterSpandrelImageToImageModel | null;
|
upscaleModel: ParameterSpandrelImageToImageModel | null;
|
||||||
@ -14,7 +13,7 @@ interface UpscaleState {
|
|||||||
creativity: number;
|
creativity: number;
|
||||||
tiledVAE: boolean;
|
tiledVAE: boolean;
|
||||||
scale: number | null;
|
scale: number | null;
|
||||||
tileControlnetModel: ControlNetModelConfig | null
|
tileControlnetModel: ControlNetModelConfig | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const initialUpscaleState: UpscaleState = {
|
const initialUpscaleState: UpscaleState = {
|
||||||
@ -26,7 +25,7 @@ const initialUpscaleState: UpscaleState = {
|
|||||||
creativity: 0,
|
creativity: 0,
|
||||||
tiledVAE: false,
|
tiledVAE: false,
|
||||||
scale: null,
|
scale: null,
|
||||||
tileControlnetModel: null
|
tileControlnetModel: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const upscaleSlice = createSlice({
|
export const upscaleSlice = createSlice({
|
||||||
@ -68,7 +67,16 @@ export const upscaleSlice = createSlice({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const { upscaleModelChanged, upscaleInitialImageChanged, tiledVAEChanged, structureChanged, creativityChanged, sharpnessChanged, scaleChanged, tileControlnetModelChanged } = upscaleSlice.actions;
|
export const {
|
||||||
|
upscaleModelChanged,
|
||||||
|
upscaleInitialImageChanged,
|
||||||
|
tiledVAEChanged,
|
||||||
|
structureChanged,
|
||||||
|
creativityChanged,
|
||||||
|
sharpnessChanged,
|
||||||
|
scaleChanged,
|
||||||
|
tileControlnetModelChanged,
|
||||||
|
} = upscaleSlice.actions;
|
||||||
|
|
||||||
export const selectUpscalelice = (state: RootState) => state.upscale;
|
export const selectUpscalelice = (state: RootState) => state.upscale;
|
||||||
|
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
import { Flex, Link, Text } from '@invoke-ai/ui-library';
|
import { Flex, Link, Text } from '@invoke-ai/ui-library';
|
||||||
import { useAppDispatch, useAppSelector } from '../../../../app/store/storeHooks';
|
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||||
import { useControlNetModels } from '../../../../services/api/hooks/modelsByType';
|
import { tileControlnetModelChanged } from 'features/parameters/store/upscaleSlice';
|
||||||
|
import { MODEL_TYPE_SHORT_MAP } from 'features/parameters/types/constants';
|
||||||
|
import { setActiveTab } from 'features/ui/store/uiSlice';
|
||||||
import { useCallback, useEffect, useMemo } from 'react';
|
import { useCallback, useEffect, useMemo } from 'react';
|
||||||
import { tileControlnetModelChanged } from '../../../parameters/store/upscaleSlice';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { MODEL_TYPE_SHORT_MAP } from '../../../parameters/types/constants';
|
import { useControlNetModels } from 'services/api/hooks/modelsByType';
|
||||||
import { setActiveTab } from '../../../ui/store/uiSlice';
|
|
||||||
|
|
||||||
export const MultidiffusionWarning = () => {
|
export const MultidiffusionWarning = () => {
|
||||||
|
const { t } = useTranslation();
|
||||||
const model = useAppSelector((s) => s.generation.model);
|
const model = useAppSelector((s) => s.generation.model);
|
||||||
const { tileControlnetModel, upscaleModel } = useAppSelector((s) => s.upscale);
|
const { tileControlnetModel, upscaleModel } = useAppSelector((s) => s.upscale);
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
@ -23,19 +25,18 @@ export const MultidiffusionWarning = () => {
|
|||||||
|
|
||||||
const warningText = useMemo(() => {
|
const warningText = useMemo(() => {
|
||||||
if (!model) {
|
if (!model) {
|
||||||
return `a model`;
|
return t('upscaling.warningNoMainModel');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!upscaleModel && !tileControlnetModel) {
|
if (!upscaleModel && !tileControlnetModel) {
|
||||||
return `an upscaler model and ${MODEL_TYPE_SHORT_MAP[model.base]} tile controlnet`;
|
return t('upscaling.warningNoTileOrUpscaleModel', { base_model: MODEL_TYPE_SHORT_MAP[model.base] });
|
||||||
}
|
}
|
||||||
if (!upscaleModel) {
|
if (!upscaleModel) {
|
||||||
return 'an upscaler model';
|
return t('upscaling.warningNoUpscaleModel');
|
||||||
}
|
}
|
||||||
if (!tileControlnetModel) {
|
if (!tileControlnetModel) {
|
||||||
return `a ${MODEL_TYPE_SHORT_MAP[model.base]} tile controlnet`;
|
return t('upscaling.warningNoTile', { base_model: MODEL_TYPE_SHORT_MAP[model.base] });
|
||||||
}
|
}
|
||||||
}, [model?.base, upscaleModel, tileControlnetModel]);
|
}, [model, upscaleModel, tileControlnetModel, t]);
|
||||||
|
|
||||||
const handleGoToModelManager = useCallback(() => {
|
const handleGoToModelManager = useCallback(() => {
|
||||||
dispatch(setActiveTab('models'));
|
dispatch(setActiveTab('models'));
|
||||||
@ -46,13 +47,13 @@ export const MultidiffusionWarning = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex bg="error.500" borderRadius={'base'} padding="2" direction="column">
|
<Flex bg="error.500" borderRadius="base" padding="2" direction="column">
|
||||||
<Text fontSize="xs" textAlign="center" display={'inline-block'}>
|
<Text fontSize="xs" textAlign="center" display="inline-block">
|
||||||
Visit{' '}
|
{t('upscaling.visit')}{' '}
|
||||||
<Link fontWeight="bold" onClick={handleGoToModelManager}>
|
<Link fontWeight="bold" onClick={handleGoToModelManager}>
|
||||||
Model Manager
|
{t('modelManager.modelManager')}
|
||||||
</Link>{' '}
|
</Link>{' '}
|
||||||
to install {warningText} required by this feature
|
{t('upscaling.toInstall')} {warningText}.
|
||||||
</Text>
|
</Text>
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
|
@ -12,9 +12,9 @@ import { useStandaloneAccordionToggle } from 'features/settingsAccordions/hooks/
|
|||||||
import { memo } from 'react';
|
import { memo } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
import { MultidiffusionWarning } from './MultidiffusionWarning';
|
||||||
import { UpscaleInitialImage } from './UpscaleInitialImage';
|
import { UpscaleInitialImage } from './UpscaleInitialImage';
|
||||||
import { UpscaleSizeDetails } from './UpscaleSizeDetails';
|
import { UpscaleSizeDetails } from './UpscaleSizeDetails';
|
||||||
import { MultidiffusionWarning } from './MultidiffusionWarning';
|
|
||||||
|
|
||||||
const selector = createMemoizedSelector([selectUpscalelice], (upscale) => {
|
const selector = createMemoizedSelector([selectUpscalelice], (upscale) => {
|
||||||
const badges: string[] = [];
|
const badges: string[] = [];
|
||||||
|
@ -1,15 +1,17 @@
|
|||||||
import { Flex, Text } from '@invoke-ai/ui-library';
|
import { Flex, Text } from '@invoke-ai/ui-library';
|
||||||
import { useAppSelector } from 'app/store/storeHooks';
|
import { useAppSelector } from 'app/store/storeHooks';
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
export const UpscaleSizeDetails = () => {
|
export const UpscaleSizeDetails = () => {
|
||||||
|
const { t } = useTranslation();
|
||||||
const { upscaleInitialImage, scale } = useAppSelector((s) => s.upscale);
|
const { upscaleInitialImage, scale } = useAppSelector((s) => s.upscale);
|
||||||
|
|
||||||
const outputSizeText = useMemo(() => {
|
const outputSizeText = useMemo(() => {
|
||||||
if (upscaleInitialImage && scale) {
|
if (upscaleInitialImage && scale) {
|
||||||
return `Output image size: ${upscaleInitialImage.width * scale} x ${upscaleInitialImage.height * scale}`;
|
return `${t('upscaling.outputImageSize')}: ${upscaleInitialImage.width * scale} ${t('upscaling.x')} ${upscaleInitialImage.height * scale}`;
|
||||||
}
|
}
|
||||||
}, [upscaleInitialImage, scale]);
|
}, [upscaleInitialImage, scale, t]);
|
||||||
|
|
||||||
if (!outputSizeText || !upscaleInitialImage) {
|
if (!outputSizeText || !upscaleInitialImage) {
|
||||||
return <></>;
|
return <></>;
|
||||||
@ -18,7 +20,7 @@ export const UpscaleSizeDetails = () => {
|
|||||||
return (
|
return (
|
||||||
<Flex direction="column">
|
<Flex direction="column">
|
||||||
<Text variant="subtext" fontWeight="bold">
|
<Text variant="subtext" fontWeight="bold">
|
||||||
Current image size: {upscaleInitialImage.width} x {upscaleInitialImage.height}
|
{t('upscaling.currentImageSize')}: {upscaleInitialImage.width} {t('upscaling.x')} {upscaleInitialImage.height}
|
||||||
</Text>
|
</Text>
|
||||||
<Text variant="subtext" fontWeight="bold">
|
<Text variant="subtext" fontWeight="bold">
|
||||||
{outputSizeText}
|
{outputSizeText}
|
||||||
|
Loading…
Reference in New Issue
Block a user