diff --git a/docs/nodes/communityNodes.md b/docs/nodes/communityNodes.md
index f3b8af0425..46615e5ebd 100644
--- a/docs/nodes/communityNodes.md
+++ b/docs/nodes/communityNodes.md
@@ -14,6 +14,10 @@ To use a community workflow, download the the `.json` node graph file and load i
- Community Nodes
+ [Average Images](#average-images)
+ + [Clean Image Artifacts After Cut](#clean-image-artifacts-after-cut)
+ + [Close Color Mask](#close-color-mask)
+ + [Clothing Mask](#clothing-mask)
+ + [Contrast Limited Adaptive Histogram Equalization](#contrast-limited-adaptive-histogram-equalization)
+ [Depth Map from Wavefront OBJ](#depth-map-from-wavefront-obj)
+ [Film Grain](#film-grain)
+ [Generative Grammar-Based Prompt Nodes](#generative-grammar-based-prompt-nodes)
@@ -22,16 +26,22 @@ To use a community workflow, download the the `.json` node graph file and load i
+ [Halftone](#halftone)
+ [Ideal Size](#ideal-size)
+ [Image and Mask Composition Pack](#image-and-mask-composition-pack)
+ + [Image Dominant Color](#image-dominant-color)
+ [Image to Character Art Image Nodes](#image-to-character-art-image-nodes)
+ [Image Picker](#image-picker)
+ + [Image Resize Plus](#image-resize-plus)
+ [Load Video Frame](#load-video-frame)
+ [Make 3D](#make-3d)
+ + [Mask Operations](#mask-operations)
+ [Match Histogram](#match-histogram)
+ + [Negative Image](#negative-image)
+ [Oobabooga](#oobabooga)
+ [Prompt Tools](#prompt-tools)
+ [Remote Image](#remote-image)
+ + [Remove Background](#remove-background)
+ [Retroize](#retroize)
+ [Size Stepper Nodes](#size-stepper-nodes)
+ + [Simple Skin Detection](#simple-skin-detection)
+ [Text font to Image](#text-font-to-image)
+ [Thresholding](#thresholding)
+ [Unsharp Mask](#unsharp-mask)
@@ -48,6 +58,46 @@ To use a community workflow, download the the `.json` node graph file and load i
**Node Link:** https://github.com/JPPhoto/average-images-node
+--------------------------------
+### Clean Image Artifacts After Cut
+
+Description: Removes residual artifacts after an image is separated from its background.
+
+Node Link: https://github.com/VeyDlin/clean-artifact-after-cut-node
+
+View:
+
+
+--------------------------------
+### Close Color Mask
+
+Description: Generates a mask for images based on a closely matching color, useful for color-based selections.
+
+Node Link: https://github.com/VeyDlin/close-color-mask-node
+
+View:
+
+
+--------------------------------
+### Clothing Mask
+
+Description: Employs a U2NET neural network trained for the segmentation of clothing items in images.
+
+Node Link: https://github.com/VeyDlin/clothing-mask-node
+
+View:
+
+
+--------------------------------
+### Contrast Limited Adaptive Histogram Equalization
+
+Description: Enhances local image contrast using adaptive histogram equalization with contrast limiting.
+
+Node Link: https://github.com/VeyDlin/clahe-node
+
+View:
+
+
--------------------------------
### Depth Map from Wavefront OBJ
@@ -164,6 +214,16 @@ This includes 15 Nodes:
+--------------------------------
+### Image Dominant Color
+
+Description: Identifies and extracts the dominant color from an image using k-means clustering.
+
+Node Link: https://github.com/VeyDlin/image-dominant-color-node
+
+View:
+
+
--------------------------------
### Image to Character Art Image Nodes
@@ -185,6 +245,17 @@ This includes 15 Nodes:
**Node Link:** https://github.com/JPPhoto/image-picker-node
+--------------------------------
+### Image Resize Plus
+
+Description: Provides various image resizing options such as fill, stretch, fit, center, and crop.
+
+Node Link: https://github.com/VeyDlin/image-resize-plus-node
+
+View:
+
+
+
--------------------------------
### Load Video Frame
@@ -209,6 +280,16 @@ This includes 15 Nodes:
+--------------------------------
+### Mask Operations
+
+Description: Offers logical operations (OR, SUB, AND) for combining and manipulating image masks.
+
+Node Link: https://github.com/VeyDlin/mask-operations-node
+
+View:
+
+
--------------------------------
### Match Histogram
@@ -226,6 +307,16 @@ See full docs here: https://github.com/skunkworxdark/Prompt-tools-nodes/edit/mai
+--------------------------------
+### Negative Image
+
+Description: Creates a negative version of an image, effective for visual effects and mask inversion.
+
+Node Link: https://github.com/VeyDlin/negative-image-node
+
+View:
+
+
--------------------------------
### Oobabooga
@@ -289,6 +380,15 @@ See full docs here: https://github.com/skunkworxdark/Prompt-tools-nodes/edit/mai
**Node Link:** https://github.com/fieldOfView/InvokeAI-remote_image
+--------------------------------
+### Remove Background
+
+Description: An integration of the rembg package to remove backgrounds from images using multiple U2NET models.
+
+Node Link: https://github.com/VeyDlin/remove-background-node
+
+View:
+
--------------------------------
### Retroize
@@ -301,6 +401,17 @@ See full docs here: https://github.com/skunkworxdark/Prompt-tools-nodes/edit/mai
+--------------------------------
+### Simple Skin Detection
+
+Description: Detects skin in images based on predefined color thresholds.
+
+Node Link: https://github.com/VeyDlin/simple-skin-detection-node
+
+View:
+
+
+
--------------------------------
### Size Stepper Nodes
@@ -386,6 +497,7 @@ See full docs here: https://github.com/skunkworxdark/XYGrid_nodes/edit/main/READ
+
--------------------------------
### Example Node Template
diff --git a/invokeai/configs/INITIAL_MODELS.yaml b/invokeai/configs/INITIAL_MODELS.yaml
index 67fcad4055..c230665e3a 100644
--- a/invokeai/configs/INITIAL_MODELS.yaml
+++ b/invokeai/configs/INITIAL_MODELS.yaml
@@ -32,9 +32,9 @@ sd-1/main/Analog-Diffusion:
description: An SD-1.5 model trained on diverse analog photographs (2.13 GB)
repo_id: wavymulder/Analog-Diffusion
recommended: False
-sd-1/main/Deliberate:
+sd-1/main/Deliberate_v5:
description: Versatile model that produces detailed images up to 768px (4.27 GB)
- repo_id: XpucT/Deliberate
+ path: https://huggingface.co/XpucT/Deliberate/resolve/main/Deliberate_v5.safetensors
recommended: False
sd-1/main/Dungeons-and-Diffusion:
description: Dungeons & Dragons characters (2.13 GB)
diff --git a/invokeai/frontend/web/public/locales/de.json b/invokeai/frontend/web/public/locales/de.json
index b67663d6d2..d9b64f8fc6 100644
--- a/invokeai/frontend/web/public/locales/de.json
+++ b/invokeai/frontend/web/public/locales/de.json
@@ -99,7 +99,18 @@
"data": "Daten",
"safetensors": "Safetensors",
"outpaint": "outpaint",
- "details": "Details"
+ "details": "Details",
+ "format": "Format",
+ "unknown": "Unbekannt",
+ "folder": "Ordner",
+ "error": "Fehler",
+ "installed": "Installiert",
+ "ai": "KI",
+ "file": "Datei",
+ "somethingWentWrong": "Etwas ist schief gelaufen",
+ "copyError": "$t(gallery.copy) Fehler",
+ "input": "Eingabe",
+ "notInstalled": "Nicht $t(common.installed)"
},
"gallery": {
"generations": "Erzeugungen",
@@ -696,7 +707,9 @@
"menu": "Menü",
"loadMore": "Mehr laden",
"invokeProgressBar": "Invoke Fortschrittsanzeige",
- "mode": "Modus"
+ "mode": "Modus",
+ "resetUI": "$t(accessibility.reset) von UI",
+ "createIssue": "Ticket erstellen"
},
"boards": {
"autoAddBoard": "Automatisches Hinzufügen zum Ordner",
@@ -718,7 +731,9 @@
"deleteBoardOnly": "Nur Ordner löschen",
"deleteBoard": "Löschen Ordner",
"deleteBoardAndImages": "Löschen Ordner und Bilder",
- "deletedBoardsCannotbeRestored": "Gelöschte Ordner könnte nicht wiederhergestellt werden"
+ "deletedBoardsCannotbeRestored": "Gelöschte Ordner könnte nicht wiederhergestellt werden",
+ "movingImagesToBoard_one": "Verschiebe {{count}} Bild zu Ordner",
+ "movingImagesToBoard_other": "Verschiebe {{count}} Bilder in Ordner"
},
"controlnet": {
"showAdvanced": "Zeige Erweitert",
@@ -843,7 +858,7 @@
"cancelBatchSucceeded": "Stapel abgebrochen",
"cancelBatch": "Stapel stoppen",
"enqueueing": "Stapel in der Warteschlange",
- "queueMaxExceeded": "Maximum von {{max_queue_size}} Elementen erreicht, würde {{skip}} Elemente überspringen",
+ "queueMaxExceeded": "Maximum von {{max_queue_size}} Elementen erreicht, würde {{skip}} Elemente überspringen",
"cancelBatchFailed": "Problem beim Abbruch vom Stapel",
"clearQueueAlertDialog2": "bist du sicher die Warteschlange zu leeren?",
"pruneSucceeded": "{{item_count}} abgeschlossene Elemente aus der Warteschlange entfernt",
@@ -932,7 +947,8 @@
"embedding": {
"noMatchingEmbedding": "Keine passenden Embeddings",
"addEmbedding": "Embedding hinzufügen",
- "incompatibleModel": "Inkompatibles Basismodell:"
+ "incompatibleModel": "Inkompatibles Basismodell:",
+ "noEmbeddingsLoaded": "Kein Embedding geladen"
},
"nodes": {
"booleanPolymorphicDescription": "Eine Sammlung boolescher Werte.",
diff --git a/invokeai/frontend/web/public/locales/en.json b/invokeai/frontend/web/public/locales/en.json
index 8663815adb..948f24093b 100644
--- a/invokeai/frontend/web/public/locales/en.json
+++ b/invokeai/frontend/web/public/locales/en.json
@@ -161,6 +161,7 @@
"txt2img": "Text To Image",
"unifiedCanvas": "Unified Canvas",
"unknown": "Unknown",
+ "unknownError": "Unknown Error",
"upload": "Upload"
},
"controlnet": {
@@ -384,7 +385,9 @@
"deleteSelection": "Delete Selection",
"downloadSelection": "Download Selection",
"preparingDownload": "Preparing Download",
- "preparingDownloadFailed": "Problem Preparing Download"
+ "preparingDownloadFailed": "Problem Preparing Download",
+ "problemDeletingImages": "Problem Deleting Images",
+ "problemDeletingImagesDesc": "One or more images could not be deleted"
},
"hotkeys": {
"acceptStagingImage": {
diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/batchEnqueued.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/batchEnqueued.ts
index 62a661756b..99756cbadb 100644
--- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/batchEnqueued.ts
+++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/batchEnqueued.ts
@@ -3,7 +3,7 @@ import { logger } from 'app/logging/logger';
import { parseify } from 'common/util/serialize';
import { zPydanticValidationError } from 'features/system/store/zodSchemas';
import { t } from 'i18next';
-import { get, truncate, upperFirst } from 'lodash-es';
+import { truncate, upperFirst } from 'lodash-es';
import { queueApi } from 'services/api/endpoints/queue';
import { TOAST_OPTIONS, theme } from 'theme/theme';
import { startAppListening } from '..';
@@ -74,22 +74,11 @@ export const addBatchEnqueuedListener = () => {
),
});
});
- } else {
- let detail = 'Unknown Error';
- let duration = undefined;
- if (response.status === 403 && 'body' in response) {
- detail = get(response, 'body.detail', 'Unknown Error');
- } else if (response.status === 403 && 'error' in response) {
- detail = get(response, 'error.detail', 'Unknown Error');
- } else if (response.status === 403 && 'data' in response) {
- detail = get(response, 'data.detail', 'Unknown Error');
- duration = 15000;
- }
+ } else if (response.status !== 403) {
toast({
title: t('queue.batchFailedToQueue'),
+ description: t('common.unknownError'),
status: 'error',
- description: detail,
- ...(duration ? { duration } : {}),
});
}
logger('queue').error(
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 0966a8c86b..3d35caebf6 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
@@ -109,20 +109,9 @@ export const addControlNetImageProcessedListener = () => {
t('queue.graphFailedToQueue')
);
- // handle usage-related errors
if (error instanceof Object) {
if ('data' in error && 'status' in error) {
if (error.status === 403) {
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- const detail = (error.data as any)?.detail || 'Unknown Error';
- dispatch(
- addToast({
- title: t('queue.graphFailedToQueue'),
- status: 'error',
- description: detail,
- duration: 15000,
- })
- );
dispatch(pendingControlImagesCleared());
dispatch(controlAdapterImageChanged({ id, controlImage: null }));
return;
diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/upscaleRequested.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/upscaleRequested.ts
index 7dbb7d9fb1..1b4211087a 100644
--- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/upscaleRequested.ts
+++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/upscaleRequested.ts
@@ -75,31 +75,20 @@ export const addUpscaleRequestedListener = () => {
t('queue.graphFailedToQueue')
);
- // handle usage-related errors
- if (error instanceof Object) {
- if ('data' in error && 'status' in error) {
- if (error.status === 403) {
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- const detail = (error.data as any)?.detail || 'Unknown Error';
- dispatch(
- addToast({
- title: t('queue.graphFailedToQueue'),
- status: 'error',
- description: detail,
- duration: 15000,
- })
- );
- return;
- }
- }
+ if (
+ error instanceof Object &&
+ 'status' in error &&
+ error.status === 403
+ ) {
+ return;
+ } else {
+ dispatch(
+ addToast({
+ title: t('queue.graphFailedToQueue'),
+ status: 'error',
+ })
+ );
}
-
- dispatch(
- addToast({
- title: t('queue.graphFailedToQueue'),
- status: 'error',
- })
- );
}
},
});
diff --git a/invokeai/frontend/web/src/app/store/store.ts b/invokeai/frontend/web/src/app/store/store.ts
index 0e3634468b..0ea3829c66 100644
--- a/invokeai/frontend/web/src/app/store/store.ts
+++ b/invokeai/frontend/web/src/app/store/store.ts
@@ -33,6 +33,7 @@ import { actionsDenylist } from './middleware/devtools/actionsDenylist';
import { stateSanitizer } from './middleware/devtools/stateSanitizer';
import { listenerMiddleware } from './middleware/listenerMiddleware';
import { createStore as createIDBKeyValStore, get, set } from 'idb-keyval';
+import { authToastMiddleware } from 'services/api/authToastMiddleware';
const allReducers = {
canvas: canvasReducer,
@@ -107,6 +108,7 @@ export const createStore = (uniqueStoreKey?: string) =>
})
.concat(api.middleware)
.concat(dynamicMiddlewares)
+ .concat(authToastMiddleware)
.prepend(listenerMiddleware.middleware),
devTools: {
actionSanitizer,
diff --git a/invokeai/frontend/web/src/services/api/authToastMiddleware.ts b/invokeai/frontend/web/src/services/api/authToastMiddleware.ts
new file mode 100644
index 0000000000..0a8e257cc5
--- /dev/null
+++ b/invokeai/frontend/web/src/services/api/authToastMiddleware.ts
@@ -0,0 +1,26 @@
+import { isRejectedWithValue } from '@reduxjs/toolkit';
+import type { MiddlewareAPI, Middleware } from '@reduxjs/toolkit';
+import { addToast } from 'features/system/store/systemSlice';
+import { t } from 'i18next';
+
+export const authToastMiddleware: Middleware =
+ (api: MiddlewareAPI) => (next) => (action) => {
+ if (isRejectedWithValue(action)) {
+ if (action.payload.status === 403) {
+ const { dispatch } = api;
+ const customMessage =
+ action.payload.data.detail !== 'Forbidden'
+ ? action.payload.data.detail
+ : undefined;
+ dispatch(
+ addToast({
+ title: t('common.somethingWentWrong'),
+ status: 'error',
+ description: customMessage,
+ })
+ );
+ }
+ }
+
+ return next(action);
+ };
diff --git a/invokeai/frontend/web/src/services/api/endpoints/images.ts b/invokeai/frontend/web/src/services/api/endpoints/images.ts
index 75b1bb771d..e261402837 100644
--- a/invokeai/frontend/web/src/services/api/endpoints/images.ts
+++ b/invokeai/frontend/web/src/services/api/endpoints/images.ts
@@ -27,6 +27,8 @@ import {
imagesSelectors,
} from 'services/api/util';
import { boardsApi } from './boards';
+import { addToast } from 'features/system/store/systemSlice';
+import { t } from 'i18next';
export const imagesApi = api.injectEndpoints({
endpoints: (build) => ({
@@ -208,6 +210,16 @@ export const imagesApi = api.injectEndpoints({
try {
const { data } = await queryFulfilled;
+ if (data.deleted_images.length < imageDTOs.length) {
+ dispatch(
+ addToast({
+ title: t('gallery.problemDeletingImages'),
+ description: t('gallery.problemDeletingImagesDesc'),
+ status: 'warning',
+ })
+ );
+ }
+
// convert to an object so we can access the successfully delete image DTOs by name
const groupedImageDTOs = keyBy(imageDTOs, 'image_name');