diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/userInvokedCanvas.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/userInvokedCanvas.ts
index 2ef62aed7b..17b2eeed46 100644
--- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/userInvokedCanvas.ts
+++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/userInvokedCanvas.ts
@@ -40,7 +40,7 @@ export const addUserInvokedCanvasListener = () => {
const state = getState();
// Build canvas blobs
- const canvasBlobsAndImageData = await getCanvasData(state);
+ const canvasBlobsAndImageData = await getCanvasData(state.canvas);
if (!canvasBlobsAndImageData) {
log.error('Unable to create canvas data');
diff --git a/invokeai/frontend/web/src/features/canvas/components/IAICanvasStatusText.tsx b/invokeai/frontend/web/src/features/canvas/components/IAICanvasStatusText.tsx
index 69bf628a39..8c1dfbb86f 100644
--- a/invokeai/frontend/web/src/features/canvas/components/IAICanvasStatusText.tsx
+++ b/invokeai/frontend/web/src/features/canvas/components/IAICanvasStatusText.tsx
@@ -2,8 +2,8 @@ import { Box, Flex } from '@chakra-ui/react';
import { createSelector } from '@reduxjs/toolkit';
import { useAppSelector } from 'app/store/storeHooks';
import { canvasSelector } from 'features/canvas/store/canvasSelectors';
+import GenerationModeStatusText from 'features/parameters/components/Parameters/Canvas/GenerationModeStatusText';
import { isEqual } from 'lodash-es';
-
import { useTranslation } from 'react-i18next';
import roundToHundreth from '../util/roundToHundreth';
import IAICanvasStatusTextCursorPos from './IAICanvasStatusText/IAICanvasStatusTextCursorPos';
@@ -110,6 +110,7 @@ const IAICanvasStatusText = () => {
},
}}
>
+
{
}}
>
- ) => {
+ state.generationMode = action.payload;
+ },
},
extraReducers: (builder) => {
builder.addCase(sessionCanceled.pending, (state) => {
@@ -955,6 +959,7 @@ export const {
stagingAreaInitialized,
canvasSessionIdChanged,
setShouldAntialias,
+ generationModeChanged,
} = canvasSlice.actions;
export default canvasSlice.reducer;
diff --git a/invokeai/frontend/web/src/features/canvas/store/canvasTypes.ts b/invokeai/frontend/web/src/features/canvas/store/canvasTypes.ts
index 48d59395ab..ba85a7e132 100644
--- a/invokeai/frontend/web/src/features/canvas/store/canvasTypes.ts
+++ b/invokeai/frontend/web/src/features/canvas/store/canvasTypes.ts
@@ -168,4 +168,7 @@ export interface CanvasState {
stageDimensions: Dimensions;
stageScale: number;
tool: CanvasTool;
+ generationMode?: GenerationMode;
}
+
+export type GenerationMode = 'txt2img' | 'img2img' | 'inpaint' | 'outpaint';
diff --git a/invokeai/frontend/web/src/features/canvas/util/getCanvasData.ts b/invokeai/frontend/web/src/features/canvas/util/getCanvasData.ts
index d37ee7b8d0..855420f78a 100644
--- a/invokeai/frontend/web/src/features/canvas/util/getCanvasData.ts
+++ b/invokeai/frontend/web/src/features/canvas/util/getCanvasData.ts
@@ -1,6 +1,5 @@
import { logger } from 'app/logging/logger';
-import { RootState } from 'app/store/store';
-import { isCanvasMaskLine } from '../store/canvasTypes';
+import { CanvasState, isCanvasMaskLine } from '../store/canvasTypes';
import createMaskStage from './createMaskStage';
import { getCanvasBaseLayer, getCanvasStage } from './konvaInstanceProvider';
import { konvaNodeToBlob } from './konvaNodeToBlob';
@@ -9,7 +8,7 @@ import { konvaNodeToImageData } from './konvaNodeToImageData';
/**
* Gets Blob and ImageData objects for the base and mask layers
*/
-export const getCanvasData = async (state: RootState) => {
+export const getCanvasData = async (canvasState: CanvasState) => {
const log = logger('canvas');
const canvasBaseLayer = getCanvasBaseLayer();
@@ -26,7 +25,7 @@ export const getCanvasData = async (state: RootState) => {
boundingBoxDimensions,
isMaskEnabled,
shouldPreserveMaskedArea,
- } = state.canvas;
+ } = canvasState;
const boundingBox = {
...boundingBoxCoordinates,
diff --git a/invokeai/frontend/web/src/features/canvas/util/getCanvasGenerationMode.ts b/invokeai/frontend/web/src/features/canvas/util/getCanvasGenerationMode.ts
index 5b38ecf938..d3e8792690 100644
--- a/invokeai/frontend/web/src/features/canvas/util/getCanvasGenerationMode.ts
+++ b/invokeai/frontend/web/src/features/canvas/util/getCanvasGenerationMode.ts
@@ -2,11 +2,12 @@ import {
areAnyPixelsBlack,
getImageDataTransparency,
} from 'common/util/arrayBuffer';
+import { GenerationMode } from '../store/canvasTypes';
export const getCanvasGenerationMode = (
baseImageData: ImageData,
maskImageData: ImageData
-) => {
+): GenerationMode => {
const {
isPartiallyTransparent: baseIsPartiallyTransparent,
isFullyTransparent: baseIsFullyTransparent,
diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/GenerationModeStatusText.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/GenerationModeStatusText.tsx
new file mode 100644
index 0000000000..5c6bbd0ba3
--- /dev/null
+++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Canvas/GenerationModeStatusText.tsx
@@ -0,0 +1,55 @@
+import { Box } from '@chakra-ui/react';
+import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
+import { generationModeChanged } from 'features/canvas/store/canvasSlice';
+import { getCanvasData } from 'features/canvas/util/getCanvasData';
+import { getCanvasGenerationMode } from 'features/canvas/util/getCanvasGenerationMode';
+import { useDebounce } from 'react-use';
+
+const GENERATION_MODE_NAME_MAP = {
+ txt2img: 'Text to Image',
+ img2img: 'Image to Image',
+ inpaint: 'Inpaint',
+ outpaint: 'Inpaint',
+};
+
+export const useGenerationMode = () => {
+ const dispatch = useAppDispatch();
+ const canvasState = useAppSelector((state) => state.canvas);
+
+ useDebounce(
+ async () => {
+ // Build canvas blobs
+ const canvasBlobsAndImageData = await getCanvasData(canvasState);
+
+ if (!canvasBlobsAndImageData) {
+ return;
+ }
+
+ const { baseImageData, maskImageData } = canvasBlobsAndImageData;
+
+ // Determine the generation mode
+ const generationMode = getCanvasGenerationMode(
+ baseImageData,
+ maskImageData
+ );
+
+ dispatch(generationModeChanged(generationMode));
+ },
+ 1000,
+ [dispatch, canvasState, generationModeChanged]
+ );
+};
+
+const GenerationModeStatusText = () => {
+ const generationMode = useAppSelector((state) => state.canvas.generationMode);
+
+ useGenerationMode();
+
+ return (
+
+ Mode: {generationMode ? GENERATION_MODE_NAME_MAP[generationMode] : '...'}
+
+ );
+};
+
+export default GenerationModeStatusText;