mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
Adds Save to Gallery button to staging toolbar
This commit is contained in:
parent
d27d92325d
commit
e1e978b423
@ -32,9 +32,10 @@ opt = Args()
|
|||||||
args = opt.parse_args()
|
args = opt.parse_args()
|
||||||
|
|
||||||
# Set the root directory for static files and relative paths
|
# Set the root directory for static files and relative paths
|
||||||
args.root_dir = os.path.expanduser(args.root_dir or '..')
|
args.root_dir = os.path.expanduser(args.root_dir or "..")
|
||||||
if not os.path.isabs(args.outdir):
|
if not os.path.isabs(args.outdir):
|
||||||
args.outdir=os.path.join(args.root_dir,args.outdir)
|
args.outdir = os.path.join(args.root_dir, args.outdir)
|
||||||
|
|
||||||
|
|
||||||
class InvokeAIWebServer:
|
class InvokeAIWebServer:
|
||||||
def __init__(self, generate, gfpgan, codeformer, esrgan) -> None:
|
def __init__(self, generate, gfpgan, codeformer, esrgan) -> None:
|
||||||
@ -80,7 +81,9 @@ class InvokeAIWebServer:
|
|||||||
socketio_args["cors_allowed_origins"] = opt.cors
|
socketio_args["cors_allowed_origins"] = opt.cors
|
||||||
|
|
||||||
self.app = Flask(
|
self.app = Flask(
|
||||||
__name__, static_url_path="", static_folder=os.path.join(args.root_dir,"frontend/dist")
|
__name__,
|
||||||
|
static_url_path="",
|
||||||
|
static_folder=os.path.join(args.root_dir, "frontend/dist"),
|
||||||
)
|
)
|
||||||
|
|
||||||
self.socketio = SocketIO(self.app, **socketio_args)
|
self.socketio = SocketIO(self.app, **socketio_args)
|
||||||
@ -308,6 +311,50 @@ class InvokeAIWebServer:
|
|||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
print("\n")
|
print("\n")
|
||||||
|
|
||||||
|
@socketio.on("requestSaveStagingAreaImageToGallery")
|
||||||
|
def save_temp_image_to_gallery(url):
|
||||||
|
try:
|
||||||
|
image_path = self.get_image_path_from_url(url)
|
||||||
|
new_path = os.path.join(self.result_path, os.path.basename(image_path))
|
||||||
|
shutil.copy2(image_path, new_path)
|
||||||
|
|
||||||
|
if os.path.splitext(new_path)[1] == ".png":
|
||||||
|
metadata = retrieve_metadata(new_path)
|
||||||
|
else:
|
||||||
|
metadata = {}
|
||||||
|
|
||||||
|
pil_image = Image.open(new_path)
|
||||||
|
|
||||||
|
(width, height) = pil_image.size
|
||||||
|
|
||||||
|
thumbnail_path = save_thumbnail(
|
||||||
|
pil_image, os.path.basename(new_path), self.thumbnail_image_path
|
||||||
|
)
|
||||||
|
|
||||||
|
image_array = [
|
||||||
|
{
|
||||||
|
"url": self.get_url_from_image_path(new_path),
|
||||||
|
"thumbnail": self.get_url_from_image_path(thumbnail_path),
|
||||||
|
"mtime": os.path.getmtime(new_path),
|
||||||
|
"metadata": metadata,
|
||||||
|
"width": width,
|
||||||
|
"height": height,
|
||||||
|
"category": "result",
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
socketio.emit(
|
||||||
|
"galleryImages",
|
||||||
|
{"images": image_array, "category": "result"},
|
||||||
|
)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self.socketio.emit("error", {"message": (str(e))})
|
||||||
|
print("\n")
|
||||||
|
|
||||||
|
traceback.print_exc()
|
||||||
|
print("\n")
|
||||||
|
|
||||||
@socketio.on("requestLatestImages")
|
@socketio.on("requestLatestImages")
|
||||||
def handle_request_latest_images(category, latest_mtime):
|
def handle_request_latest_images(category, latest_mtime):
|
||||||
try:
|
try:
|
||||||
@ -431,7 +478,7 @@ class InvokeAIWebServer:
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
except:
|
except:
|
||||||
print(f'>> Unable to load {path}')
|
print(f">> Unable to load {path}")
|
||||||
socketio.emit("error", {"message": f"Unable to load {path}"})
|
socketio.emit("error", {"message": f"Unable to load {path}"})
|
||||||
|
|
||||||
socketio.emit(
|
socketio.emit(
|
||||||
|
@ -3,7 +3,6 @@ import { GalleryCategory } from 'features/gallery/store/gallerySlice';
|
|||||||
import { InvokeTabName } from 'features/tabs/components/InvokeTabs';
|
import { InvokeTabName } from 'features/tabs/components/InvokeTabs';
|
||||||
import * as InvokeAI from 'app/invokeai';
|
import * as InvokeAI from 'app/invokeai';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* We can't use redux-toolkit's createSlice() to make these actions,
|
* We can't use redux-toolkit's createSlice() to make these actions,
|
||||||
* because they have no associated reducer. They only exist to dispatch
|
* because they have no associated reducer. They only exist to dispatch
|
||||||
@ -26,8 +25,6 @@ export const requestNewImages = createAction<GalleryCategory>(
|
|||||||
export const cancelProcessing = createAction<undefined>(
|
export const cancelProcessing = createAction<undefined>(
|
||||||
'socketio/cancelProcessing'
|
'socketio/cancelProcessing'
|
||||||
);
|
);
|
||||||
// export const uploadImage = createAction<InvokeAI.UploadImagePayload>('socketio/uploadImage');
|
|
||||||
// export const uploadMaskImage = createAction<File>('socketio/uploadMaskImage');
|
|
||||||
|
|
||||||
export const requestSystemConfig = createAction<undefined>(
|
export const requestSystemConfig = createAction<undefined>(
|
||||||
'socketio/requestSystemConfig'
|
'socketio/requestSystemConfig'
|
||||||
@ -36,3 +33,7 @@ export const requestSystemConfig = createAction<undefined>(
|
|||||||
export const requestModelChange = createAction<string>(
|
export const requestModelChange = createAction<string>(
|
||||||
'socketio/requestModelChange'
|
'socketio/requestModelChange'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const saveStagingAreaImageToGallery = createAction<string>(
|
||||||
|
'socketio/saveStagingAreaImageToGallery'
|
||||||
|
);
|
||||||
|
@ -171,6 +171,9 @@ const makeSocketIOEmitters = (
|
|||||||
dispatch(modelChangeRequested());
|
dispatch(modelChangeRequested());
|
||||||
socketio.emit('requestModelChange', modelName);
|
socketio.emit('requestModelChange', modelName);
|
||||||
},
|
},
|
||||||
|
emitSaveStagingAreaImageToGallery: (url: string) => {
|
||||||
|
socketio.emit('requestSaveStagingAreaImageToGallery', url)
|
||||||
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -58,6 +58,7 @@ export const socketioMiddleware = () => {
|
|||||||
emitCancelProcessing,
|
emitCancelProcessing,
|
||||||
emitRequestSystemConfig,
|
emitRequestSystemConfig,
|
||||||
emitRequestModelChange,
|
emitRequestModelChange,
|
||||||
|
emitSaveStagingAreaImageToGallery,
|
||||||
} = makeSocketIOEmitters(store, socketio);
|
} = makeSocketIOEmitters(store, socketio);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -163,6 +164,11 @@ export const socketioMiddleware = () => {
|
|||||||
emitRequestModelChange(action.payload);
|
emitRequestModelChange(action.payload);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case 'socketio/saveStagingAreaImageToGallery': {
|
||||||
|
emitSaveStagingAreaImageToGallery(action.payload);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
next(action);
|
next(action);
|
||||||
|
@ -10,6 +10,7 @@ import {
|
|||||||
FaCheck,
|
FaCheck,
|
||||||
FaEye,
|
FaEye,
|
||||||
FaEyeSlash,
|
FaEyeSlash,
|
||||||
|
FaSave,
|
||||||
FaTrash,
|
FaTrash,
|
||||||
} from 'react-icons/fa';
|
} from 'react-icons/fa';
|
||||||
import { canvasSelector } from 'features/canvas/store/canvasSelectors';
|
import { canvasSelector } from 'features/canvas/store/canvasSelectors';
|
||||||
@ -22,6 +23,7 @@ import {
|
|||||||
setShouldShowStagingOutline,
|
setShouldShowStagingOutline,
|
||||||
} from 'features/canvas/store/canvasSlice';
|
} from 'features/canvas/store/canvasSlice';
|
||||||
import { useHotkeys } from 'react-hotkeys-hook';
|
import { useHotkeys } from 'react-hotkeys-hook';
|
||||||
|
import { saveStagingAreaImageToGallery } from 'app/socketio/actions';
|
||||||
|
|
||||||
const selector = createSelector(
|
const selector = createSelector(
|
||||||
[canvasSelector],
|
[canvasSelector],
|
||||||
@ -151,6 +153,17 @@ const IAICanvasStagingAreaToolbar = () => {
|
|||||||
}
|
}
|
||||||
data-selected={true}
|
data-selected={true}
|
||||||
/>
|
/>
|
||||||
|
<IAIIconButton
|
||||||
|
tooltip="Save to Gallery"
|
||||||
|
aria-label="Save to Gallery"
|
||||||
|
icon={<FaSave />}
|
||||||
|
onClick={() =>
|
||||||
|
dispatch(
|
||||||
|
saveStagingAreaImageToGallery(currentStagingAreaImage.image.url)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
data-selected={true}
|
||||||
|
/>
|
||||||
<IAIIconButton
|
<IAIIconButton
|
||||||
tooltip="Discard All"
|
tooltip="Discard All"
|
||||||
aria-label="Discard All"
|
aria-label="Discard All"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user