diff --git a/invokeai/frontend/web/src/features/nodes/store/types.ts b/invokeai/frontend/web/src/features/nodes/store/types.ts index 2074f1f342..2f3acc694b 100644 --- a/invokeai/frontend/web/src/features/nodes/store/types.ts +++ b/invokeai/frontend/web/src/features/nodes/store/types.ts @@ -23,6 +23,7 @@ export type NodesState = { nodeOpacity: number; shouldSnapToGrid: boolean; shouldColorEdges: boolean; + shouldShowEdgeLabels: boolean; selectedNodes: string[]; selectedEdges: string[]; nodeExecutionStates: Record; diff --git a/invokeai/frontend/web/src/features/nodes/util/graph/addRegionalPromptsToGraph.ts b/invokeai/frontend/web/src/features/nodes/util/graph/addRegionalPromptsToGraph.ts new file mode 100644 index 0000000000..ebe2e74da5 --- /dev/null +++ b/invokeai/frontend/web/src/features/nodes/util/graph/addRegionalPromptsToGraph.ts @@ -0,0 +1,151 @@ +import { getStore } from 'app/store/nanostores/store'; +import type { RootState } from 'app/store/store'; +import { + NEGATIVE_CONDITIONING_COLLECT, + POSITIVE_CONDITIONING, + POSITIVE_CONDITIONING_COLLECT, + PROMPT_REGION_COND_PREFIX, + PROMPT_REGION_MASK_PREFIX, +} from 'features/nodes/util/graph/constants'; +import { getRegionalPromptLayerBlobs } from 'features/regionalPrompts/util/getLayerBlobs'; +import { size } from 'lodash-es'; +import { imagesApi } from 'services/api/endpoints/images'; +import type { CollectInvocation, Edge, NonNullableGraph, S } from 'services/api/types'; +import { assert } from 'tsafe'; + +export const addRegionalPromptsToGraph = async (state: RootState, graph: NonNullableGraph, denoiseNodeId: string) => { + const { dispatch } = getStore(); + const isSDXL = state.generation.model?.base === 'sdxl'; + const layers = state.regionalPrompts.layers + .filter((l) => l.kind === 'promptRegionLayer') // We only want the prompt region layers + .filter((l) => l.isVisible); // Only visible layers are rendered on the canvas + + const layerIds = layers.map((l) => l.id); // We only need the IDs + + const blobs = await getRegionalPromptLayerBlobs(layerIds); + + console.log('blobs', blobs, 'layerIds', layerIds); + assert(size(blobs) === size(layerIds), 'Mismatch between layer IDs and blobs'); + + // Set up the conditioning collectors + const posCondCollectNode: CollectInvocation = { + id: POSITIVE_CONDITIONING_COLLECT, + type: 'collect', + }; + const negCondCollectNode: CollectInvocation = { + id: NEGATIVE_CONDITIONING_COLLECT, + type: 'collect', + }; + graph.nodes[POSITIVE_CONDITIONING_COLLECT] = posCondCollectNode; + graph.nodes[NEGATIVE_CONDITIONING_COLLECT] = negCondCollectNode; + + // Re-route the denoise node's OG conditioning inputs to the collect nodes + const newEdges: Edge[] = []; + for (const edge of graph.edges) { + if (edge.destination.node_id === denoiseNodeId && edge.destination.field === 'positive_conditioning') { + newEdges.push({ + source: edge.source, + destination: { + node_id: POSITIVE_CONDITIONING_COLLECT, + field: 'item', + }, + }); + } else if (edge.destination.node_id === denoiseNodeId && edge.destination.field === 'negative_conditioning') { + newEdges.push({ + source: edge.source, + destination: { + node_id: NEGATIVE_CONDITIONING_COLLECT, + field: 'item', + }, + }); + } else { + newEdges.push(edge); + } + } + graph.edges = newEdges; + + // Connect collectors to the denoise nodes - must happen _after_ rerouting else you get cycles + graph.edges.push({ + source: { + node_id: POSITIVE_CONDITIONING_COLLECT, + field: 'collection', + }, + destination: { + node_id: denoiseNodeId, + field: 'positive_conditioning', + }, + }); + graph.edges.push({ + source: { + node_id: NEGATIVE_CONDITIONING_COLLECT, + field: 'collection', + }, + destination: { + node_id: denoiseNodeId, + field: 'negative_conditioning', + }, + }); + + // Remove the global prompt + (graph.nodes[POSITIVE_CONDITIONING] as S['SDXLCompelPromptInvocation'] | S['CompelInvocation']).prompt = ''; + + // Upload the blobs to the backend, add each to graph + for (const [layerId, blob] of Object.entries(blobs)) { + const layer = layers.find((l) => l.id === layerId); + assert(layer, `Layer ${layerId} not found`); + + const id = `${PROMPT_REGION_MASK_PREFIX}_${layerId}`; + const file = new File([blob], `${id}.png`, { type: 'image/png' }); + const req = dispatch( + imagesApi.endpoints.uploadImage.initiate({ file, image_category: 'mask', is_intermediate: true }) + ); + req.reset(); + + // TODO: this will raise an error + const { image_name } = await req.unwrap(); + + const alphaMaskToTensorNode: S['AlphaMaskToTensorInvocation'] = { + id, + type: 'alpha_mask_to_tensor', + image: { + image_name, + }, + }; + graph.nodes[id] = alphaMaskToTensorNode; + + // Create the conditioning nodes for each region - different handling for SDXL + + // TODO: negative prompt + const regionalCondNodeId = `${PROMPT_REGION_COND_PREFIX}_${layerId}`; + + if (isSDXL) { + graph.nodes[regionalCondNodeId] = { + type: 'sdxl_compel_prompt', + id: regionalCondNodeId, + prompt: layer.prompt, + }; + } else { + graph.nodes[regionalCondNodeId] = { + type: 'compel', + id: regionalCondNodeId, + prompt: layer.prompt, + }; + } + graph.edges.push({ + source: { node_id: id, field: 'mask' }, + destination: { node_id: regionalCondNodeId, field: 'mask' }, + }); + graph.edges.push({ + source: { node_id: regionalCondNodeId, field: 'conditioning' }, + destination: { node_id: posCondCollectNode.id, field: 'item' }, + }); + for (const edge of graph.edges) { + if (edge.destination.node_id === POSITIVE_CONDITIONING && edge.destination.field !== 'prompt') { + graph.edges.push({ + source: edge.source, + destination: { node_id: regionalCondNodeId, field: edge.destination.field }, + }); + } + } + } +}; diff --git a/invokeai/frontend/web/src/features/nodes/util/graph/buildLinearBatchConfig.ts b/invokeai/frontend/web/src/features/nodes/util/graph/buildLinearBatchConfig.ts index 9fcc6afaa0..51619e7e38 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graph/buildLinearBatchConfig.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graph/buildLinearBatchConfig.ts @@ -1,11 +1,11 @@ import { NUMPY_RAND_MAX } from 'app/constants'; import type { RootState } from 'app/store/store'; import { generateSeeds } from 'common/util/generateSeeds'; -import { range } from 'lodash-es'; +import { range, some } from 'lodash-es'; import type { components } from 'services/api/schema'; import type { Batch, BatchConfig, NonNullableGraph } from 'services/api/types'; -import { CANVAS_COHERENCE_NOISE, METADATA, NOISE, POSITIVE_CONDITIONING } from './constants'; +import { CANVAS_COHERENCE_NOISE, METADATA, NOISE, POSITIVE_CONDITIONING, PROMPT_REGION_MASK_PREFIX } from './constants'; import { getHasMetadata, removeMetadata } from './metadata'; export const prepareLinearUIBatch = (state: RootState, graph: NonNullableGraph, prepend: boolean): BatchConfig => { @@ -86,23 +86,27 @@ export const prepareLinearUIBatch = (state: RootState, graph: NonNullableGraph, const extendedPrompts = seedBehaviour === 'PER_PROMPT' ? range(iterations).flatMap(() => prompts) : prompts; - // zipped batch of prompts - if (graph.nodes[POSITIVE_CONDITIONING]) { - firstBatchDatumList.push({ - node_path: POSITIVE_CONDITIONING, - field_name: 'prompt', - items: extendedPrompts, - }); - } + const hasRegionalPrompts = some(graph.nodes, (n) => n.id.startsWith(PROMPT_REGION_MASK_PREFIX)); - // add to metadata - if (getHasMetadata(graph)) { - removeMetadata(graph, 'positive_prompt'); - firstBatchDatumList.push({ - node_path: METADATA, - field_name: 'positive_prompt', - items: extendedPrompts, - }); + if (!hasRegionalPrompts) { + // zipped batch of prompts + if (graph.nodes[POSITIVE_CONDITIONING]) { + firstBatchDatumList.push({ + node_path: POSITIVE_CONDITIONING, + field_name: 'prompt', + items: extendedPrompts, + }); + } + + // add to metadata + if (getHasMetadata(graph)) { + removeMetadata(graph, 'positive_prompt'); + firstBatchDatumList.push({ + node_path: METADATA, + field_name: 'positive_prompt', + items: extendedPrompts, + }); + } } if (shouldConcatSDXLStylePrompt && model?.base === 'sdxl') { diff --git a/invokeai/frontend/web/src/features/nodes/util/graph/buildLinearSDXLTextToImageGraph.ts b/invokeai/frontend/web/src/features/nodes/util/graph/buildLinearSDXLTextToImageGraph.ts index 7dadb8c3e9..b0b1140d5b 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graph/buildLinearSDXLTextToImageGraph.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graph/buildLinearSDXLTextToImageGraph.ts @@ -1,6 +1,7 @@ import { logger } from 'app/logging/logger'; import type { RootState } from 'app/store/store'; import { fetchModelConfigWithTypeGuard } from 'features/metadata/util/modelFetchingHelpers'; +import { addRegionalPromptsToGraph } from 'features/nodes/util/graph/addRegionalPromptsToGraph'; import { isNonRefinerMainModelConfig, type NonNullableGraph } from 'services/api/types'; import { addControlNetToLinearGraph } from './addControlNetToLinearGraph'; @@ -273,6 +274,8 @@ export const buildLinearSDXLTextToImageGraph = async (state: RootState): Promise await addT2IAdaptersToLinearGraph(state, graph, SDXL_DENOISE_LATENTS); + await addRegionalPromptsToGraph(state, graph, SDXL_DENOISE_LATENTS); + // NSFW & watermark - must be last thing added to graph if (state.system.shouldUseNSFWChecker) { // must add before watermarker! diff --git a/invokeai/frontend/web/src/features/nodes/util/graph/constants.ts b/invokeai/frontend/web/src/features/nodes/util/graph/constants.ts index 984f8ae7d6..adde745b4a 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graph/constants.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graph/constants.ts @@ -46,6 +46,10 @@ export const SDXL_REFINER_DENOISE_LATENTS = 'sdxl_refiner_denoise_latents'; export const SDXL_REFINER_INPAINT_CREATE_MASK = 'refiner_inpaint_create_mask'; export const SEAMLESS = 'seamless'; export const SDXL_REFINER_SEAMLESS = 'refiner_seamless'; +export const PROMPT_REGION_MASK_PREFIX = 'prompt_region_mask'; +export const PROMPT_REGION_COND_PREFIX = 'prompt_region_cond'; +export const POSITIVE_CONDITIONING_COLLECT = 'positive_conditioning_collect'; +export const NEGATIVE_CONDITIONING_COLLECT = 'negative_conditioning_collect'; // friendly graph ids export const TEXT_TO_IMAGE_GRAPH = 'text_to_image_graph'; diff --git a/invokeai/frontend/web/src/features/regionalPrompts/components/RegionalPromptsEditor.tsx b/invokeai/frontend/web/src/features/regionalPrompts/components/RegionalPromptsEditor.tsx index 22a6d4f223..cf3614dbec 100644 --- a/invokeai/frontend/web/src/features/regionalPrompts/components/RegionalPromptsEditor.tsx +++ b/invokeai/frontend/web/src/features/regionalPrompts/components/RegionalPromptsEditor.tsx @@ -18,13 +18,13 @@ const selectLayerIdsReversed = createMemoizedSelector(selectRegionalPromptsSlice ); const debugBlobs = () => { - getRegionalPromptLayerBlobs(true); + getRegionalPromptLayerBlobs(undefined, true); }; export const RegionalPromptsEditor = memo(() => { const layerIdsReversed = useAppSelector(selectLayerIdsReversed); return ( - + diff --git a/invokeai/frontend/web/src/features/regionalPrompts/util/getLayerBlobs.ts b/invokeai/frontend/web/src/features/regionalPrompts/util/getLayerBlobs.ts index 362f100941..114f68a478 100644 --- a/invokeai/frontend/web/src/features/regionalPrompts/util/getLayerBlobs.ts +++ b/invokeai/frontend/web/src/features/regionalPrompts/util/getLayerBlobs.ts @@ -1,4 +1,3 @@ -import { getStore } from 'app/store/nanostores/store'; import openBase64ImageInTab from 'common/util/openBase64ImageInTab'; import { blobToDataURL } from 'features/canvas/util/blobToDataURL'; import { selectPromptLayerObjectGroup } from 'features/regionalPrompts/components/LayerComponent'; @@ -7,16 +6,24 @@ import Konva from 'konva'; import { assert } from 'tsafe'; /** - * Get the blobs of all regional prompt layers. + * Get the blobs of all regional prompt layers. Only visible layers are returned. + * @param layerIds The IDs of the layers to get blobs for. If not provided, all regional prompt layers are used. * @param preview Whether to open a new tab displaying each layer. * @returns A map of layer IDs to blobs. */ -export const getRegionalPromptLayerBlobs = async (preview: boolean = false): Promise> => { - const state = getStore().getState(); +export const getRegionalPromptLayerBlobs = async ( + layerIds?: string[], + preview: boolean = false +): Promise> => { const stage = getStage(); // This automatically omits layers that are not rendered. Rendering is controlled by the layer's `isVisible` flag in redux. - const regionalPromptLayers = stage.getLayers().filter((l) => l.name() === REGIONAL_PROMPT_LAYER_NAME); + const regionalPromptLayers = stage.getLayers().filter((l) => { + console.log(l.name(), l.id()) + const isRegionalPromptLayer = l.name() === REGIONAL_PROMPT_LAYER_NAME; + const isRequestedLayerId = layerIds ? layerIds.includes(l.id()) : true; + return isRegionalPromptLayer && isRequestedLayerId; + }); // We need to reconstruct each layer to only output the desired data. This logic mirrors the logic in // `getKonvaLayerBbox()` in `invokeai/frontend/web/src/features/regionalPrompts/util/bbox.ts` @@ -48,14 +55,13 @@ export const getRegionalPromptLayerBlobs = async (preview: boolean = false): Pro }, }); }); - blobs[layer.id()] = blob; if (preview) { const base64 = await blobToDataURL(blob); - const prompt = state.regionalPrompts.layers.find((l) => l.id === layer.id())?.prompt; - openBase64ImageInTab([{ base64, caption: prompt ?? '' }]); + openBase64ImageInTab([{ base64, caption: layer.id() }]); } layerClone.destroy(); + blobs[layer.id()] = blob; } return blobs; diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/TextToImageTab.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/TextToImageTab.tsx index fd38514edc..00a747e6b8 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/TextToImageTab.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/TextToImageTab.tsx @@ -1,13 +1,26 @@ -import { Box, Flex } from '@invoke-ai/ui-library'; +import { Box, Tab, TabList, TabPanel, TabPanels, Tabs } from '@invoke-ai/ui-library'; import CurrentImageDisplay from 'features/gallery/components/CurrentImage/CurrentImageDisplay'; +import { RegionalPromptsEditor } from 'features/regionalPrompts/components/RegionalPromptsEditor'; import { memo } from 'react'; const TextToImageTab = () => { return ( - - - - + + + + Viewer + Regional Prompts + + + + + + + + + + + ); }; diff --git a/invokeai/frontend/web/src/services/api/schema.ts b/invokeai/frontend/web/src/services/api/schema.ts index 7157de227b..a4bb9462c9 100644 --- a/invokeai/frontend/web/src/services/api/schema.ts +++ b/invokeai/frontend/web/src/services/api/schema.ts @@ -584,6 +584,43 @@ export type components = { */ type: "add"; }; + /** + * Alpha Mask to Tensor + * @description Convert a mask image to a tensor. Opaque regions are 1 and transparent regions are 0. + */ + AlphaMaskToTensorInvocation: { + /** + * Id + * @description The id of this instance of an invocation. Must be unique among all instances of invocations. + */ + id: string; + /** + * Is Intermediate + * @description Whether or not this is an intermediate invocation. + * @default false + */ + is_intermediate?: boolean; + /** + * Use Cache + * @description Whether or not to use the cache + * @default true + */ + use_cache?: boolean; + /** @description The mask image to convert. */ + image?: components["schemas"]["ImageField"]; + /** + * Invert + * @description Whether to invert the mask. + * @default false + */ + invert?: boolean; + /** + * type + * @default alpha_mask_to_tensor + * @constant + */ + type: "alpha_mask_to_tensor"; + }; /** * AppConfig * @description App Config Response @@ -4125,7 +4162,7 @@ export type components = { * @description The nodes in this graph */ nodes: { - [key: string]: components["schemas"]["CalculateImageTilesMinimumOverlapInvocation"] | components["schemas"]["ScaleLatentsInvocation"] | components["schemas"]["IterateInvocation"] | components["schemas"]["ImageChannelInvocation"] | components["schemas"]["RangeOfSizeInvocation"] | components["schemas"]["AddInvocation"] | components["schemas"]["CoreMetadataInvocation"] | components["schemas"]["T2IAdapterInvocation"] | components["schemas"]["RandomRangeInvocation"] | components["schemas"]["LineartImageProcessorInvocation"] | components["schemas"]["DenoiseLatentsInvocation"] | components["schemas"]["CollectInvocation"] | components["schemas"]["MergeMetadataInvocation"] | components["schemas"]["FreeUInvocation"] | components["schemas"]["ZoeDepthImageProcessorInvocation"] | components["schemas"]["RandomFloatInvocation"] | components["schemas"]["ConditioningInvocation"] | components["schemas"]["NoiseInvocation"] | components["schemas"]["StringReplaceInvocation"] | components["schemas"]["ImageCropInvocation"] | components["schemas"]["ImageBlurInvocation"] | components["schemas"]["SDXLRefinerModelLoaderInvocation"] | components["schemas"]["MlsdImageProcessorInvocation"] | components["schemas"]["DWOpenposeImageProcessorInvocation"] | components["schemas"]["ControlNetInvocation"] | components["schemas"]["TileResamplerProcessorInvocation"] | components["schemas"]["SchedulerInvocation"] | components["schemas"]["LatentsCollectionInvocation"] | components["schemas"]["BooleanInvocation"] | components["schemas"]["StringInvocation"] | components["schemas"]["ImageNSFWBlurInvocation"] | components["schemas"]["CLIPSkipInvocation"] | components["schemas"]["PairTileImageInvocation"] | components["schemas"]["FaceMaskInvocation"] | components["schemas"]["CenterPadCropInvocation"] | components["schemas"]["InfillColorInvocation"] | components["schemas"]["BooleanCollectionInvocation"] | components["schemas"]["FloatCollectionInvocation"] | components["schemas"]["MaskFromIDInvocation"] | components["schemas"]["StringJoinThreeInvocation"] | components["schemas"]["IntegerCollectionInvocation"] | components["schemas"]["CompelInvocation"] | components["schemas"]["ColorCorrectInvocation"] | components["schemas"]["StringSplitNegInvocation"] | components["schemas"]["FaceIdentifierInvocation"] | components["schemas"]["CanvasPasteBackInvocation"] | components["schemas"]["LineartAnimeImageProcessorInvocation"] | components["schemas"]["MultiplyInvocation"] | components["schemas"]["ColorInvocation"] | components["schemas"]["NormalbaeImageProcessorInvocation"] | components["schemas"]["CropLatentsCoreInvocation"] | components["schemas"]["MaskFromAlphaInvocation"] | components["schemas"]["StringCollectionInvocation"] | components["schemas"]["ImageLerpInvocation"] | components["schemas"]["InfillTileInvocation"] | components["schemas"]["VAELoaderInvocation"] | components["schemas"]["SDXLModelLoaderInvocation"] | components["schemas"]["DepthAnythingImageProcessorInvocation"] | components["schemas"]["CreateDenoiseMaskInvocation"] | components["schemas"]["FloatLinearRangeInvocation"] | components["schemas"]["LoRALoaderInvocation"] | components["schemas"]["MetadataInvocation"] | components["schemas"]["MediapipeFaceProcessorInvocation"] | components["schemas"]["FloatInvocation"] | components["schemas"]["ESRGANInvocation"] | components["schemas"]["CannyImageProcessorInvocation"] | components["schemas"]["TileToPropertiesInvocation"] | components["schemas"]["ImageToLatentsInvocation"] | components["schemas"]["ImageInvocation"] | components["schemas"]["ImageScaleInvocation"] | components["schemas"]["MidasDepthImageProcessorInvocation"] | components["schemas"]["CalculateImageTilesInvocation"] | components["schemas"]["FloatToIntegerInvocation"] | components["schemas"]["MergeTilesToImageInvocation"] | components["schemas"]["ImageInverseLerpInvocation"] | components["schemas"]["ImageHueAdjustmentInvocation"] | components["schemas"]["PromptsFromFileInvocation"] | components["schemas"]["SegmentAnythingProcessorInvocation"] | components["schemas"]["DivideInvocation"] | components["schemas"]["InfillPatchMatchInvocation"] | components["schemas"]["FaceOffInvocation"] | components["schemas"]["ImageResizeInvocation"] | components["schemas"]["RangeInvocation"] | components["schemas"]["ImageChannelOffsetInvocation"] | components["schemas"]["IdealSizeInvocation"] | components["schemas"]["RoundInvocation"] | components["schemas"]["ImageMultiplyInvocation"] | components["schemas"]["MetadataItemInvocation"] | components["schemas"]["StepParamEasingInvocation"] | components["schemas"]["SDXLLoRALoaderInvocation"] | components["schemas"]["ResizeLatentsInvocation"] | components["schemas"]["ImageWatermarkInvocation"] | components["schemas"]["PidiImageProcessorInvocation"] | components["schemas"]["SeamlessModeInvocation"] | components["schemas"]["ImageCollectionInvocation"] | components["schemas"]["LaMaInfillInvocation"] | components["schemas"]["CvInpaintInvocation"] | components["schemas"]["LatentsInvocation"] | components["schemas"]["RectangleMaskInvocation"] | components["schemas"]["ConditioningCollectionInvocation"] | components["schemas"]["ImageChannelMultiplyInvocation"] | components["schemas"]["ColorMapImageProcessorInvocation"] | components["schemas"]["LatentsToImageInvocation"] | components["schemas"]["ShowImageInvocation"] | components["schemas"]["LeresImageProcessorInvocation"] | components["schemas"]["UnsharpMaskInvocation"] | components["schemas"]["SDXLCompelPromptInvocation"] | components["schemas"]["IntegerInvocation"] | components["schemas"]["StringJoinInvocation"] | components["schemas"]["BlankImageInvocation"] | components["schemas"]["IntegerMathInvocation"] | components["schemas"]["CV2InfillInvocation"] | components["schemas"]["DynamicPromptInvocation"] | components["schemas"]["ContentShuffleImageProcessorInvocation"] | components["schemas"]["CreateGradientMaskInvocation"] | components["schemas"]["HedImageProcessorInvocation"] | components["schemas"]["CalculateImageTilesEvenSplitInvocation"] | components["schemas"]["RandomIntInvocation"] | components["schemas"]["MaskEdgeInvocation"] | components["schemas"]["IPAdapterInvocation"] | components["schemas"]["StringSplitInvocation"] | components["schemas"]["ImagePasteInvocation"] | components["schemas"]["FloatMathInvocation"] | components["schemas"]["SaveImageInvocation"] | components["schemas"]["MainModelLoaderInvocation"] | components["schemas"]["SubtractInvocation"] | components["schemas"]["BlendLatentsInvocation"] | components["schemas"]["MaskCombineInvocation"] | components["schemas"]["ImageConvertInvocation"] | components["schemas"]["SDXLRefinerCompelPromptInvocation"]; + [key: string]: components["schemas"]["LatentsCollectionInvocation"] | components["schemas"]["FloatLinearRangeInvocation"] | components["schemas"]["MaskFromIDInvocation"] | components["schemas"]["ColorCorrectInvocation"] | components["schemas"]["RangeInvocation"] | components["schemas"]["MainModelLoaderInvocation"] | components["schemas"]["ContentShuffleImageProcessorInvocation"] | components["schemas"]["NormalbaeImageProcessorInvocation"] | components["schemas"]["PromptsFromFileInvocation"] | components["schemas"]["StringSplitNegInvocation"] | components["schemas"]["CV2InfillInvocation"] | components["schemas"]["SaveImageInvocation"] | components["schemas"]["StringCollectionInvocation"] | components["schemas"]["BlendLatentsInvocation"] | components["schemas"]["ImageToLatentsInvocation"] | components["schemas"]["RangeOfSizeInvocation"] | components["schemas"]["LineartImageProcessorInvocation"] | components["schemas"]["LeresImageProcessorInvocation"] | components["schemas"]["StringReplaceInvocation"] | components["schemas"]["ConditioningCollectionInvocation"] | components["schemas"]["InfillColorInvocation"] | components["schemas"]["RandomRangeInvocation"] | components["schemas"]["CalculateImageTilesInvocation"] | components["schemas"]["TileToPropertiesInvocation"] | components["schemas"]["DynamicPromptInvocation"] | components["schemas"]["SegmentAnythingProcessorInvocation"] | components["schemas"]["MetadataInvocation"] | components["schemas"]["ControlNetInvocation"] | components["schemas"]["ImageHueAdjustmentInvocation"] | components["schemas"]["ImageInverseLerpInvocation"] | components["schemas"]["IntegerMathInvocation"] | components["schemas"]["MidasDepthImageProcessorInvocation"] | components["schemas"]["ImageMultiplyInvocation"] | components["schemas"]["FloatMathInvocation"] | components["schemas"]["CanvasPasteBackInvocation"] | components["schemas"]["ImageChannelInvocation"] | components["schemas"]["RandomFloatInvocation"] | components["schemas"]["SDXLLoRALoaderInvocation"] | components["schemas"]["IntegerCollectionInvocation"] | components["schemas"]["MultiplyInvocation"] | components["schemas"]["FloatCollectionInvocation"] | components["schemas"]["RectangleMaskInvocation"] | components["schemas"]["ImageLerpInvocation"] | components["schemas"]["AddInvocation"] | components["schemas"]["BooleanInvocation"] | components["schemas"]["ImageInvocation"] | components["schemas"]["CoreMetadataInvocation"] | components["schemas"]["ESRGANInvocation"] | components["schemas"]["ZoeDepthImageProcessorInvocation"] | components["schemas"]["StringInvocation"] | components["schemas"]["T2IAdapterInvocation"] | components["schemas"]["LatentsToImageInvocation"] | components["schemas"]["SDXLRefinerCompelPromptInvocation"] | components["schemas"]["FloatToIntegerInvocation"] | components["schemas"]["InfillTileInvocation"] | components["schemas"]["CalculateImageTilesMinimumOverlapInvocation"] | components["schemas"]["NoiseInvocation"] | components["schemas"]["PidiImageProcessorInvocation"] | components["schemas"]["ImageConvertInvocation"] | components["schemas"]["SeamlessModeInvocation"] | components["schemas"]["CollectInvocation"] | components["schemas"]["CLIPSkipInvocation"] | components["schemas"]["SubtractInvocation"] | components["schemas"]["MaskFromAlphaInvocation"] | components["schemas"]["LoRALoaderInvocation"] | components["schemas"]["CompelInvocation"] | components["schemas"]["LaMaInfillInvocation"] | components["schemas"]["DenoiseLatentsInvocation"] | components["schemas"]["MetadataItemInvocation"] | components["schemas"]["SDXLCompelPromptInvocation"] | components["schemas"]["CreateGradientMaskInvocation"] | components["schemas"]["MergeTilesToImageInvocation"] | components["schemas"]["AlphaMaskToTensorInvocation"] | components["schemas"]["MlsdImageProcessorInvocation"] | components["schemas"]["ConditioningInvocation"] | components["schemas"]["DWOpenposeImageProcessorInvocation"] | components["schemas"]["ImageScaleInvocation"] | components["schemas"]["SDXLRefinerModelLoaderInvocation"] | components["schemas"]["IdealSizeInvocation"] | components["schemas"]["IterateInvocation"] | components["schemas"]["CreateDenoiseMaskInvocation"] | components["schemas"]["ImageBlurInvocation"] | components["schemas"]["CvInpaintInvocation"] | components["schemas"]["LineartAnimeImageProcessorInvocation"] | components["schemas"]["MediapipeFaceProcessorInvocation"] | components["schemas"]["PairTileImageInvocation"] | components["schemas"]["HedImageProcessorInvocation"] | components["schemas"]["StringJoinInvocation"] | components["schemas"]["ImageCollectionInvocation"] | components["schemas"]["FreeUInvocation"] | components["schemas"]["RandomIntInvocation"] | components["schemas"]["StringJoinThreeInvocation"] | components["schemas"]["DepthAnythingImageProcessorInvocation"] | components["schemas"]["ImagePasteInvocation"] | components["schemas"]["ImageNSFWBlurInvocation"] | components["schemas"]["FaceMaskInvocation"] | components["schemas"]["IPAdapterInvocation"] | components["schemas"]["ImageResizeInvocation"] | components["schemas"]["MaskCombineInvocation"] | components["schemas"]["StringSplitInvocation"] | components["schemas"]["FloatInvocation"] | components["schemas"]["CannyImageProcessorInvocation"] | components["schemas"]["SchedulerInvocation"] | components["schemas"]["IntegerInvocation"] | components["schemas"]["VAELoaderInvocation"] | components["schemas"]["CenterPadCropInvocation"] | components["schemas"]["RoundInvocation"] | components["schemas"]["ImageWatermarkInvocation"] | components["schemas"]["ImageChannelOffsetInvocation"] | components["schemas"]["BooleanCollectionInvocation"] | components["schemas"]["FaceOffInvocation"] | components["schemas"]["ColorMapImageProcessorInvocation"] | components["schemas"]["ColorInvocation"] | components["schemas"]["ImageCropInvocation"] | components["schemas"]["ScaleLatentsInvocation"] | components["schemas"]["DivideInvocation"] | components["schemas"]["UnsharpMaskInvocation"] | components["schemas"]["ImageChannelMultiplyInvocation"] | components["schemas"]["FaceIdentifierInvocation"] | components["schemas"]["CropLatentsCoreInvocation"] | components["schemas"]["SDXLModelLoaderInvocation"] | components["schemas"]["CalculateImageTilesEvenSplitInvocation"] | components["schemas"]["ResizeLatentsInvocation"] | components["schemas"]["BlankImageInvocation"] | components["schemas"]["StepParamEasingInvocation"] | components["schemas"]["MergeMetadataInvocation"] | components["schemas"]["ShowImageInvocation"] | components["schemas"]["InfillPatchMatchInvocation"] | components["schemas"]["MaskEdgeInvocation"] | components["schemas"]["TileResamplerProcessorInvocation"] | components["schemas"]["LatentsInvocation"]; }; /** * Edges @@ -4162,7 +4199,7 @@ export type components = { * @description The results of node executions */ results: { - [key: string]: components["schemas"]["ColorCollectionOutput"] | components["schemas"]["NoiseOutput"] | components["schemas"]["IntegerCollectionOutput"] | components["schemas"]["T2IAdapterOutput"] | components["schemas"]["ColorOutput"] | components["schemas"]["SDXLLoRALoaderOutput"] | components["schemas"]["ConditioningCollectionOutput"] | components["schemas"]["CLIPSkipInvocationOutput"] | components["schemas"]["IPAdapterOutput"] | components["schemas"]["String2Output"] | components["schemas"]["MaskOutput"] | components["schemas"]["FloatOutput"] | components["schemas"]["ModelLoaderOutput"] | components["schemas"]["StringOutput"] | components["schemas"]["ImageCollectionOutput"] | components["schemas"]["CLIPOutput"] | components["schemas"]["IntegerOutput"] | components["schemas"]["BooleanCollectionOutput"] | components["schemas"]["GradientMaskOutput"] | components["schemas"]["ControlOutput"] | components["schemas"]["UNetOutput"] | components["schemas"]["SeamlessModeOutput"] | components["schemas"]["StringPosNegOutput"] | components["schemas"]["FaceOffOutput"] | components["schemas"]["FloatCollectionOutput"] | components["schemas"]["CollectInvocationOutput"] | components["schemas"]["MetadataOutput"] | components["schemas"]["SchedulerOutput"] | components["schemas"]["DenoiseMaskOutput"] | components["schemas"]["ImageOutput"] | components["schemas"]["IterateInvocationOutput"] | components["schemas"]["LatentsOutput"] | components["schemas"]["LoRALoaderOutput"] | components["schemas"]["SDXLRefinerModelLoaderOutput"] | components["schemas"]["StringCollectionOutput"] | components["schemas"]["SDXLModelLoaderOutput"] | components["schemas"]["FaceMaskOutput"] | components["schemas"]["LatentsCollectionOutput"] | components["schemas"]["VAEOutput"] | components["schemas"]["CalculateImageTilesOutput"] | components["schemas"]["PairTileImageOutput"] | components["schemas"]["BooleanOutput"] | components["schemas"]["ConditioningOutput"] | components["schemas"]["IdealSizeOutput"] | components["schemas"]["MetadataItemOutput"] | components["schemas"]["TileToPropertiesOutput"]; + [key: string]: components["schemas"]["BooleanOutput"] | components["schemas"]["IterateInvocationOutput"] | components["schemas"]["NoiseOutput"] | components["schemas"]["LatentsCollectionOutput"] | components["schemas"]["FaceOffOutput"] | components["schemas"]["IPAdapterOutput"] | components["schemas"]["UNetOutput"] | components["schemas"]["MetadataItemOutput"] | components["schemas"]["CalculateImageTilesOutput"] | components["schemas"]["T2IAdapterOutput"] | components["schemas"]["ImageCollectionOutput"] | components["schemas"]["ModelLoaderOutput"] | components["schemas"]["SDXLLoRALoaderOutput"] | components["schemas"]["IntegerCollectionOutput"] | components["schemas"]["CollectInvocationOutput"] | components["schemas"]["SDXLRefinerModelLoaderOutput"] | components["schemas"]["ImageOutput"] | components["schemas"]["MetadataOutput"] | components["schemas"]["LoRALoaderOutput"] | components["schemas"]["PairTileImageOutput"] | components["schemas"]["FaceMaskOutput"] | components["schemas"]["SeamlessModeOutput"] | components["schemas"]["LatentsOutput"] | components["schemas"]["ControlOutput"] | components["schemas"]["SchedulerOutput"] | components["schemas"]["FloatOutput"] | components["schemas"]["GradientMaskOutput"] | components["schemas"]["IntegerOutput"] | components["schemas"]["FloatCollectionOutput"] | components["schemas"]["VAEOutput"] | components["schemas"]["CLIPOutput"] | components["schemas"]["SDXLModelLoaderOutput"] | components["schemas"]["ConditioningOutput"] | components["schemas"]["StringCollectionOutput"] | components["schemas"]["IdealSizeOutput"] | components["schemas"]["TileToPropertiesOutput"] | components["schemas"]["BooleanCollectionOutput"] | components["schemas"]["ColorOutput"] | components["schemas"]["ColorCollectionOutput"] | components["schemas"]["StringPosNegOutput"] | components["schemas"]["DenoiseMaskOutput"] | components["schemas"]["String2Output"] | components["schemas"]["MaskOutput"] | components["schemas"]["ConditioningCollectionOutput"] | components["schemas"]["StringOutput"] | components["schemas"]["CLIPSkipInvocationOutput"]; }; /** * Errors