From 3ba547a41a58298bb08089a75d0ce6aec31139c5 Mon Sep 17 00:00:00 2001 From: Surisen Date: Thu, 16 Nov 2023 02:57:08 +0100 Subject: [PATCH 1/5] translationBot(ui): update translation (Chinese (Simplified)) Currently translated at 100.0% (1229 of 1229 strings) Co-authored-by: Surisen Translate-URL: https://hosted.weblate.org/projects/invokeai/web-ui/zh_Hans/ Translation: InvokeAI/Web UI --- invokeai/frontend/web/public/locales/zh_CN.json | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/invokeai/frontend/web/public/locales/zh_CN.json b/invokeai/frontend/web/public/locales/zh_CN.json index 72eb686b27..130fdfb182 100644 --- a/invokeai/frontend/web/public/locales/zh_CN.json +++ b/invokeai/frontend/web/public/locales/zh_CN.json @@ -1222,7 +1222,8 @@ "seamless": "无缝", "fit": "图生图匹配", "recallParameters": "召回参数", - "noRecallParameters": "未找到要召回的参数" + "noRecallParameters": "未找到要召回的参数", + "vae": "VAE" }, "models": { "noMatchingModels": "无相匹配的模型", @@ -1501,5 +1502,18 @@ "clear": "清除", "maxCacheSize": "最大缓存大小", "cacheSize": "缓存大小" + }, + "hrf": { + "enableHrf": "启用高分辨率修复", + "upscaleMethod": "放大方法", + "enableHrfTooltip": "使用较低的分辨率进行初始生成,放大到基础分辨率后进行图生图。", + "metadata": { + "strength": "高分辨率修复强度", + "enabled": "高分辨率修复已启用", + "method": "高分辨率修复方法" + }, + "hrf": "高分辨率修复", + "hrfStrength": "高分辨率修复强度", + "strengthTooltip": "值越低细节越少,但可以减少部分潜在的伪影。" } } From cc747c066c67c8ea5c7f03519ef939e7e717e18d Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Thu, 16 Nov 2023 18:47:31 +1100 Subject: [PATCH 2/5] fix(nodes): fix hrf_enabled metadata item It was a float but should be a bool --- invokeai/app/invocations/metadata.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/invokeai/app/invocations/metadata.py b/invokeai/app/invocations/metadata.py index ed8a091f8d..d837e6297f 100644 --- a/invokeai/app/invocations/metadata.py +++ b/invokeai/app/invocations/metadata.py @@ -112,7 +112,7 @@ GENERATION_MODES = Literal[ ] -@invocation("core_metadata", title="Core Metadata", tags=["metadata"], category="metadata", version="1.0.0") +@invocation("core_metadata", title="Core Metadata", tags=["metadata"], category="metadata", version="1.0.1") class CoreMetadataInvocation(BaseInvocation): """Collects core generation metadata into a MetadataField""" @@ -160,7 +160,7 @@ class CoreMetadataInvocation(BaseInvocation): ) # High resolution fix metadata. - hrf_enabled: Optional[float] = InputField( + hrf_enabled: Optional[bool] = InputField( default=None, description="Whether or not high resolution fix was enabled.", ) From 4599517c6c309d71cd32a535076c2e12c585d75f Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Thu, 16 Nov 2023 18:56:27 +1100 Subject: [PATCH 3/5] feat: add private node for linear UI image outputting Add a LinearUIOutputInvocation node to be the new terminal node for Linear UI graphs. This node is private and hidden from the Workflow Editor, as it is an implementation detail. The Linear UI was using the Save Image node for this purpose. It allowed every linear graph to end a single node type, which handled saving metadata and board. This substantially reduced the complexity of the linear graphs. This caused two related issues: - Images were saved to disk twice - Noticeable delay between when an image was decoded and showed up in the UI To resolve this, the new LinearUIOutputInvocation node will handle adding an image to a board if one is provided. Metadata is no longer provided in this unified node. Instead, the metadata graph helpers now need to know the node to add metadata to and provide it to the last node that actually outputs an image. This is a `l2i` node for txt2img & img2img graphs, and a different image-outputting node for canvas graphs. HRF poses another complication, in that it changes the terminal node. To handle this, a new metadata util is added called `setMetadataReceivingNode()`. HRF calls this to change the node that should receive the graph's metadata. This resolves the duplicate images issue and improves perf without otherwise changing the user experience. --- invokeai/app/invocations/image.py | 31 +++++- .../listeners/controlNetImageProcessed.ts | 23 +---- .../ImageMetadataActions.tsx | 2 + .../nodes/util/graphBuilders/addHrfToGraph.ts | 3 +- ...eImageNode.ts => addLinearUIOutputNode.ts} | 16 ++-- .../graphBuilders/buildAdHocUpscaleGraph.ts | 16 ++-- .../buildCanvasImageToImageGraph.ts | 46 +++++---- .../graphBuilders/buildCanvasInpaintGraph.ts | 4 +- .../graphBuilders/buildCanvasOutpaintGraph.ts | 4 +- .../buildCanvasSDXLImageToImageGraph.ts | 44 +++++---- .../buildCanvasSDXLInpaintGraph.ts | 4 +- .../buildCanvasSDXLOutpaintGraph.ts | 4 +- .../buildCanvasSDXLTextToImageGraph.ts | 40 ++++---- .../buildCanvasTextToImageGraph.ts | 42 ++++---- .../buildLinearImageToImageGraph.ts | 40 ++++---- .../buildLinearSDXLImageToImageGraph.ts | 42 ++++---- .../buildLinearSDXLTextToImageGraph.ts | 38 ++++---- .../buildLinearTextToImageGraph.ts | 36 +++---- .../nodes/util/graphBuilders/constants.ts | 2 +- .../nodes/util/graphBuilders/metadata.ts | 25 ++++- .../src/features/nodes/util/parseSchema.ts | 2 +- .../frontend/web/src/services/api/schema.d.ts | 95 +++++++++++++------ .../frontend/web/src/services/api/types.ts | 2 +- 23 files changed, 336 insertions(+), 225 deletions(-) rename invokeai/frontend/web/src/features/nodes/util/graphBuilders/{addSaveImageNode.ts => addLinearUIOutputNode.ts} (84%) diff --git a/invokeai/app/invocations/image.py b/invokeai/app/invocations/image.py index 1e0adbd37a..fb59fdf7fd 100644 --- a/invokeai/app/invocations/image.py +++ b/invokeai/app/invocations/image.py @@ -8,7 +8,7 @@ import numpy from PIL import Image, ImageChops, ImageFilter, ImageOps from invokeai.app.invocations.primitives import BoardField, ColorField, ImageField, ImageOutput -from invokeai.app.services.image_records.image_records_common import ImageCategory, ResourceOrigin +from invokeai.app.services.image_records.image_records_common import ImageCategory, ImageRecordChanges, ResourceOrigin from invokeai.app.shared.fields import FieldDescriptions from invokeai.backend.image_util.invisible_watermark import InvisibleWatermark from invokeai.backend.image_util.safety_checker import SafetyChecker @@ -1017,3 +1017,32 @@ class SaveImageInvocation(BaseInvocation, WithWorkflow, WithMetadata): width=image_dto.width, height=image_dto.height, ) + + +@invocation( + "linear_ui_output", + title="Linear UI Image Output", + tags=["primitives", "image"], + category="primitives", + version="1.0.0", + use_cache=False, +) +class LinearUIOutputInvocation(BaseInvocation, WithWorkflow, WithMetadata): + """Handles Linear UI Image Outputting tasks.""" + + image: ImageField = InputField(description=FieldDescriptions.image) + board: Optional[BoardField] = InputField(default=None, description=FieldDescriptions.board, input=Input.Direct) + + def invoke(self, context: InvocationContext) -> ImageOutput: + image_dto = context.services.images.get_dto(self.image.image_name) + + if self.board: + context.services.board_images.add_image_to_board(self.board.board_id, self.image.image_name) + + context.services.images.update(self.image.image_name, changes=ImageRecordChanges(is_intermediate=False)) + + return ImageOutput( + image=ImageField(image_name=self.image.image_name), + width=image_dto.width, + height=image_dto.height, + ) diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/controlNetImageProcessed.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/controlNetImageProcessed.ts index a454e5ca48..1996ec99a5 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/controlNetImageProcessed.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/controlNetImageProcessed.ts @@ -8,7 +8,6 @@ import { selectControlAdapterById, } from 'features/controlAdapters/store/controlAdaptersSlice'; import { isControlNetOrT2IAdapter } from 'features/controlAdapters/store/types'; -import { SAVE_IMAGE } from 'features/nodes/util/graphBuilders/constants'; import { addToast } from 'features/system/store/systemSlice'; import { t } from 'i18next'; import { imagesApi } from 'services/api/endpoints/images'; @@ -38,6 +37,7 @@ export const addControlNetImageProcessedListener = () => { // ControlNet one-off procressing graph is just the processor node, no edges. // Also we need to grab the image. + const nodeId = ca.processorNode.id; const enqueueBatchArg: BatchConfig = { prepend: true, batch: { @@ -46,27 +46,10 @@ export const addControlNetImageProcessedListener = () => { [ca.processorNode.id]: { ...ca.processorNode, is_intermediate: true, + use_cache: false, image: { image_name: ca.controlImage }, }, - [SAVE_IMAGE]: { - id: SAVE_IMAGE, - type: 'save_image', - is_intermediate: true, - use_cache: false, - }, }, - edges: [ - { - source: { - node_id: ca.processorNode.id, - field: 'image', - }, - destination: { - node_id: SAVE_IMAGE, - field: 'image', - }, - }, - ], }, runs: 1, }, @@ -90,7 +73,7 @@ export const addControlNetImageProcessedListener = () => { socketInvocationComplete.match(action) && action.payload.data.queue_batch_id === enqueueResult.batch.batch_id && - action.payload.data.source_node_id === SAVE_IMAGE + action.payload.data.source_node_id === nodeId ); // We still have to check the output type diff --git a/invokeai/frontend/web/src/features/gallery/components/ImageMetadataViewer/ImageMetadataActions.tsx b/invokeai/frontend/web/src/features/gallery/components/ImageMetadataViewer/ImageMetadataActions.tsx index 9053ce973d..ce5b178fa2 100644 --- a/invokeai/frontend/web/src/features/gallery/components/ImageMetadataViewer/ImageMetadataActions.tsx +++ b/invokeai/frontend/web/src/features/gallery/components/ImageMetadataViewer/ImageMetadataActions.tsx @@ -157,6 +157,8 @@ const ImageMetadataActions = (props: Props) => { return null; } + console.log(metadata); + return ( <> {metadata.created_by && ( diff --git a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/addHrfToGraph.ts b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/addHrfToGraph.ts index d1df9bb9c2..9825ce754e 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/addHrfToGraph.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/addHrfToGraph.ts @@ -23,7 +23,7 @@ import { RESIZE_HRF, VAE_LOADER, } from './constants'; -import { upsertMetadata } from './metadata'; +import { setMetadataReceivingNode, upsertMetadata } from './metadata'; // Copy certain connections from previous DENOISE_LATENTS to new DENOISE_LATENTS_HRF. function copyConnectionsToDenoiseLatentsHrf(graph: NonNullableGraph): void { @@ -369,4 +369,5 @@ export const addHrfToGraph = ( hrf_enabled: hrfEnabled, hrf_method: hrfMethod, }); + setMetadataReceivingNode(graph, LATENTS_TO_IMAGE_HRF_HR); }; diff --git a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/addSaveImageNode.ts b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/addLinearUIOutputNode.ts similarity index 84% rename from invokeai/frontend/web/src/features/nodes/util/graphBuilders/addSaveImageNode.ts rename to invokeai/frontend/web/src/features/nodes/util/graphBuilders/addLinearUIOutputNode.ts index 171bd37de8..926fa3a8f3 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/addSaveImageNode.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/addLinearUIOutputNode.ts @@ -1,20 +1,20 @@ import { RootState } from 'app/store/store'; import { NonNullableGraph } from 'features/nodes/types/types'; import { activeTabNameSelector } from 'features/ui/store/uiSelectors'; -import { SaveImageInvocation } from 'services/api/types'; +import { LinearUIOutputInvocation } from 'services/api/types'; import { CANVAS_OUTPUT, LATENTS_TO_IMAGE, LATENTS_TO_IMAGE_HRF_HR, + LINEAR_UI_OUTPUT, NSFW_CHECKER, - SAVE_IMAGE, WATERMARKER, } from './constants'; /** * Set the `use_cache` field on the linear/canvas graph's final image output node to False. */ -export const addSaveImageNode = ( +export const addLinearUIOutputNode = ( state: RootState, graph: NonNullableGraph ): void => { @@ -23,18 +23,18 @@ export const addSaveImageNode = ( activeTabName === 'unifiedCanvas' ? !state.canvas.shouldAutoSave : false; const { autoAddBoardId } = state.gallery; - const saveImageNode: SaveImageInvocation = { - id: SAVE_IMAGE, - type: 'save_image', + const linearUIOutputNode: LinearUIOutputInvocation = { + id: LINEAR_UI_OUTPUT, + type: 'linear_ui_output', is_intermediate, use_cache: false, board: autoAddBoardId === 'none' ? undefined : { board_id: autoAddBoardId }, }; - graph.nodes[SAVE_IMAGE] = saveImageNode; + graph.nodes[LINEAR_UI_OUTPUT] = linearUIOutputNode; const destination = { - node_id: SAVE_IMAGE, + node_id: LINEAR_UI_OUTPUT, field: 'image', }; diff --git a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildAdHocUpscaleGraph.ts b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildAdHocUpscaleGraph.ts index 5af8edbdfc..73551202b8 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildAdHocUpscaleGraph.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildAdHocUpscaleGraph.ts @@ -4,9 +4,9 @@ import { ESRGANModelName } from 'features/parameters/store/postprocessingSlice'; import { ESRGANInvocation, Graph, - SaveImageInvocation, + LinearUIOutputInvocation, } from 'services/api/types'; -import { REALESRGAN as ESRGAN, SAVE_IMAGE } from './constants'; +import { REALESRGAN as ESRGAN, LINEAR_UI_OUTPUT } from './constants'; import { addCoreMetadataNode, upsertMetadata } from './metadata'; type Arg = { @@ -28,9 +28,9 @@ export const buildAdHocUpscaleGraph = ({ is_intermediate: true, }; - const saveImageNode: SaveImageInvocation = { - id: SAVE_IMAGE, - type: 'save_image', + const linearUIOutputNode: LinearUIOutputInvocation = { + id: LINEAR_UI_OUTPUT, + type: 'linear_ui_output', use_cache: false, is_intermediate: false, board: autoAddBoardId === 'none' ? undefined : { board_id: autoAddBoardId }, @@ -40,7 +40,7 @@ export const buildAdHocUpscaleGraph = ({ id: `adhoc-esrgan-graph`, nodes: { [ESRGAN]: realesrganNode, - [SAVE_IMAGE]: saveImageNode, + [LINEAR_UI_OUTPUT]: linearUIOutputNode, }, edges: [ { @@ -49,14 +49,14 @@ export const buildAdHocUpscaleGraph = ({ field: 'image', }, destination: { - node_id: SAVE_IMAGE, + node_id: LINEAR_UI_OUTPUT, field: 'image', }, }, ], }; - addCoreMetadataNode(graph, {}); + addCoreMetadataNode(graph, {}, ESRGAN); upsertMetadata(graph, { esrgan_model: esrganModelName, }); diff --git a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasImageToImageGraph.ts b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasImageToImageGraph.ts index 9d957c3a4a..a86fdb4ce6 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasImageToImageGraph.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasImageToImageGraph.ts @@ -6,7 +6,7 @@ import { addControlNetToLinearGraph } from './addControlNetToLinearGraph'; import { addIPAdapterToLinearGraph } from './addIPAdapterToLinearGraph'; import { addLoRAsToGraph } from './addLoRAsToGraph'; import { addNSFWCheckerToGraph } from './addNSFWCheckerToGraph'; -import { addSaveImageNode } from './addSaveImageNode'; +import { addLinearUIOutputNode } from './addLinearUIOutputNode'; import { addSeamlessToLinearGraph } from './addSeamlessToLinearGraph'; import { addT2IAdaptersToLinearGraph } from './addT2IAdapterToLinearGraph'; import { addVAEToGraph } from './addVAEToGraph'; @@ -308,24 +308,30 @@ export const buildCanvasImageToImageGraph = ( }); } - addCoreMetadataNode(graph, { - generation_mode: 'img2img', - cfg_scale, - width: !isUsingScaledDimensions ? width : scaledBoundingBoxDimensions.width, - height: !isUsingScaledDimensions - ? height - : scaledBoundingBoxDimensions.height, - positive_prompt: positivePrompt, - negative_prompt: negativePrompt, - model, - seed, - steps, - rand_device: use_cpu ? 'cpu' : 'cuda', - scheduler, - clip_skip: clipSkip, - strength, - init_image: initialImage.image_name, - }); + addCoreMetadataNode( + graph, + { + generation_mode: 'img2img', + cfg_scale, + width: !isUsingScaledDimensions + ? width + : scaledBoundingBoxDimensions.width, + height: !isUsingScaledDimensions + ? height + : scaledBoundingBoxDimensions.height, + positive_prompt: positivePrompt, + negative_prompt: negativePrompt, + model, + seed, + steps, + rand_device: use_cpu ? 'cpu' : 'cuda', + scheduler, + clip_skip: clipSkip, + strength, + init_image: initialImage.image_name, + }, + CANVAS_OUTPUT + ); // Add Seamless To Graph if (seamlessXAxis || seamlessYAxis) { @@ -357,7 +363,7 @@ export const buildCanvasImageToImageGraph = ( addWatermarkerToGraph(state, graph, CANVAS_OUTPUT); } - addSaveImageNode(state, graph); + addLinearUIOutputNode(state, graph); return graph; }; diff --git a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasInpaintGraph.ts b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasInpaintGraph.ts index c786bad017..48052e2a94 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasInpaintGraph.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasInpaintGraph.ts @@ -13,7 +13,7 @@ import { addControlNetToLinearGraph } from './addControlNetToLinearGraph'; import { addIPAdapterToLinearGraph } from './addIPAdapterToLinearGraph'; import { addLoRAsToGraph } from './addLoRAsToGraph'; import { addNSFWCheckerToGraph } from './addNSFWCheckerToGraph'; -import { addSaveImageNode } from './addSaveImageNode'; +import { addLinearUIOutputNode } from './addLinearUIOutputNode'; import { addSeamlessToLinearGraph } from './addSeamlessToLinearGraph'; import { addT2IAdaptersToLinearGraph } from './addT2IAdapterToLinearGraph'; import { addVAEToGraph } from './addVAEToGraph'; @@ -666,7 +666,7 @@ export const buildCanvasInpaintGraph = ( addWatermarkerToGraph(state, graph, CANVAS_OUTPUT); } - addSaveImageNode(state, graph); + addLinearUIOutputNode(state, graph); return graph; }; diff --git a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasOutpaintGraph.ts b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasOutpaintGraph.ts index e7e27fabfa..31cf5ca7e8 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasOutpaintGraph.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasOutpaintGraph.ts @@ -12,7 +12,7 @@ import { addControlNetToLinearGraph } from './addControlNetToLinearGraph'; import { addIPAdapterToLinearGraph } from './addIPAdapterToLinearGraph'; import { addLoRAsToGraph } from './addLoRAsToGraph'; import { addNSFWCheckerToGraph } from './addNSFWCheckerToGraph'; -import { addSaveImageNode } from './addSaveImageNode'; +import { addLinearUIOutputNode } from './addLinearUIOutputNode'; import { addSeamlessToLinearGraph } from './addSeamlessToLinearGraph'; import { addT2IAdaptersToLinearGraph } from './addT2IAdapterToLinearGraph'; import { addVAEToGraph } from './addVAEToGraph'; @@ -770,7 +770,7 @@ export const buildCanvasOutpaintGraph = ( addWatermarkerToGraph(state, graph, CANVAS_OUTPUT); } - addSaveImageNode(state, graph); + addLinearUIOutputNode(state, graph); return graph; }; diff --git a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasSDXLImageToImageGraph.ts b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasSDXLImageToImageGraph.ts index c1ecde5395..8281c9c248 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasSDXLImageToImageGraph.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasSDXLImageToImageGraph.ts @@ -7,7 +7,7 @@ import { addIPAdapterToLinearGraph } from './addIPAdapterToLinearGraph'; import { addNSFWCheckerToGraph } from './addNSFWCheckerToGraph'; import { addSDXLLoRAsToGraph } from './addSDXLLoRAstoGraph'; import { addSDXLRefinerToGraph } from './addSDXLRefinerToGraph'; -import { addSaveImageNode } from './addSaveImageNode'; +import { addLinearUIOutputNode } from './addLinearUIOutputNode'; import { addSeamlessToLinearGraph } from './addSeamlessToLinearGraph'; import { addVAEToGraph } from './addVAEToGraph'; import { addWatermarkerToGraph } from './addWatermarkerToGraph'; @@ -319,23 +319,29 @@ export const buildCanvasSDXLImageToImageGraph = ( }); } - addCoreMetadataNode(graph, { - generation_mode: 'img2img', - cfg_scale, - width: !isUsingScaledDimensions ? width : scaledBoundingBoxDimensions.width, - height: !isUsingScaledDimensions - ? height - : scaledBoundingBoxDimensions.height, - positive_prompt: positivePrompt, - negative_prompt: negativePrompt, - model, - seed, - steps, - rand_device: use_cpu ? 'cpu' : 'cuda', - scheduler, - strength, - init_image: initialImage.image_name, - }); + addCoreMetadataNode( + graph, + { + generation_mode: 'img2img', + cfg_scale, + width: !isUsingScaledDimensions + ? width + : scaledBoundingBoxDimensions.width, + height: !isUsingScaledDimensions + ? height + : scaledBoundingBoxDimensions.height, + positive_prompt: positivePrompt, + negative_prompt: negativePrompt, + model, + seed, + steps, + rand_device: use_cpu ? 'cpu' : 'cuda', + scheduler, + strength, + init_image: initialImage.image_name, + }, + CANVAS_OUTPUT + ); // Add Seamless To Graph if (seamlessXAxis || seamlessYAxis) { @@ -380,7 +386,7 @@ export const buildCanvasSDXLImageToImageGraph = ( addWatermarkerToGraph(state, graph, CANVAS_OUTPUT); } - addSaveImageNode(state, graph); + addLinearUIOutputNode(state, graph); return graph; }; diff --git a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasSDXLInpaintGraph.ts b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasSDXLInpaintGraph.ts index f302c4c62f..40626e289a 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasSDXLInpaintGraph.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasSDXLInpaintGraph.ts @@ -14,7 +14,7 @@ import { addIPAdapterToLinearGraph } from './addIPAdapterToLinearGraph'; import { addNSFWCheckerToGraph } from './addNSFWCheckerToGraph'; import { addSDXLLoRAsToGraph } from './addSDXLLoRAstoGraph'; import { addSDXLRefinerToGraph } from './addSDXLRefinerToGraph'; -import { addSaveImageNode } from './addSaveImageNode'; +import { addLinearUIOutputNode } from './addLinearUIOutputNode'; import { addSeamlessToLinearGraph } from './addSeamlessToLinearGraph'; import { addT2IAdaptersToLinearGraph } from './addT2IAdapterToLinearGraph'; import { addVAEToGraph } from './addVAEToGraph'; @@ -696,7 +696,7 @@ export const buildCanvasSDXLInpaintGraph = ( addWatermarkerToGraph(state, graph, CANVAS_OUTPUT); } - addSaveImageNode(state, graph); + addLinearUIOutputNode(state, graph); return graph; }; diff --git a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasSDXLOutpaintGraph.ts b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasSDXLOutpaintGraph.ts index 501417b00d..c7302cd56d 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasSDXLOutpaintGraph.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasSDXLOutpaintGraph.ts @@ -13,7 +13,7 @@ import { addIPAdapterToLinearGraph } from './addIPAdapterToLinearGraph'; import { addNSFWCheckerToGraph } from './addNSFWCheckerToGraph'; import { addSDXLLoRAsToGraph } from './addSDXLLoRAstoGraph'; import { addSDXLRefinerToGraph } from './addSDXLRefinerToGraph'; -import { addSaveImageNode } from './addSaveImageNode'; +import { addLinearUIOutputNode } from './addLinearUIOutputNode'; import { addSeamlessToLinearGraph } from './addSeamlessToLinearGraph'; import { addT2IAdaptersToLinearGraph } from './addT2IAdapterToLinearGraph'; import { addVAEToGraph } from './addVAEToGraph'; @@ -799,7 +799,7 @@ export const buildCanvasSDXLOutpaintGraph = ( addWatermarkerToGraph(state, graph, CANVAS_OUTPUT); } - addSaveImageNode(state, graph); + addLinearUIOutputNode(state, graph); return graph; }; diff --git a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasSDXLTextToImageGraph.ts b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasSDXLTextToImageGraph.ts index e43891eba4..2a712f2ef3 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasSDXLTextToImageGraph.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasSDXLTextToImageGraph.ts @@ -10,7 +10,7 @@ import { addIPAdapterToLinearGraph } from './addIPAdapterToLinearGraph'; import { addNSFWCheckerToGraph } from './addNSFWCheckerToGraph'; import { addSDXLLoRAsToGraph } from './addSDXLLoRAstoGraph'; import { addSDXLRefinerToGraph } from './addSDXLRefinerToGraph'; -import { addSaveImageNode } from './addSaveImageNode'; +import { addLinearUIOutputNode } from './addLinearUIOutputNode'; import { addSeamlessToLinearGraph } from './addSeamlessToLinearGraph'; import { addT2IAdaptersToLinearGraph } from './addT2IAdapterToLinearGraph'; import { addVAEToGraph } from './addVAEToGraph'; @@ -301,21 +301,27 @@ export const buildCanvasSDXLTextToImageGraph = ( }); } - addCoreMetadataNode(graph, { - generation_mode: 'txt2img', - cfg_scale, - width: !isUsingScaledDimensions ? width : scaledBoundingBoxDimensions.width, - height: !isUsingScaledDimensions - ? height - : scaledBoundingBoxDimensions.height, - positive_prompt: positivePrompt, - negative_prompt: negativePrompt, - model, - seed, - steps, - rand_device: use_cpu ? 'cpu' : 'cuda', - scheduler, - }); + addCoreMetadataNode( + graph, + { + generation_mode: 'txt2img', + cfg_scale, + width: !isUsingScaledDimensions + ? width + : scaledBoundingBoxDimensions.width, + height: !isUsingScaledDimensions + ? height + : scaledBoundingBoxDimensions.height, + positive_prompt: positivePrompt, + negative_prompt: negativePrompt, + model, + seed, + steps, + rand_device: use_cpu ? 'cpu' : 'cuda', + scheduler, + }, + CANVAS_OUTPUT + ); // Add Seamless To Graph if (seamlessXAxis || seamlessYAxis) { @@ -360,7 +366,7 @@ export const buildCanvasSDXLTextToImageGraph = ( addWatermarkerToGraph(state, graph, CANVAS_OUTPUT); } - addSaveImageNode(state, graph); + addLinearUIOutputNode(state, graph); return graph; }; diff --git a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasTextToImageGraph.ts b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasTextToImageGraph.ts index 6e48c14086..5c0c91ca71 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasTextToImageGraph.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildCanvasTextToImageGraph.ts @@ -9,7 +9,7 @@ import { addControlNetToLinearGraph } from './addControlNetToLinearGraph'; import { addIPAdapterToLinearGraph } from './addIPAdapterToLinearGraph'; import { addLoRAsToGraph } from './addLoRAsToGraph'; import { addNSFWCheckerToGraph } from './addNSFWCheckerToGraph'; -import { addSaveImageNode } from './addSaveImageNode'; +import { addLinearUIOutputNode } from './addLinearUIOutputNode'; import { addSeamlessToLinearGraph } from './addSeamlessToLinearGraph'; import { addT2IAdaptersToLinearGraph } from './addT2IAdapterToLinearGraph'; import { addVAEToGraph } from './addVAEToGraph'; @@ -289,22 +289,28 @@ export const buildCanvasTextToImageGraph = ( }); } - addCoreMetadataNode(graph, { - generation_mode: 'txt2img', - cfg_scale, - width: !isUsingScaledDimensions ? width : scaledBoundingBoxDimensions.width, - height: !isUsingScaledDimensions - ? height - : scaledBoundingBoxDimensions.height, - positive_prompt: positivePrompt, - negative_prompt: negativePrompt, - model, - seed, - steps, - rand_device: use_cpu ? 'cpu' : 'cuda', - scheduler, - clip_skip: clipSkip, - }); + addCoreMetadataNode( + graph, + { + generation_mode: 'txt2img', + cfg_scale, + width: !isUsingScaledDimensions + ? width + : scaledBoundingBoxDimensions.width, + height: !isUsingScaledDimensions + ? height + : scaledBoundingBoxDimensions.height, + positive_prompt: positivePrompt, + negative_prompt: negativePrompt, + model, + seed, + steps, + rand_device: use_cpu ? 'cpu' : 'cuda', + scheduler, + clip_skip: clipSkip, + }, + CANVAS_OUTPUT + ); // Add Seamless To Graph if (seamlessXAxis || seamlessYAxis) { @@ -336,7 +342,7 @@ export const buildCanvasTextToImageGraph = ( addWatermarkerToGraph(state, graph, CANVAS_OUTPUT); } - addSaveImageNode(state, graph); + addLinearUIOutputNode(state, graph); return graph; }; diff --git a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildLinearImageToImageGraph.ts b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildLinearImageToImageGraph.ts index 3b13c746c9..e13e7f3e53 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildLinearImageToImageGraph.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildLinearImageToImageGraph.ts @@ -9,7 +9,7 @@ import { addControlNetToLinearGraph } from './addControlNetToLinearGraph'; import { addIPAdapterToLinearGraph } from './addIPAdapterToLinearGraph'; import { addLoRAsToGraph } from './addLoRAsToGraph'; import { addNSFWCheckerToGraph } from './addNSFWCheckerToGraph'; -import { addSaveImageNode } from './addSaveImageNode'; +import { addLinearUIOutputNode } from './addLinearUIOutputNode'; import { addSeamlessToLinearGraph } from './addSeamlessToLinearGraph'; import { addT2IAdaptersToLinearGraph } from './addT2IAdapterToLinearGraph'; import { addVAEToGraph } from './addVAEToGraph'; @@ -311,22 +311,26 @@ export const buildLinearImageToImageGraph = ( }); } - addCoreMetadataNode(graph, { - generation_mode: 'img2img', - cfg_scale, - height, - width, - positive_prompt: positivePrompt, - negative_prompt: negativePrompt, - model, - seed, - steps, - rand_device: use_cpu ? 'cpu' : 'cuda', - scheduler, - clip_skip: clipSkip, - strength, - init_image: initialImage.imageName, - }); + addCoreMetadataNode( + graph, + { + generation_mode: 'img2img', + cfg_scale, + height, + width, + positive_prompt: positivePrompt, + negative_prompt: negativePrompt, + model, + seed, + steps, + rand_device: use_cpu ? 'cpu' : 'cuda', + scheduler, + clip_skip: clipSkip, + strength, + init_image: initialImage.imageName, + }, + IMAGE_TO_LATENTS + ); // Add Seamless To Graph if (seamlessXAxis || seamlessYAxis) { @@ -358,7 +362,7 @@ export const buildLinearImageToImageGraph = ( addWatermarkerToGraph(state, graph); } - addSaveImageNode(state, graph); + addLinearUIOutputNode(state, graph); return graph; }; diff --git a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildLinearSDXLImageToImageGraph.ts b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildLinearSDXLImageToImageGraph.ts index 54f8e05d21..94586c97ba 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildLinearSDXLImageToImageGraph.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildLinearSDXLImageToImageGraph.ts @@ -10,7 +10,7 @@ import { addIPAdapterToLinearGraph } from './addIPAdapterToLinearGraph'; import { addNSFWCheckerToGraph } from './addNSFWCheckerToGraph'; import { addSDXLLoRAsToGraph } from './addSDXLLoRAstoGraph'; import { addSDXLRefinerToGraph } from './addSDXLRefinerToGraph'; -import { addSaveImageNode } from './addSaveImageNode'; +import { addLinearUIOutputNode } from './addLinearUIOutputNode'; import { addSeamlessToLinearGraph } from './addSeamlessToLinearGraph'; import { addT2IAdaptersToLinearGraph } from './addT2IAdapterToLinearGraph'; import { addVAEToGraph } from './addVAEToGraph'; @@ -331,23 +331,27 @@ export const buildLinearSDXLImageToImageGraph = ( }); } - addCoreMetadataNode(graph, { - generation_mode: 'sdxl_img2img', - cfg_scale, - height, - width, - positive_prompt: positivePrompt, - negative_prompt: negativePrompt, - model, - seed, - steps, - rand_device: use_cpu ? 'cpu' : 'cuda', - scheduler, - strength, - init_image: initialImage.imageName, - positive_style_prompt: positiveStylePrompt, - negative_style_prompt: negativeStylePrompt, - }); + addCoreMetadataNode( + graph, + { + generation_mode: 'sdxl_img2img', + cfg_scale, + height, + width, + positive_prompt: positivePrompt, + negative_prompt: negativePrompt, + model, + seed, + steps, + rand_device: use_cpu ? 'cpu' : 'cuda', + scheduler, + strength, + init_image: initialImage.imageName, + positive_style_prompt: positiveStylePrompt, + negative_style_prompt: negativeStylePrompt, + }, + IMAGE_TO_LATENTS + ); // Add Seamless To Graph if (seamlessXAxis || seamlessYAxis) { @@ -388,7 +392,7 @@ export const buildLinearSDXLImageToImageGraph = ( addWatermarkerToGraph(state, graph); } - addSaveImageNode(state, graph); + addLinearUIOutputNode(state, graph); return graph; }; diff --git a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildLinearSDXLTextToImageGraph.ts b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildLinearSDXLTextToImageGraph.ts index 37fbbf7f43..37e9b293c6 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildLinearSDXLTextToImageGraph.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildLinearSDXLTextToImageGraph.ts @@ -6,7 +6,7 @@ import { addIPAdapterToLinearGraph } from './addIPAdapterToLinearGraph'; import { addNSFWCheckerToGraph } from './addNSFWCheckerToGraph'; import { addSDXLLoRAsToGraph } from './addSDXLLoRAstoGraph'; import { addSDXLRefinerToGraph } from './addSDXLRefinerToGraph'; -import { addSaveImageNode } from './addSaveImageNode'; +import { addLinearUIOutputNode } from './addLinearUIOutputNode'; import { addSeamlessToLinearGraph } from './addSeamlessToLinearGraph'; import { addT2IAdaptersToLinearGraph } from './addT2IAdapterToLinearGraph'; import { addVAEToGraph } from './addVAEToGraph'; @@ -225,21 +225,25 @@ export const buildLinearSDXLTextToImageGraph = ( ], }; - addCoreMetadataNode(graph, { - generation_mode: 'sdxl_txt2img', - cfg_scale, - height, - width, - positive_prompt: positivePrompt, - negative_prompt: negativePrompt, - model, - seed, - steps, - rand_device: use_cpu ? 'cpu' : 'cuda', - scheduler, - positive_style_prompt: positiveStylePrompt, - negative_style_prompt: negativeStylePrompt, - }); + addCoreMetadataNode( + graph, + { + generation_mode: 'sdxl_txt2img', + cfg_scale, + height, + width, + positive_prompt: positivePrompt, + negative_prompt: negativePrompt, + model, + seed, + steps, + rand_device: use_cpu ? 'cpu' : 'cuda', + scheduler, + positive_style_prompt: positiveStylePrompt, + negative_style_prompt: negativeStylePrompt, + }, + LATENTS_TO_IMAGE + ); // Add Seamless To Graph if (seamlessXAxis || seamlessYAxis) { @@ -280,7 +284,7 @@ export const buildLinearSDXLTextToImageGraph = ( addWatermarkerToGraph(state, graph); } - addSaveImageNode(state, graph); + addLinearUIOutputNode(state, graph); return graph; }; diff --git a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildLinearTextToImageGraph.ts b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildLinearTextToImageGraph.ts index 8e0143f180..f097cf0c42 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildLinearTextToImageGraph.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildLinearTextToImageGraph.ts @@ -10,7 +10,7 @@ import { addHrfToGraph } from './addHrfToGraph'; import { addIPAdapterToLinearGraph } from './addIPAdapterToLinearGraph'; import { addLoRAsToGraph } from './addLoRAsToGraph'; import { addNSFWCheckerToGraph } from './addNSFWCheckerToGraph'; -import { addSaveImageNode } from './addSaveImageNode'; +import { addLinearUIOutputNode } from './addLinearUIOutputNode'; import { addSeamlessToLinearGraph } from './addSeamlessToLinearGraph'; import { addT2IAdaptersToLinearGraph } from './addT2IAdapterToLinearGraph'; import { addVAEToGraph } from './addVAEToGraph'; @@ -234,20 +234,24 @@ export const buildLinearTextToImageGraph = ( ], }; - addCoreMetadataNode(graph, { - generation_mode: 'txt2img', - cfg_scale, - height, - width, - positive_prompt: positivePrompt, - negative_prompt: negativePrompt, - model, - seed, - steps, - rand_device: use_cpu ? 'cpu' : 'cuda', - scheduler, - clip_skip: clipSkip, - }); + addCoreMetadataNode( + graph, + { + generation_mode: 'txt2img', + cfg_scale, + height, + width, + positive_prompt: positivePrompt, + negative_prompt: negativePrompt, + model, + seed, + steps, + rand_device: use_cpu ? 'cpu' : 'cuda', + scheduler, + clip_skip: clipSkip, + }, + LATENTS_TO_IMAGE + ); // Add Seamless To Graph if (seamlessXAxis || seamlessYAxis) { @@ -286,7 +290,7 @@ export const buildLinearTextToImageGraph = ( addWatermarkerToGraph(state, graph); } - addSaveImageNode(state, graph); + addLinearUIOutputNode(state, graph); return graph; }; diff --git a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/constants.ts b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/constants.ts index 811b2604b1..3839822133 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/constants.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/constants.ts @@ -9,7 +9,7 @@ export const LATENTS_TO_IMAGE_HRF_LR = 'latents_to_image_hrf_lr'; export const IMAGE_TO_LATENTS_HRF = 'image_to_latents_hrf'; export const RESIZE_HRF = 'resize_hrf'; export const ESRGAN_HRF = 'esrgan_hrf'; -export const SAVE_IMAGE = 'save_image'; +export const LINEAR_UI_OUTPUT = 'linear_ui_output'; export const NSFW_CHECKER = 'nsfw_checker'; export const WATERMARKER = 'invisible_watermark'; export const NOISE = 'noise'; diff --git a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/metadata.ts b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/metadata.ts index b673be9e4a..c80e1c80c6 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/metadata.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/metadata.ts @@ -1,11 +1,12 @@ import { NonNullableGraph } from 'features/nodes/types/types'; import { CoreMetadataInvocation } from 'services/api/types'; import { JsonObject } from 'type-fest'; -import { METADATA, SAVE_IMAGE } from './constants'; +import { METADATA } from './constants'; export const addCoreMetadataNode = ( graph: NonNullableGraph, - metadata: Partial + metadata: Partial, + nodeId: string ): void => { graph.nodes[METADATA] = { id: METADATA, @@ -19,7 +20,7 @@ export const addCoreMetadataNode = ( field: 'metadata', }, destination: { - node_id: SAVE_IMAGE, + node_id: nodeId, field: 'metadata', }, }); @@ -64,3 +65,21 @@ export const getHasMetadata = (graph: NonNullableGraph): boolean => { return Boolean(metadataNode); }; + +export const setMetadataReceivingNode = ( + graph: NonNullableGraph, + nodeId: string +) => { + graph.edges = graph.edges.filter((edge) => edge.source.node_id !== METADATA); + + graph.edges.push({ + source: { + node_id: METADATA, + field: 'metadata', + }, + destination: { + node_id: nodeId, + field: 'metadata', + }, + }); +}; diff --git a/invokeai/frontend/web/src/features/nodes/util/parseSchema.ts b/invokeai/frontend/web/src/features/nodes/util/parseSchema.ts index 7c6f4e638f..8737fc52b9 100644 --- a/invokeai/frontend/web/src/features/nodes/util/parseSchema.ts +++ b/invokeai/frontend/web/src/features/nodes/util/parseSchema.ts @@ -19,7 +19,7 @@ const RESERVED_INPUT_FIELD_NAMES = ['id', 'type', 'use_cache']; const RESERVED_OUTPUT_FIELD_NAMES = ['type']; const RESERVED_FIELD_TYPES = ['IsIntermediate']; -const invocationDenylist: AnyInvocationType[] = ['graph']; +const invocationDenylist: AnyInvocationType[] = ['graph', 'linear_ui_output']; const isReservedInputField = (nodeType: string, fieldName: string) => { if (RESERVED_INPUT_FIELD_NAMES.includes(fieldName)) { diff --git a/invokeai/frontend/web/src/services/api/schema.d.ts b/invokeai/frontend/web/src/services/api/schema.d.ts index 81bfed5a1a..6788835152 100644 --- a/invokeai/frontend/web/src/services/api/schema.d.ts +++ b/invokeai/frontend/web/src/services/api/schema.d.ts @@ -2127,7 +2127,7 @@ export type components = { * Hrf Enabled * @description Whether or not high resolution fix was enabled. */ - hrf_enabled?: number | null; + hrf_enabled?: boolean | null; /** * Hrf Method * @description The high resolution fix upscale method. @@ -3216,7 +3216,7 @@ export type components = { * @description The nodes in this graph */ nodes?: { - [key: string]: components["schemas"]["GraphInvocation"] | components["schemas"]["MultiplyInvocation"] | components["schemas"]["InfillTileInvocation"] | components["schemas"]["CannyImageProcessorInvocation"] | components["schemas"]["TileResamplerProcessorInvocation"] | components["schemas"]["FaceIdentifierInvocation"] | components["schemas"]["MaskCombineInvocation"] | components["schemas"]["NormalbaeImageProcessorInvocation"] | components["schemas"]["StringReplaceInvocation"] | components["schemas"]["OnnxModelLoaderInvocation"] | components["schemas"]["SegmentAnythingProcessorInvocation"] | components["schemas"]["FreeUInvocation"] | components["schemas"]["IntegerMathInvocation"] | components["schemas"]["StringCollectionInvocation"] | components["schemas"]["DenoiseLatentsInvocation"] | components["schemas"]["LatentsCollectionInvocation"] | components["schemas"]["SeamlessModeInvocation"] | components["schemas"]["RangeOfSizeInvocation"] | components["schemas"]["VaeLoaderInvocation"] | components["schemas"]["StringInvocation"] | components["schemas"]["IntegerInvocation"] | components["schemas"]["FaceMaskInvocation"] | components["schemas"]["SubtractInvocation"] | components["schemas"]["FloatLinearRangeInvocation"] | components["schemas"]["StringSplitNegInvocation"] | components["schemas"]["ColorCorrectInvocation"] | components["schemas"]["LaMaInfillInvocation"] | components["schemas"]["ImageWatermarkInvocation"] | components["schemas"]["IPAdapterInvocation"] | components["schemas"]["ImageInvocation"] | components["schemas"]["ColorMapImageProcessorInvocation"] | components["schemas"]["TestInvocation"] | components["schemas"]["MetadataItemInvocation"] | components["schemas"]["IterateInvocation"] | components["schemas"]["MlsdImageProcessorInvocation"] | components["schemas"]["FloatToIntegerInvocation"] | components["schemas"]["BooleanInvocation"] | components["schemas"]["ConditioningCollectionInvocation"] | components["schemas"]["MediapipeFaceProcessorInvocation"] | components["schemas"]["CV2InfillInvocation"] | components["schemas"]["FloatInvocation"] | components["schemas"]["CvInpaintInvocation"] | components["schemas"]["InfillColorInvocation"] | components["schemas"]["CompelInvocation"] | components["schemas"]["CollectInvocation"] | components["schemas"]["MaskFromAlphaInvocation"] | components["schemas"]["BlankImageInvocation"] | components["schemas"]["ClipSkipInvocation"] | components["schemas"]["SDXLRefinerCompelPromptInvocation"] | components["schemas"]["ScaleLatentsInvocation"] | components["schemas"]["ImageLerpInvocation"] | components["schemas"]["NoiseInvocation"] | components["schemas"]["LatentsInvocation"] | components["schemas"]["MaskEdgeInvocation"] | components["schemas"]["ShowImageInvocation"] | components["schemas"]["LatentsToImageInvocation"] | components["schemas"]["ONNXPromptInvocation"] | components["schemas"]["RoundInvocation"] | components["schemas"]["ImageCropInvocation"] | components["schemas"]["LineartImageProcessorInvocation"] | components["schemas"]["ContentShuffleImageProcessorInvocation"] | components["schemas"]["StringJoinThreeInvocation"] | components["schemas"]["ImageResizeInvocation"] | components["schemas"]["IntegerCollectionInvocation"] | components["schemas"]["ImageCollectionInvocation"] | components["schemas"]["TestInvocation2"] | components["schemas"]["PidiImageProcessorInvocation"] | components["schemas"]["MergeMetadataInvocation"] | components["schemas"]["StringJoinInvocation"] | components["schemas"]["ImageBlurInvocation"] | components["schemas"]["OpenposeImageProcessorInvocation"] | components["schemas"]["SchedulerInvocation"] | components["schemas"]["RandomIntInvocation"] | components["schemas"]["AddInvocation"] | components["schemas"]["FloatCollectionInvocation"] | components["schemas"]["ImageToLatentsInvocation"] | components["schemas"]["ESRGANInvocation"] | components["schemas"]["ColorInvocation"] | components["schemas"]["TestInvocation3"] | components["schemas"]["ONNXLatentsToImageInvocation"] | components["schemas"]["BlendLatentsInvocation"] | components["schemas"]["ControlNetInvocation"] | components["schemas"]["PromptsFromFileInvocation"] | components["schemas"]["InfillPatchMatchInvocation"] | components["schemas"]["DivideInvocation"] | components["schemas"]["DynamicPromptInvocation"] | components["schemas"]["LeresImageProcessorInvocation"] | components["schemas"]["ONNXTextToLatentsInvocation"] | components["schemas"]["ZoeDepthImageProcessorInvocation"] | components["schemas"]["StringSplitInvocation"] | components["schemas"]["FloatMathInvocation"] | components["schemas"]["HedImageProcessorInvocation"] | components["schemas"]["CoreMetadataInvocation"] | components["schemas"]["ImageInverseLerpInvocation"] | components["schemas"]["RangeInvocation"] | components["schemas"]["SDXLCompelPromptInvocation"] | components["schemas"]["MidasDepthImageProcessorInvocation"] | components["schemas"]["ImageChannelInvocation"] | components["schemas"]["ImageMultiplyInvocation"] | components["schemas"]["ImagePasteInvocation"] | components["schemas"]["BooleanCollectionInvocation"] | components["schemas"]["RandomFloatInvocation"] | components["schemas"]["ResizeLatentsInvocation"] | components["schemas"]["ImageNSFWBlurInvocation"] | components["schemas"]["LoraLoaderInvocation"] | components["schemas"]["MainModelLoaderInvocation"] | components["schemas"]["LineartAnimeImageProcessorInvocation"] | components["schemas"]["ConditioningInvocation"] | components["schemas"]["SDXLModelLoaderInvocation"] | components["schemas"]["SaveImageInvocation"] | components["schemas"]["StepParamEasingInvocation"] | components["schemas"]["RandomRangeInvocation"] | components["schemas"]["T2IAdapterInvocation"] | components["schemas"]["ImageChannelOffsetInvocation"] | components["schemas"]["FaceOffInvocation"] | components["schemas"]["ImageConvertInvocation"] | components["schemas"]["ImageHueAdjustmentInvocation"] | components["schemas"]["ImageScaleInvocation"] | components["schemas"]["CreateDenoiseMaskInvocation"] | components["schemas"]["SDXLRefinerModelLoaderInvocation"] | components["schemas"]["MetadataInvocation"] | components["schemas"]["ImageChannelMultiplyInvocation"] | components["schemas"]["SDXLLoraLoaderInvocation"]; + [key: string]: components["schemas"]["ImageScaleInvocation"] | components["schemas"]["MaskCombineInvocation"] | components["schemas"]["ColorInvocation"] | components["schemas"]["ImageChannelOffsetInvocation"] | components["schemas"]["MergeMetadataInvocation"] | components["schemas"]["LatentsCollectionInvocation"] | components["schemas"]["ImageHueAdjustmentInvocation"] | components["schemas"]["LatentsInvocation"] | components["schemas"]["ScaleLatentsInvocation"] | components["schemas"]["SDXLModelLoaderInvocation"] | components["schemas"]["SegmentAnythingProcessorInvocation"] | components["schemas"]["ResizeLatentsInvocation"] | components["schemas"]["DynamicPromptInvocation"] | components["schemas"]["DivideInvocation"] | components["schemas"]["FloatToIntegerInvocation"] | components["schemas"]["RandomIntInvocation"] | components["schemas"]["CV2InfillInvocation"] | components["schemas"]["InfillColorInvocation"] | components["schemas"]["SDXLRefinerModelLoaderInvocation"] | components["schemas"]["HedImageProcessorInvocation"] | components["schemas"]["CreateDenoiseMaskInvocation"] | components["schemas"]["FloatCollectionInvocation"] | components["schemas"]["CompelInvocation"] | components["schemas"]["LaMaInfillInvocation"] | components["schemas"]["SeamlessModeInvocation"] | components["schemas"]["BlankImageInvocation"] | components["schemas"]["MultiplyInvocation"] | components["schemas"]["StringReplaceInvocation"] | components["schemas"]["StringSplitNegInvocation"] | components["schemas"]["ContentShuffleImageProcessorInvocation"] | components["schemas"]["TestInvocation2"] | components["schemas"]["NoiseInvocation"] | components["schemas"]["ESRGANInvocation"] | components["schemas"]["TileResamplerProcessorInvocation"] | components["schemas"]["RandomRangeInvocation"] | components["schemas"]["PidiImageProcessorInvocation"] | components["schemas"]["MidasDepthImageProcessorInvocation"] | components["schemas"]["ImageWatermarkInvocation"] | components["schemas"]["FaceIdentifierInvocation"] | components["schemas"]["ColorMapImageProcessorInvocation"] | components["schemas"]["ONNXLatentsToImageInvocation"] | components["schemas"]["DenoiseLatentsInvocation"] | components["schemas"]["RoundInvocation"] | components["schemas"]["ShowImageInvocation"] | components["schemas"]["ImageCropInvocation"] | components["schemas"]["ConditioningInvocation"] | components["schemas"]["TestInvocation3"] | components["schemas"]["SDXLLoraLoaderInvocation"] | components["schemas"]["IntegerInvocation"] | components["schemas"]["RandomFloatInvocation"] | components["schemas"]["GraphInvocation"] | components["schemas"]["ImageResizeInvocation"] | components["schemas"]["ONNXTextToLatentsInvocation"] | components["schemas"]["FloatMathInvocation"] | components["schemas"]["ClipSkipInvocation"] | components["schemas"]["ColorCorrectInvocation"] | components["schemas"]["IPAdapterInvocation"] | components["schemas"]["BooleanInvocation"] | components["schemas"]["SDXLRefinerCompelPromptInvocation"] | components["schemas"]["FloatLinearRangeInvocation"] | components["schemas"]["FaceOffInvocation"] | components["schemas"]["ImageBlurInvocation"] | components["schemas"]["InfillPatchMatchInvocation"] | components["schemas"]["MaskEdgeInvocation"] | components["schemas"]["SubtractInvocation"] | components["schemas"]["FloatInvocation"] | components["schemas"]["NormalbaeImageProcessorInvocation"] | components["schemas"]["MaskFromAlphaInvocation"] | components["schemas"]["MediapipeFaceProcessorInvocation"] | components["schemas"]["ImageLerpInvocation"] | components["schemas"]["VaeLoaderInvocation"] | components["schemas"]["RangeInvocation"] | components["schemas"]["LineartImageProcessorInvocation"] | components["schemas"]["StringCollectionInvocation"] | components["schemas"]["SaveImageInvocation"] | components["schemas"]["LatentsToImageInvocation"] | components["schemas"]["ImageToLatentsInvocation"] | components["schemas"]["SchedulerInvocation"] | components["schemas"]["SDXLCompelPromptInvocation"] | components["schemas"]["CvInpaintInvocation"] | components["schemas"]["AddInvocation"] | components["schemas"]["IntegerCollectionInvocation"] | components["schemas"]["CoreMetadataInvocation"] | components["schemas"]["ImageChannelMultiplyInvocation"] | components["schemas"]["BlendLatentsInvocation"] | components["schemas"]["StringJoinInvocation"] | components["schemas"]["StringInvocation"] | components["schemas"]["ImageInvocation"] | components["schemas"]["ImagePasteInvocation"] | components["schemas"]["FaceMaskInvocation"] | components["schemas"]["StringJoinThreeInvocation"] | components["schemas"]["IntegerMathInvocation"] | components["schemas"]["InfillTileInvocation"] | components["schemas"]["StringSplitInvocation"] | components["schemas"]["CollectInvocation"] | components["schemas"]["ConditioningCollectionInvocation"] | components["schemas"]["MetadataInvocation"] | components["schemas"]["ControlNetInvocation"] | components["schemas"]["BooleanCollectionInvocation"] | components["schemas"]["ImageNSFWBlurInvocation"] | components["schemas"]["CannyImageProcessorInvocation"] | components["schemas"]["IterateInvocation"] | components["schemas"]["ImageInverseLerpInvocation"] | components["schemas"]["LinearUIOutputInvocation"] | components["schemas"]["LineartAnimeImageProcessorInvocation"] | components["schemas"]["LeresImageProcessorInvocation"] | components["schemas"]["ONNXPromptInvocation"] | components["schemas"]["OpenposeImageProcessorInvocation"] | components["schemas"]["LoraLoaderInvocation"] | components["schemas"]["ImageCollectionInvocation"] | components["schemas"]["MlsdImageProcessorInvocation"] | components["schemas"]["ImageChannelInvocation"] | components["schemas"]["ImageMultiplyInvocation"] | components["schemas"]["PromptsFromFileInvocation"] | components["schemas"]["OnnxModelLoaderInvocation"] | components["schemas"]["T2IAdapterInvocation"] | components["schemas"]["StepParamEasingInvocation"] | components["schemas"]["RangeOfSizeInvocation"] | components["schemas"]["ImageConvertInvocation"] | components["schemas"]["TestInvocation"] | components["schemas"]["MainModelLoaderInvocation"] | components["schemas"]["FreeUInvocation"] | components["schemas"]["MetadataItemInvocation"] | components["schemas"]["ZoeDepthImageProcessorInvocation"]; }; /** * Edges @@ -3253,7 +3253,7 @@ export type components = { * @description The results of node executions */ results: { - [key: string]: components["schemas"]["IntegerOutput"] | components["schemas"]["LatentsCollectionOutput"] | components["schemas"]["ColorCollectionOutput"] | components["schemas"]["StringOutput"] | components["schemas"]["SDXLRefinerModelLoaderOutput"] | components["schemas"]["ImageCollectionOutput"] | components["schemas"]["FloatCollectionOutput"] | components["schemas"]["IterateInvocationOutput"] | components["schemas"]["ONNXModelLoaderOutput"] | components["schemas"]["DenoiseMaskOutput"] | components["schemas"]["ControlOutput"] | components["schemas"]["SDXLModelLoaderOutput"] | components["schemas"]["LoraLoaderOutput"] | components["schemas"]["ConditioningOutput"] | components["schemas"]["SeamlessModeOutput"] | components["schemas"]["FaceOffOutput"] | components["schemas"]["ModelLoaderOutput"] | components["schemas"]["StringPosNegOutput"] | components["schemas"]["UNetOutput"] | components["schemas"]["ImageOutput"] | components["schemas"]["GraphInvocationOutput"] | components["schemas"]["LatentsOutput"] | components["schemas"]["StringCollectionOutput"] | components["schemas"]["SDXLLoraLoaderOutput"] | components["schemas"]["ColorOutput"] | components["schemas"]["ConditioningCollectionOutput"] | components["schemas"]["ClipSkipInvocationOutput"] | components["schemas"]["IPAdapterOutput"] | components["schemas"]["CLIPOutput"] | components["schemas"]["IntegerCollectionOutput"] | components["schemas"]["FaceMaskOutput"] | components["schemas"]["NoiseOutput"] | components["schemas"]["CollectInvocationOutput"] | components["schemas"]["SchedulerOutput"] | components["schemas"]["T2IAdapterOutput"] | components["schemas"]["MetadataOutput"] | components["schemas"]["MetadataItemOutput"] | components["schemas"]["BooleanOutput"] | components["schemas"]["FloatOutput"] | components["schemas"]["BooleanCollectionOutput"] | components["schemas"]["String2Output"] | components["schemas"]["VAEOutput"]; + [key: string]: components["schemas"]["SeamlessModeOutput"] | components["schemas"]["LatentsCollectionOutput"] | components["schemas"]["IntegerOutput"] | components["schemas"]["String2Output"] | components["schemas"]["ImageOutput"] | components["schemas"]["CollectInvocationOutput"] | components["schemas"]["T2IAdapterOutput"] | components["schemas"]["VAEOutput"] | components["schemas"]["DenoiseMaskOutput"] | components["schemas"]["IntegerCollectionOutput"] | components["schemas"]["CLIPOutput"] | components["schemas"]["FloatOutput"] | components["schemas"]["StringOutput"] | components["schemas"]["ColorOutput"] | components["schemas"]["MetadataItemOutput"] | components["schemas"]["GraphInvocationOutput"] | components["schemas"]["ConditioningCollectionOutput"] | components["schemas"]["StringPosNegOutput"] | components["schemas"]["NoiseOutput"] | components["schemas"]["IterateInvocationOutput"] | components["schemas"]["SDXLModelLoaderOutput"] | components["schemas"]["FaceOffOutput"] | components["schemas"]["SDXLRefinerModelLoaderOutput"] | components["schemas"]["FaceMaskOutput"] | components["schemas"]["SchedulerOutput"] | components["schemas"]["BooleanOutput"] | components["schemas"]["FloatCollectionOutput"] | components["schemas"]["LatentsOutput"] | components["schemas"]["BooleanCollectionOutput"] | components["schemas"]["SDXLLoraLoaderOutput"] | components["schemas"]["ClipSkipInvocationOutput"] | components["schemas"]["MetadataOutput"] | components["schemas"]["ModelLoaderOutput"] | components["schemas"]["IPAdapterOutput"] | components["schemas"]["LoraLoaderOutput"] | components["schemas"]["ImageCollectionOutput"] | components["schemas"]["StringCollectionOutput"] | components["schemas"]["UNetOutput"] | components["schemas"]["ColorCollectionOutput"] | components["schemas"]["ControlOutput"] | components["schemas"]["ONNXModelLoaderOutput"] | components["schemas"]["ConditioningOutput"]; }; /** * Errors @@ -5243,6 +5243,43 @@ export type components = { */ type: "leres_image_processor"; }; + /** + * Linear UI Image Output + * @description Handles Linear UI Image Outputting tasks. + */ + LinearUIOutputInvocation: { + /** @description Optional metadata to be saved with the image */ + metadata?: components["schemas"]["MetadataField"] | null; + /** @description Optional workflow to be saved with the image */ + workflow?: components["schemas"]["WorkflowField"] | null; + /** + * 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 false + */ + use_cache?: boolean; + /** @description The image to process */ + image?: components["schemas"]["ImageField"]; + /** @description The board to save the image to */ + board?: components["schemas"]["BoardField"] | null; + /** + * type + * @default linear_ui_output + * @constant + */ + type: "linear_ui_output"; + }; /** * Lineart Anime Processor * @description Applies line art anime processing to image @@ -9664,12 +9701,6 @@ export type components = { /** Ui Order */ ui_order: number | null; }; - /** - * StableDiffusionXLModelFormat - * @description An enumeration. - * @enum {string} - */ - StableDiffusionXLModelFormat: "checkpoint" | "diffusers"; /** * StableDiffusionOnnxModelFormat * @description An enumeration. @@ -9677,41 +9708,47 @@ export type components = { */ StableDiffusionOnnxModelFormat: "olive" | "onnx"; /** - * T2IAdapterModelFormat + * ControlNetModelFormat * @description An enumeration. * @enum {string} */ - T2IAdapterModelFormat: "diffusers"; - /** - * StableDiffusion1ModelFormat - * @description An enumeration. - * @enum {string} - */ - StableDiffusion1ModelFormat: "checkpoint" | "diffusers"; - /** - * StableDiffusion2ModelFormat - * @description An enumeration. - * @enum {string} - */ - StableDiffusion2ModelFormat: "checkpoint" | "diffusers"; + ControlNetModelFormat: "checkpoint" | "diffusers"; /** * CLIPVisionModelFormat * @description An enumeration. * @enum {string} */ CLIPVisionModelFormat: "diffusers"; + /** + * T2IAdapterModelFormat + * @description An enumeration. + * @enum {string} + */ + T2IAdapterModelFormat: "diffusers"; + /** + * StableDiffusionXLModelFormat + * @description An enumeration. + * @enum {string} + */ + StableDiffusionXLModelFormat: "checkpoint" | "diffusers"; + /** + * StableDiffusion2ModelFormat + * @description An enumeration. + * @enum {string} + */ + StableDiffusion2ModelFormat: "checkpoint" | "diffusers"; + /** + * StableDiffusion1ModelFormat + * @description An enumeration. + * @enum {string} + */ + StableDiffusion1ModelFormat: "checkpoint" | "diffusers"; /** * IPAdapterModelFormat * @description An enumeration. * @enum {string} */ IPAdapterModelFormat: "invokeai"; - /** - * ControlNetModelFormat - * @description An enumeration. - * @enum {string} - */ - ControlNetModelFormat: "checkpoint" | "diffusers"; }; responses: never; parameters: never; diff --git a/invokeai/frontend/web/src/services/api/types.ts b/invokeai/frontend/web/src/services/api/types.ts index 9038374912..ce3e75a584 100644 --- a/invokeai/frontend/web/src/services/api/types.ts +++ b/invokeai/frontend/web/src/services/api/types.ts @@ -142,7 +142,7 @@ export type DivideInvocation = s['DivideInvocation']; export type ImageNSFWBlurInvocation = s['ImageNSFWBlurInvocation']; export type ImageWatermarkInvocation = s['ImageWatermarkInvocation']; export type SeamlessModeInvocation = s['SeamlessModeInvocation']; -export type SaveImageInvocation = s['SaveImageInvocation']; +export type LinearUIOutputInvocation = s['LinearUIOutputInvocation']; export type MetadataInvocation = s['MetadataInvocation']; export type CoreMetadataInvocation = s['CoreMetadataInvocation']; export type MetadataItemInvocation = s['MetadataItemInvocation']; From 230dfdb9ad68b0e738bb25969b56374a4e6f1aa3 Mon Sep 17 00:00:00 2001 From: Jonathan <34005131+JPPhoto@users.noreply.github.com> Date: Thu, 16 Nov 2023 14:25:06 -0600 Subject: [PATCH 4/5] Added unsharp mask node to communityNodes.md --- docs/nodes/communityNodes.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/nodes/communityNodes.md b/docs/nodes/communityNodes.md index d24873b24c..7732d2c25f 100644 --- a/docs/nodes/communityNodes.md +++ b/docs/nodes/communityNodes.md @@ -32,6 +32,7 @@ To use a community workflow, download the the `.json` node graph file and load i + [Size Stepper Nodes](#size-stepper-nodes) + [Text font to Image](#text-font-to-image) + [Thresholding](#thresholding) + + [Unsharp Mask](#unsharp-mask) + [XY Image to Grid and Images to Grids nodes](#xy-image-to-grid-and-images-to-grids-nodes) - [Example Node Template](#example-node-template) - [Disclaimer](#disclaimer) @@ -316,6 +317,13 @@ Highlights/Midtones/Shadows (with LUT blur enabled): +-------------------------------- +### Unsharp Mask + +**Description:** Applies an unsharp mask filter to an image, preserving its alpha channel in the process. + +**Node Link:** https://github.com/JPPhoto/unsharp-mask-node + -------------------------------- ### XY Image to Grid and Images to Grids nodes From 91ef24e15cb74ddef40cfc24281485a691b801ec Mon Sep 17 00:00:00 2001 From: psychedelicious <4822129+psychedelicious@users.noreply.github.com> Date: Fri, 17 Nov 2023 07:32:04 +1100 Subject: [PATCH 5/5] fix(nodes,ui): fix missed/canvas temp images in gallery Resolves two bugs introduced in #5106: 1. Linear UI images sometimes didn't make it to the gallery. This was a race condition. The VAE decode nodes were handled by the socketInvocationComplete listener. At that moment, the image was marked as intermediate. Immediately after this node was handled, a LinearUIOutputInvocation, introduced in #5106, was handled by socketInvocationComplete. This node internally sets changed the image to not intermediate. During the handling of that socketInvocationComplete, RTK Query would sometimes use its cache instead of retrieving the image DTO again. The result is that the UI never got the message that the image was not intermediate, so it wasn't added to the gallery. This is resolved by refactoring the socketInvocationComplete listener. We now skip the gallery processing for linear UI events, except for the LinearUIOutputInvocation. Images now always make it to the gallery, and network requests to get image DTOs are substantially reduced. 2. Canvas temp images always went into the gallery The LinearUIOutputInvocation was always setting its image's is_intermediate to false. This included all canvas images and resulted in all canvas temp images going to gallery. This is resolved by making LinearUIOutputInvocation set is_intermediate based on `self.is_intermediate`. The behaviour now more or less mirroring the behaviour of is_intermediate on other image-outputting nodes, except it doesn't save the image again - only changes it. One extra minor change - LinearUIOutputInvocation only changes is_intermediate if it differs from the image's current setting. Very minor optimisation. --- invokeai/app/invocations/image.py | 7 +++-- .../socketio/socketInvocationComplete.ts | 28 +++++++++++++------ .../graphBuilders/buildAdHocUpscaleGraph.ts | 2 +- .../nodes/util/graphBuilders/constants.ts | 28 ++++++++++++++++++- 4 files changed, 53 insertions(+), 12 deletions(-) diff --git a/invokeai/app/invocations/image.py b/invokeai/app/invocations/image.py index fb59fdf7fd..87e8392402 100644 --- a/invokeai/app/invocations/image.py +++ b/invokeai/app/invocations/image.py @@ -1024,7 +1024,7 @@ class SaveImageInvocation(BaseInvocation, WithWorkflow, WithMetadata): title="Linear UI Image Output", tags=["primitives", "image"], category="primitives", - version="1.0.0", + version="1.0.1", use_cache=False, ) class LinearUIOutputInvocation(BaseInvocation, WithWorkflow, WithMetadata): @@ -1039,7 +1039,10 @@ class LinearUIOutputInvocation(BaseInvocation, WithWorkflow, WithMetadata): if self.board: context.services.board_images.add_image_to_board(self.board.board_id, self.image.image_name) - context.services.images.update(self.image.image_name, changes=ImageRecordChanges(is_intermediate=False)) + if image_dto.is_intermediate != self.is_intermediate: + context.services.images.update( + self.image.image_name, changes=ImageRecordChanges(is_intermediate=self.is_intermediate) + ) return ImageOutput( image=ImageField(image_name=self.image.image_name), diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketInvocationComplete.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketInvocationComplete.ts index 007a829bf9..cfd69ce9bc 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketInvocationComplete.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketInvocationComplete.ts @@ -7,7 +7,10 @@ import { imageSelected, } from 'features/gallery/store/gallerySlice'; import { IMAGE_CATEGORIES } from 'features/gallery/store/types'; -import { CANVAS_OUTPUT } from 'features/nodes/util/graphBuilders/constants'; +import { + LINEAR_UI_OUTPUT, + nodeIDDenyList, +} from 'features/nodes/util/graphBuilders/constants'; import { boardsApi } from 'services/api/endpoints/boards'; import { imagesApi } from 'services/api/endpoints/images'; import { isImageOutput } from 'services/api/guards'; @@ -19,7 +22,7 @@ import { import { startAppListening } from '../..'; // These nodes output an image, but do not actually *save* an image, so we don't want to handle the gallery logic on them -const nodeDenylist = ['load_image', 'image']; +const nodeTypeDenylist = ['load_image', 'image']; export const addInvocationCompleteEventListener = () => { startAppListening({ @@ -32,22 +35,31 @@ export const addInvocationCompleteEventListener = () => { `Invocation complete (${action.payload.data.node.type})` ); - const { result, node, queue_batch_id } = data; + const { result, node, queue_batch_id, source_node_id } = data; // This complete event has an associated image output - if (isImageOutput(result) && !nodeDenylist.includes(node.type)) { + if ( + isImageOutput(result) && + !nodeTypeDenylist.includes(node.type) && + !nodeIDDenyList.includes(source_node_id) + ) { const { image_name } = result.image; const { canvas, gallery } = getState(); // This populates the `getImageDTO` cache - const imageDTO = await dispatch( - imagesApi.endpoints.getImageDTO.initiate(image_name) - ).unwrap(); + const imageDTORequest = dispatch( + imagesApi.endpoints.getImageDTO.initiate(image_name, { + forceRefetch: true, + }) + ); + + const imageDTO = await imageDTORequest.unwrap(); + imageDTORequest.unsubscribe(); // Add canvas images to the staging area if ( canvas.batchIds.includes(queue_batch_id) && - [CANVAS_OUTPUT].includes(data.source_node_id) + [LINEAR_UI_OUTPUT].includes(data.source_node_id) ) { dispatch(addImageToStagingArea(imageDTO)); } diff --git a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildAdHocUpscaleGraph.ts b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildAdHocUpscaleGraph.ts index 73551202b8..8331c81eb3 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildAdHocUpscaleGraph.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/buildAdHocUpscaleGraph.ts @@ -6,7 +6,7 @@ import { Graph, LinearUIOutputInvocation, } from 'services/api/types'; -import { REALESRGAN as ESRGAN, LINEAR_UI_OUTPUT } from './constants'; +import { ESRGAN, LINEAR_UI_OUTPUT } from './constants'; import { addCoreMetadataNode, upsertMetadata } from './metadata'; type Arg = { diff --git a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/constants.ts b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/constants.ts index 3839822133..c2d6ac041c 100644 --- a/invokeai/frontend/web/src/features/nodes/util/graphBuilders/constants.ts +++ b/invokeai/frontend/web/src/features/nodes/util/graphBuilders/constants.ts @@ -67,7 +67,7 @@ export const BATCH_PROMPT = 'batch_prompt'; export const BATCH_STYLE_PROMPT = 'batch_style_prompt'; export const METADATA_COLLECT = 'metadata_collect'; export const MERGE_METADATA = 'merge_metadata'; -export const REALESRGAN = 'esrgan'; +export const ESRGAN = 'esrgan'; export const DIVIDE = 'divide'; export const SCALE = 'scale_image'; export const SDXL_MODEL_LOADER = 'sdxl_model_loader'; @@ -82,6 +82,32 @@ export const SDXL_REFINER_INPAINT_CREATE_MASK = 'refiner_inpaint_create_mask'; export const SEAMLESS = 'seamless'; export const SDXL_REFINER_SEAMLESS = 'refiner_seamless'; +// these image-outputting nodes are from the linear UI and we should not handle the gallery logic on them +// instead, we wait for LINEAR_UI_OUTPUT node, and handle it like any other image-outputting node +export const nodeIDDenyList = [ + CANVAS_OUTPUT, + LATENTS_TO_IMAGE, + LATENTS_TO_IMAGE_HRF_HR, + NSFW_CHECKER, + WATERMARKER, + ESRGAN, + ESRGAN_HRF, + RESIZE_HRF, + LATENTS_TO_IMAGE_HRF_LR, + IMG2IMG_RESIZE, + INPAINT_IMAGE, + SCALED_INPAINT_IMAGE, + INPAINT_IMAGE_RESIZE_UP, + INPAINT_IMAGE_RESIZE_DOWN, + INPAINT_INFILL, + INPAINT_INFILL_RESIZE_DOWN, + INPAINT_FINAL_IMAGE, + INPAINT_CREATE_MASK, + INPAINT_MASK, + PASTE_IMAGE, + SCALE, +]; + // friendly graph ids export const TEXT_TO_IMAGE_GRAPH = 'text_to_image_graph'; export const IMAGE_TO_IMAGE_GRAPH = 'image_to_image_graph';